Reputation: 39
I am trying to add 'n' number of nodes to the beginning of double circular linked list here is the function for adding the node:
//the **head is assigned the address of the original head pointer which is being passed from the main function.
void insert(struct node**head,int n){
while(n-- >0){
int num;
//to input the data for the linked list
scanf("%d",&num);
struct node* newnode=(struct node*)malloc(sizeof(struct node));
newnode->data=num;
if(*head==NULL){
newnode->next=newnode;
newnode->prev=newnode;
*head=newnode;
}
else{
newnode->next=*head;
newnode->prev=(*head)->prev;
//to make the previously first node point to the new first node
newnode->next->prev=newnode;
//to make the last node point to the new first node
(*head)->prev->next=newnode;
*head=newnode;
}
}
}
when I execute it, it is not showing any ouput but when I change
//to make the last node point to the new first node
(*head)->prev->next=newnode;
this line to
newnode->prev->next=newnode;
the code is running. I am not able to understand what is the difference between the two statement.
Upvotes: 2
Views: 121
Reputation: 17403
The original code goes wrong when the list contains a single node before the new node is added. Let's call that node A
for reference. Before inserting the new node, the situation is as follows:
/* List with single node. */
(*head) = &A;
A.next = &A;
A.prev = &A;
Let's call the node pointed to by newnode
B
:
newnode = &B;
The code to prepend newnode
is currently as follows (with added comments //>
):
newnode->next=*head; //> B.next=&A;
newnode->prev=(*head)->prev; //> B.prev=&A;
//to make the previously first node point to the new first node
newnode->next->prev=newnode; //> A.prev=&B;
//to make the last node point to the new first node
(*head)->prev->next=newnode; //> B.next=&B; !!! want A.next = &B;
*head=newnode;
The situation after the above code sequence:
(*head) = &B;
B.next = &B; // !!! want B.next = &A;
B.prev = &A;
A.next = &A; // !!! want A.next = &B;
A.prev = &B;
The list has been broken because the wrong link pointer was changed. It can be fixed by using a temporary variable lastnode
set to the old value of (*head)->prev
. The updated code is as follows:
struct node *lastnode;
lastnode=(*head)->prev; //> lastnode=&A;
newnode->next=*head; //> B.next=&A;
newnode->prev=lastnode; //> B.prev=&A;
//to make the previously first node point to the new first node
newnode->next->prev=newnode; //> A.prev=&B;
//to make the last node point to the new first node
lastnode->next=newnode; //> A.next=&B;
*head=newnode;
The situation after the updated code sequence:
(*head) = &B;
B.next = &A;
B.prev = &A;
A.next = &B;
A.prev = &B;
Upvotes: 0
Reputation: 19375
(*head)->prev->next=newnode; ... newnode->prev->next=newnode;
I am not able to understand what is the difference between the two statement.
newnode->prev
has been correctly set to the node before the head. In contrast, (*head)->prev
at this time has already been altered by newnode->next->prev=newnode
, since newnode->next=*head
. Hence (*head)->prev
no longer points to the node before the head, but to the new node. That's the difference.
Upvotes: 1
Reputation: 2201
The next code assumes that head
is defines as: struct node* head;
. I just removed some extra dereferencing operators(*
).
It is not directly testable, as a minimally reproducible example was not provided.
while(n-- >0){
int num;
//to input the data for the linked list
scanf("%d",&num);
struct node* newnode=(struct node*)malloc(sizeof(struct node));
newnode->data=num;
if(head==NULL){ /* was: if(*head==NULL){ */
newnode->next=newnode;
newnode->prev=newnode;
head=newnode;{ /* was: *head=newnode;{ */
}
else{
newnode->next=head; /* was: newnode->next=*head; */
newnode->prev=(*head)->prev;
//to make the previously first node point to the new first node
newnode->next->prev=newnode;
//to make the last node point to the new first node
(*head)->prev->next=newnode;
head=newnode; /* was: *head=newnode; */
}
}
Upvotes: 0