I have a circular doubly linked list and I want to change the direction of all the next
and prev
pointers. I can't really figure out what the source of the error is. When I print the reversed list, it gets the first two numbers correct but past that point the links list stops printing.
struct Link
{
TYPE value;
struct Link * next;
struct Link * prev;
};
struct CircularList
{
int size;
struct Link* sentinel;
};
static void init(struct CircularList* list)
{
list->sentinel = (struct Link *) malloc(sizeof(struct Link));
list->sentinel->next = list->sentinel;
list->sentinel->prev = list->sentinel;
list->size = 0;
}
struct CircularList* circularListCreate()
{
struct CircularList* list = malloc(sizeof(struct CircularList));
init(list);
return list;
}
void circularListAddFront(struct CircularList* list, TYPE value)
{
struct Link *newLink = (struct Link *) malloc(sizeof(struct Link));
newLink->value = value;
newLink->next = list->sentinel->next;
newLink->prev = list->sentinel;
list->sentinel->next = newLink;
if(circularListIsEmpty(list)) {
list->sentinel->prev = newLink;
}
list->size++;
}
void circularListRemoveFront(struct CircularList* list)
{
struct Link *temp = list->sentinel->next;
temp->next->prev = list->sentinel;
list->sentinel->next = temp->next;
free(temp);
list->size--;
}
void circularListRemoveBack(struct CircularList* list)
{
struct Link *temp = list->sentinel->prev;
temp->prev->next = list->sentinel;
list->sentinel->prev = temp->prev;
free(temp);
list->size--;
}
void circularListReverse(struct CircularList* list)
{
struct Link *link = list->sentinel->next;
while(link != list->sentinel) {
struct Link *nextTemp = link->next;
struct Link *prevTemp = link->prev;
link->prev = link->next;
link->next = prevTemp;
link = nextTemp;
}
struct Link *temp = list->sentinel->next;
list->sentinel->next = list->sentinel->prev;
list->sentinel->prev = temp;
}
If I run the following to test this I get the output 5 4 1 2 2 1
and then terminates with no errors.
struct CircularList *deque = circularListCreate();
circularListAddBack(deque, 1);
circularListAddBack(deque, 2);
circularListAddBack(deque, 3);
circularListAddFront(deque, 4);
circularListAddFront(deque, 5);
circularListAddFront(deque, 6);
circularListRemoveFront(deque);
circularListRemoveBack(deque);
circularListPrint(deque);
circularListReverse(deque);
circularListPrint(deque);
There's a bug in your circularListAddFront
function, and (though not shown) probably also in circularListAddBack
:
Assume this state of the list:
p+SENTINEL+n
| A |
-----|------
Now, let's say you add 42
to the front. You first allocate a new node and set its value and pointers. Also you set the sentinel
next pointer:
struct Link *newLink = (struct Link *) malloc(sizeof(struct Link));
newLink->value = value;
newLink->next = list->sentinel->next;
newLink->prev = list->sentinel;
list->sentinel->next = newLink;
This leads to the following state:
p+SENTINEL+n
| A |
-----| |
| |
------ |
| | |
p+42+n |
A |
| |
---------
Which is not fine, because the prev
pointer of the sentinel still points to itself. You fix that directly after that:
if(circularListIsEmpty(list)) {
list->sentinel->prev = newLink;
}
list->size++;
This gives the desired result:
p+SENTINEL+n
--| A |
| | |
| ------ |
| | | |
| p+42+n |
| A |
| | |
--------------
This is fine. Now let's add a 21
to the glorious list:
----------
| |
| V
| p+SENTINEL+n
| --| A |
| | | |
| | ------ |
| | | | |
| | p+42+n |
| | A |
| | | |
| -----| |
| | |
| p+21+n |
--| A |
| |
-----------
That's the state right before that if
, and it has the same issue as before: There's one prev
pointer wrong, this time it's not sentinels but the one of node 42
: It should point to its previous node, which is now 21
, and not to the sentinel.
Since the if
is not taken, the sate remains. You don't notice it until reversing the list because you don't use the prev
pointers until then.
To fix that, get rid of the if
and correct the logic unconditionally:
When you insert a new node to the front ("after the sentinel"), then you need to change the prev
pointer of the node that was at the front before and point it to the new node:
newLink->next = list->sentinel->next;
newLink->prev = list->sentinel;
list->sentinel->next->prev = newLink; // ADDITION
list->sentinel->next = newLink;
The code for reversing the list seems fine, though. And for now, I'm done with "line art ASCII graphics" :D
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.