Reputation: 121
I am attempting to implement a circular linked list, but it is not working as I expected. Even though I insert two elements with insertAfter
, printList
only prints one node. Here is a minimal example:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
struct dnode_elm {
int item;
struct dnode_elm *next, *prev;
};
struct dnode_elm *
insertAfter(struct dnode_elm *a, int value) {
struct dnode_elm *v= malloc(sizeof(struct dnode_elm));
v->item=value;
a->next=v;
v->prev=a;
v->next=a->next;
a->next->prev=v;
return v;
}
void
printList(struct dnode_elm *h) {
while (h != h->next) {
h = h->next;
printf("%d --> ",h->item);
}
}
int
main(void) {
struct dnode_elm h = { INT_MAX, &h, &h };
insertAfter(&h, 1);
insertAfter(&h, 2);
printList(&h);
}
Upvotes: 1
Views: 212
Reputation: 70392
Your insertion logic is wrong.
a->next=v;
v->prev=a;
v->next=a->next;
a->next->prev=v;
After this sequence of code, v->next
is equal to v
, which is probably not what you want.
One possible fix is to assign v
's pointers first, and then fix up the nodes around v
afterwards.
v->prev = a;
v->next = a->next;
v->next->prev = v;
v->prev->next = v;
To illustrate:
Set
v->next->prev
and v->prev->next
.
However you could have rearranged the assignments in your code as well, by moving the first assignment to be your last.
v->prev=a;
v->next=a->next;
a->next->prev=v;
a->next=v;
This allows the assignment to a->next->prev
to work as you expect.
In addition, your printing logic is flawed. You need to remember what the initial list pointer is so you can properly detect when you have reached the end.
void *start = h;
while (start != h->next) {
h = h->next;
printf("%d --> ",h->item);
}
Upvotes: 7