Sort a linked list - c

want to sort a linked list, but my code doesnt want to:)
Here it is:
void swap(element *p,element*q) {
int aux;
aux=p->info;
p->info=q->info;
q->info=aux;
}
void ordonare(element *lista) {
element *p,*q;
for(p=lista; p!=NULL; p=p->urmator) {
if(p->info>p->urmator->info) {
swap(p,p->urmator);
}
}
}
If this works, it will only sort the values, without changing the nodes' positions.
I can't seem to find the bug here, and I would appreciate if you could also indicate the solution where the nodes will change their positions.
Thanks,
Radu
UPDATE
the code above works, but as #Daniel.S mentioned, it only does one iteration through the list.
What conditions am I supposed to put in order to iterate until it is sorted?
Thanks!!:)

Look up merge sort, it is perfect for lists and easy to implement. That link has an example implementation:
Merge sort is often the best choice for sorting a linked list: in this situation it is relatively easy to implement a merge sort in such a way that it requires only Θ(1) extra space, and the slow random-access performance of a linked list makes some other algorithms (such as quicksort) perform poorly, and others (such as heapsort) completely impossible.

Your sorting algorithm is not complete. You're missing parts in the loop. One loop iteration over the list is not enough. Example:
You have the list {3,2,1}. If you sort it with your algorithm, it will first compare 3 and 2 and swap them, then you get
{2,3,1} it will then compare 3 and 1 and swap those, too. Then you get {2,1,3}. Your algorithm finishes here, but the list isn't sorted yet.
Depending on the algorithm you want to implement (e.g. bubble sort), you have to add additional code.
What algorithm do you want to implement?

Related

Implementing Intelligent design sort

This might be frivolous question, so please have understanding for my poor soul.
After reading this article about Intelligent Design sort (http://www.dangermouse.net/esoteric/intelligentdesignsort.html) which is in no way made to be serious in any way, I started wondering whether this could be possible.
An excerpt from article says:
The probability of the original input list being in the exact order it's in is 1/(n!). There is such a small likelihood of this that it's clearly absurd to say that this happened by chance, so it must have been consciously put in that order by an intelligent Sorter.
Let's for a second forget about intelligent Sorter, and think about possibility that random occurrences of members in array are in some way sorted. Our algorithm should determine the pattern without changing array's structure.
Is there any way to do this? Speed is not a requirement.
The implementation is very easy actually. The entire point of the article is that you don't actually sort anything. In other words, a correct implementation is a simple NOP. As my preferred language is Java, I'll show a simple in-place implementation in Java as a lambda function:
list->{}
Funny article, I had a good laugh.
If the only thing you're interested in is that whether your List is sorted, then you could simply keep an internal sorted flag (defaulted to true for an empty list) and override your add() method to check if the element you're adding fits the ordering of the List - that is, compare it to the adjacent elements and setting the sorted flag appropriately.

How to implement OPT Page Replacement algorithm in C?

Hello I am trying to implement the OPT Page Replacement algorithm:
Currenly I have created a linked list for all the future memory access references.
And my initial idea was to compare each reference in my linked list and mark down the distance for its next appearence as an attribute. When actually running the program and a page fault happens, I will look through every page in my page table and evict the page that has the longest distance.
However, I find my idea quite complicated and inefficient to implement. Is there a simplier way to implement this algorithm? Thanks.
The swaps made are the same for these two executions: (1) OPT on the original sequence of requests (2) LRU on the sequence of requests in reverse order. You can implement LRU via the doubly-linked-list strategy outlined in the linked Wikipedia article.

optimizing searching through memory

I have multiple instances of 4096 items. I need to search and find an item on a reocurring basis and i'd like to optimize it. Since not all 4096 items may be used, I thought, an approach to speed things up would be to use a linked list instead of an array. And whenever I have to search an item, once I found it, I'd place it on the head of the list so that next time it comes around, I'd have to do only minimal search (loop) effort. Does this sound right?
EDIT1
I don't think the binary search tree idea is really what I can use as I have ordered data, like an array i.e. every node following the previous one is larger which defeats the purpose, doesn't it?
I have attempted to solve my problem with caching and came up with something like this:
pending edit
But the output I get, suggests that it doesn't work like I'd like it to:
any suggestions on how I can improve this?
When it comes to performance there is only one important rule: measure it!
In your case you could for example have two different considerations, a theoretical runtime analysis and what is really going on one the machine. Both are heavily depending on the characteristics of your 4096 items. If your data is sorted you can have a O(log n) search, if it is unsorted it is worst case O(n) etc.
Regarding your idea of a linked list you might have more hardware cache misses because the data is not stored together anymore (spatial locality) ending up in having a slower implementation even if your theoretical consideration is right.
If you interested in general in such problems I recommend this cool talk from the GoingNative 2013
http://channel9.msdn.com/Events/GoingNative/2013/Writing-Quick-Code-in-Cpp-Quickly
Worst case, your search is still O(N) unless you sort the array or list, like Brett suggested. Therefore with a sorted list, you increase complexity of insertion (to insert ordered), but your searching will be much faster. What you are suggesting is almost like a "cache." It's hard for us to say how useful that will be without any idea of how often a found item is searched for again in the near-term. Clearly there are benefits to caching, it's why we have the whole L1, L2, L3 architecture in memory. But whether it will work out for you it's unsure.
If your data can be put in a binary search tree: http://en.wikipedia.org/wiki/Binary_search_tree
Then you can use a data structure called Splay tree: "A splay tree is a self-adjusting binary search tree with the additional property that recently accessed elements are quick to access again" http://en.wikipedia.org/wiki/Splay_tree
Respond to Edit1:
I think if your data element is not large, say, only a few bytes or even tens of bytes, 4096 of them can be fitted into memory. In this case what you need is a hash table. In C++, you use unordered_map. For example, you can define unorderedmap<int, ptr_to_your_node_type> and get the element in O(1) if your key type is int.
The fastest search could be O(1) if you can design your hash well and the worst case could be O(n). If these items are large and can not be fitted into memory, you can use the so called least recently used cachealgorithm to save memory.
An example code for LRU cache
template <typename K>
class Key_Age{
list<K> key_list;
unordered_map<K, typename list<K> :: iterator> key_pos;
public:
void access(K key){
key_list.erase(key_pos[key]);
insert_new(key);
}
void insert_new(K key){
key_list.push_back(key);
key_pos[key] = --key_list.end();
}
K pop_oldest(){
K t = key_list.front();
key_list.pop_front();
return t;
}
};
class LRU_Cache{
int capacity;
Key_Age<int> key_age;
unordered_map<int, int> lru_cache;
public:
LRU_Cache(int capacity): capacity(capacity) {
}
int get(int key) {
if (lru_cache.find(key) != lru_cache.end()) {
key_age.access(key);
return lru_cache[key];
}
return -1;
}
void set(int key, int value) {
if (lru_cache.count(key) < 1) {
if (lru_cache.size() == capacity) {
int oldest_key = key_age.pop_oldest();
lru_cache.erase(oldest_key);
}
key_age.insert_new(key);
lru_cache[key] = value;
return;
}
key_age.access(key);
lru_cache[key] = value;
}
};

Rearraging a rotated sorted array

I have seen several questions related to rotated sorted-arrays e.g. for searching for the pivot element or searching for an element in such an array.
However I did not find any question related to rearranging such an array to its original form without using sorting.
So my question: *Is there an efficient way, or trick, to rearrange a rotated, sorted-array to original form without using extra memory?
Heres what I would do..
I would find the starting element using a variation of binary search.
Once that is found , if you can use external memory, it can be done in O(n)
So the total time is O(lgn) + O(n) which is O(n)
Specifically to rotation: Seeing ajay's comments, I agree that since we have to rotate in place, the best option is bubble sort. Which is O(n*m) where m is number of elements rotated.
But if we can use some storage to keep the elements on either side of the starting element, basically, if we can use external memory, it just is a question of putting each element in the right place in the new array.

Why exactly do we need a "Circular Linked List" (singly or doubly) data structure?

Why exactly do we need a "Circular Linked List" (singly or doubly) data structure?
What problem does it solve that is evident with simple Linked Lists (singly or doubly)?
A simple example is keeping track of whose turn it is in a multi-player board game. Put all the players in a circular linked list. After a player takes his turn, advance to the next player in the list. This will cause the program to cycle indefinitely among the players.
To traverse a circular linked list, store a pointer to the first element you see. When you see that element again, you have traversed the entire list.
void traverse(CircularList *c) {
if (is_empty(c)) {
return;
}
CircularList start = c;
do {
operateOnNode(c);
c = c->next;
} while(c != start);
}
Two reasons to use them:
1) Some problem domains are inherently circular.
For example, the squares on a Monopoly board can be represented in a circularly linked list, to map to their inherent structure.
2) Some solutions can be mapped to a circularly linked list for efficiency.
For example, a jitter buffer is a type of buffer that takes numbered packets from a network and places them in order, so that (for example) a video or audio player can play them in order. Packets that are too slow (laggy) are discarded.
This can be represented in a circular buffer, without needing to constantly allocate and deallocate memory, as slots can be re-used once they have been played.
It could be implemented with a linked-list, but there would be constant additions and deletions to the list, rather than replacement to the constants (which are cheaper).
Something i found from google.
A singly linked circular list is a linked list where the last node in thelist points to the first node in the list. A circular list does not contain NULL pointers.
A good example of an application where circular linked list should be used is a timesharing problem solved by the operating system.
In a timesharing environment, the operating system must maintain a list of present users and must alternately allow each user to use a small slice of CPU time, one user at a time. The operating system will pick a user, let him/her use a small amount of CPU time and then move on to the next user, etc.
For this application, there should be no NULL pointers unless there is absolutely no one requesting CPU time.
Applications
1) We can use circular linked list any application where the entries appear in a rotating manner.
2) Circular linked list is the basic idea of round robin scheduling algorithm.
A circular linked list can be effectively used to create a queue (FIFO) or a deque (efficient insert and remove from front and back). See http://en.wikipedia.org/wiki/Linked_list#Circularly-linked_vs._linearly-linked
Circular linked lists are widely used in applications where tasks are to be repeated or in time sharing applications. Circular queue can keep a track of tasks which have been performed and which has to be performed,once the specific task is done it jumps to next one and when whole set of task is conpleted it again jumps to first task to complete the remaining job.
In practical use : when you open multiple applications on your system the memory of those applications are saved in a circular fashion, you can observe this if u continuously press win+tab/alt+tab for switching applications.
Also in multiplayer board games ,each player are assigned to node in the linked list and the rotation is performed
Circular linked lists (singly or doubly) are useful for applications that need to visit each node equally and the lists could grow. If the size of the list if fixed, it is much more efficient (speed and memory) to use circular queue.
A circular list is simpler than a normal doubly-linked list. Append is just prepend and shift forward once, Pop back is just shift back once and pop front. By tying the two ends together, you get a double-ended list for the cost of just implementing the operations of a one-ended list.
We can use circularly linked list in resource pooling. If many users want to use a shared resource, we can allocate that resource using circularly linked list.
A good example of an application where circular linked list should be used is a timesharing problem solved by the operating system.

Resources