我有一个循环的双向链表,我想改变所有next
和prev
指针的方向。我无法弄清楚错误的来源是什么。当我打印反转列表时,它会使前两个数字正确,但在此之后链接列表将停止打印。
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;
}
如果我运行以下命令来测试它,我得到输出5 4 1 2 2 1
,然后终止,没有错误。
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);
答案 0 :(得分:1)
circularListAddFront
函数中存在一个错误,circularListAddBack
中可能也存在错误(尽管未显示):
假设列表的这种状态:
p+SENTINEL+n
| A |
-----|------
现在,我们假设您在前面添加42
。首先分配一个新节点并设置其值和指针。您还设置了sentinel
下一个指针:
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;
这导致以下状态:
p+SENTINEL+n
| A |
-----| |
| |
------ |
| | |
p+42+n |
A |
| |
---------
哪个不好,因为哨兵的prev
指针仍然指向自己。你在那之后直接解决了这个问题:
if(circularListIsEmpty(list)) {
list->sentinel->prev = newLink;
}
list->size++;
这给出了期望的结果:
p+SENTINEL+n
--| A |
| | |
| ------ |
| | | |
| p+42+n |
| A |
| | |
--------------
这很好。现在,让我们将21
添加到光荣的列表中:
----------
| |
| V
| p+SENTINEL+n
| --| A |
| | | |
| | ------ |
| | | | |
| | p+42+n |
| | A |
| | | |
| -----| |
| | |
| p+21+n |
--| A |
| |
-----------
那个状态就在if
之前,并且它有与以前相同的问题:有一个prev
指针错误,这次它没有但是节点42
之一的标记:它应指向其上一个节点,现在是21
,而不是指向标记。
由于未采用if
,因此状态仍然存在。在撤消列表之前你不会注意到它,因为在此之前你不会使用prev
指针。
要解决这个问题,请摆脱if
并无条件地纠正逻辑:
当你在前面插入一个新节点时("在哨兵"之后),你需要更改前面节点的prev
指针并将其指向新节点:
newLink->next = list->sentinel->next;
newLink->prev = list->sentinel;
list->sentinel->next->prev = newLink; // ADDITION
list->sentinel->next = newLink;
但是,反转列表的代码似乎很好。而就目前而言,我已经完成了"线条艺术ASCII图形" :d