c++ understanding a circular doubly linked list - c++

I'm having a problem figuring out how to set my ptr's for prev and next when I add a node with at least one existing node. Adding the first node is easy, just setting the ptrs to the front. I need help viewing this mentally, also this program is a queue so each node gets added to the back of the list.
if (Empty())
{
front = new qnode;
front->next=front;
front->prev=front;
front->data = item;
}
else if (front->prev=front)
{
front->prev = new qnode;
front->prev->next= front;
front->next=front->prev;
front->prev->data = item;
}
else
{
}
What i have now still not getting it
else
{
front->prev= new qnode;
front->prev->data= item;
front->prev->next=front;
front->prev=front->prev->prev;
}

I hope this image helps a bit
I have created pictures for 1 item 2 items and 3 items
the pointers just point to the actual object meaning the black rectangle is the whole object if front being blue and prev being brown(those are just there as references)
I really hope this helps linked list can get really tricky and drawing always helps me.
so to add the item at the front of the list you have some code like this:
//ok first I'll define some variables for you
//last === the last node in the list
//head === the first node in the list
//node === the new node you are adding;
qnode node = new qnode;
node.data = data; //whatever data you are holding
node->next = last; //last element in the list since it is circular;
node->prev = head; //you want the new node to point the the first node since it's getting added before that;
head->next = node; //you want the head of the node to point to the new node not the last item
last->prev = node; //last node now should point to the new node you just added not the head;

I am not sure why you need an else if, as I think the case with one element is not different from that with multiple elements. In any case you have a syntax error there - you wanted to write == instead of =.
More to the point, what you want to do is:
Create a new qnode
Set the data of the new node to the item
Set the next of the new node to the front
Set the prev of the new node to front->prev
Set the prev of the front to the new node.
You may check for yourself on a piece of paper how this works.

In a circular doubly linked list, you have 2 pointers, one to the head and one to the tail (last element in the list). If a element has a next, the next element's prev should be the element pointing at it through it's next element.
Your head pointer should never move unless the head element is removed. Your tail will move along always ensuring that the element it points to has head as it's next element.
Hopefully this helps

Since you always add at the end, the case of a queue with a single element is identical with the case of a list with multiple elements. Take a paper and a pen, make some sketches and it will come very easy to you.

Related

how to get head of the list after traversal in Linked lists?

I have traversed a linked list and ended up reaching NULL in head in between I modified some elements in head. How do I get back the head pointer with those modifications.
Node* temp=head;
while(head&&head->next){
head=head->next->next;
}
I want linked list to be modified into new one with alternate nodes. So after this how can I get back the new head pointer.
EDIT:
ListNode* temp=head,*new1=head;
while(head!=NULL&&head->next){
new1->next=head->next->next;
head->next=head->next->next;
new1=new1->next;
}
//temp=head;
return new1;
I think what you meant to do is:
Node* temp = head;
while(temp && temp->next){
temp = temp->next->next;
}
That way, you always have the head.
One way is to use a different pointer to traverse the list, and leave head alone.
Another way is to restore head after you are done. Your code seems to indicate this is possible, since you have stored head in temp before you entered the loop.
head = temp;
new1 = temp;

Return a pointer to a sorted list; linked list in C++

i want this function sortPair to take 2 Node pointers and return a pointer to a list of the 2 elements sorted alphabetically. The code below is what I have so far. If someone could let me know where I went wrong, that would be great.
struct Node{
string val;
Node* next;
};
Node* sortPair (Node* p1, Node* p2){
//Assert that neither pointer is null
assert(p1!=NULL);
assert(p2!=NULL);
Node* head=NULL;
Node* current=NULL;
Node* last = NULL;
current = new Node();
if(p1-> val >p2-> val) //If p1->val comes before p2->val in the alphabet
{
current->val = p1->val;
head = current;
last = current;
current = new Node();
current -> val = p2->val;
last = current;
last ->next = NULL;
}
else
{
current->val = p2->val;
head = current;
last = current;
current = new Node();
current -> val = p1->val;
last = current;
last ->next = NULL;
}
return head;
}
A linked list is just a series of nodes that are linked by each element having a pointer to the next one.
From your code, it seems like you do not want to make a list of the two nodes, but rather insert a node into a list that already exists.
If all you want to do is to make a linked list of the two nodes that are there, then set the one with the lower or higher value, depending on how you sort them, to point at the other one. For example, if you are sorting from smallest to biggest, set the smallest node's next pointer to point to the bigger one and return the pointer of the smallest one.
If you want to add one of the nodes into a list of nodes, then you must loop through the list until you find one that is larger or smaller than the node you want to insert. I recommend using a while loop.
If you want to merge two lists, then you must make a new loop that inserts each element of one list into the other list.
There is no need to make a new node for any of this, just use the ones you have and change the next pointers.
Hope this helps.

Organize a linkedlist into an array of linkedlist in C++

I am writing a method that takes a function that takes a root of a linked list and the number of vertices in a graph and organizes the linked list into an array of linked list based on the first vertex of an edge struct, for example, in a struct where an node Edge has firVertex = 1, sndVertex = 2, and weight = 2, it would be sorted into the first element of an array. and another node Edge that has another firVertex = 1 would be appended onto the previous one, and etc. My code compiles but it's not exactly doing what I want. Please help.
You have many issues in your code.
While assigning the newNode to the elements of array list it should be
arrayList[j]= newNode; //not 'i' since i=numberVertices always....
When you are finding a firVertex matching the j, you are creating a temporary pointer which points to the current node. Then you are doing this:
newNode -> next = NULL;
It actually changes the next of the node in the given list to NULL, thus making the current->next as NULL and your code won't process the whole list. It should be instead as follows:
Edge* newNode = new Edge(current);//create a copy of the 'current' node..
newNode -> next = NULL;//now make the 'next' of this node NULL..
The above code prevents the list from any modifications. I also assume there is a constructor for Edge, which takes another Edge pointer as argument.
As you specified in the question, if you have two Edge nodes with same firVertex, you wanted to append them on the same list. But your code merely over-writes the previous node.
To prevent that, it can be written as follows:
Edge* newNode = new Edge(current);
newNode -> next = NULL;
Edge* tmp = arrayList[j];
if(tmp==NULL)//then this is the first node..
{
arrayList[j] = new Edge(current);
arrayList[j]->next = NULL;
}
else
{
while(tmp->next!=NULL)//go to the end of the list...
tmp = tmp->next;
tmp->next = new Edge(current);//create a copy of the 'current' node...
tmp->next->next=NULL;//make the next of this new node NULL...
}
Hope this helps...and I strongly feel that you need to learn more about pointers and then start coding.

How I can get back in singly linked list?

I have a singly linked list. From each node in the list, I can get to the next element. Is it possible instead to get to the previous element? Note that I cannot use a doubly linked list because of memory constraints.
If you must use a singly linked list, then one way to approach this is to traverse the list again until you find the prior item. You will know when you are at the prior item when its Next field is equal to the current item.
Pseudo C code:
Node* GetPreviousNode(Node* currentNode)
{
Node* iteratorNode = GetHeadNode();
while (iteratorNode != NULL)
{
if (iteratorNode->Next == currentNode)
return iteratorNode;
iteratorNode = iteratorNode->Next;
}
return NULL;
}
You can't, you have to use a double-linked-list where you have a pointer to the previous and next elements. A single linked list simply points to the next element and doesn't keep track off previous elements.
Try this:
http://en.literateprograms.org/Doubly_linked_list_(Java)
There a 2 different methods for traversing a singly linked list both ways.
Method 1: The link field (of the structure) is actually a 'difference' field. The link is computed
as the address of the next item minus the address of the previous item, therefore ...
next = address of the previous item + link of the current item.
prev = address of the next item - link of the current item.
If you can do arithmetic with pointers, you will be in business. If not, you will have to use a union (in C++) or use method 2. See: Algorithms + Data Structures = Programs by Niklaus Wirth - Prentice-Hall
1976 - page 19.
Method 2: The link field is the 'exclusive or' (^) of the address of the previous item with the address
of the next item. Exclusive or is an inverse of itself, therefore ...
next = address of the previous item ^ link of the current item.
prev = address of the next item ^ link of the current item.
If you have a node that you are sure of, is before the given node in a singly linked list, then you can make a function:-
struct node* prev(struct node* before, struct student_detail* current)
{
struct student_detail* temp = before;
while (temp->next != NULL)
{
if(temp->next == current)
{
return temp;
}
temp = temp-> next;
}
return NULL;
}
and use it as in
example_node = prev(before, example_node);
If you have head, you can always use that as the prev node.
You can theoretically go back, it generally beats the whole concept behind a singly linked list and it's more trouble than necessary but if you have to, here's how to implement it in C, assuming of course, you already declared your Node struct:-
Node* go_back(Node* head, Node* current_node){
//Traverse the linked list until we discover the next node
//in our traversal points to our current node
Node* previous_node = head;
while(previous_node->next != NULL){
if(previous_node->next == current_node)
return previous_node->next; //found previous node
previous_node = previous_node->next;
}
return previous_node //we found nothing, give up
}

Sorting Nodes (Linked-list) C++

I'm trying to sort a linked-list. I have a Node called head and it's pointing to the next node, etc.
But when I try to sort the Nodes by the value they carry, I get the sort working because I see it printing out the stuff in the if-statement, but I'm not getting back the linked-list. Where did I go wrong?
Node* head;
void sortlist(){
Node * runner = head;
Node * runner2;
for(runner = head; runner->next != NULL; runner = runner->next){
for(runner2 = runner->next; runner2->next != NULL; runner2 = runner2->next){
if(runner->freq < runner2->freq){
cout<< runner->freq<< " is LT "<<runner2->freq<< endl;
Node * temp = runner;
runner = runner2;
runner2 = temp;
}
}
}
head = runner;
}
I'm only getting back the first Node.
In order to swap two elements in a linked list, consider what you need to change. For example, to get from
Head -> First -> Second -> (NULL)
to
Head -> Second -> First -> (NULL)
you need to update: Head.next, First.next and Second.next. You don't change any of those things when trying to swap nodes, so it can't possibly do what you expect.
Just swapping the values (ie, swap(runner->freq, runner2->freq)) would be much simpler.
you will stop when runner->next == NULL;, which is supposed to be the last element. And then you set head = runner;, which means the head will always be the last element after this routine. Furthermore, I do not trust this swapping.
It seems you vaguely want to do an insertion sort. If you want to do a simple sorting on linked lists, I suggest you to use selection sort: You create another empty list l2, and each time you remove the minimum element from your first list, and add it as the head of l2. The code for the second list is simple:
void prepend(Node* node, Node** list){
//null checks if you want
node->next = *list;
*list=node->next;
}