C 中的双向链表(打印)
Doubly linked list in C (printing)
我已经创建了双向链表,并且设法从头到尾打印它,但是我在向后打印时遇到了麻烦。我在 "current = current->prev" 行遇到分段错误,我不明白为什么。
current = head;
while (current) {
printf("%p\t%s\t%d\n", current, current->name, current->age);
current = current->next;
}
current = current->prev;
while (current) {
printf("%p\t%s\t%d\n", current, current->name, current->age);
current = current->prev;
}
我找到了解决这个问题的方法:
current = head;
while (current) {
printf("%p\t%s\t%d\n", current, current->name, current->age);
current = current->next;
}
current = head;
while (current->next) current = current->next;
while (current) {
printf("%p\t%s\t%d\n", current, current->name, current->age);
current = current->prev;
}
但是,我还是不明白为什么我的方法不起作用。如果有人能解释一下,我将不胜感激。
当你完成向前方向的循环遍历时,current
将被设置为 NULL
,因此使用行:
current = current->prev;
不会有好下场。不允许取消引用 NULL
.
你的第二个代码片段起作用的原因是:
current = head;
while (current->next) current = current->next;
它让 current
指向列表中的 last 项,而不是 NULL
。
大多数双向链表往往同时具有 head
和 以及 tail
,您将使用后者进行反向扫描。
如果您没有tail
,那么第二个代码片段可能看起来是一种可接受的查找方式最后,虽然效率不如 with a tail
.
然而,它有一个致命的缺陷,那就是如果列表为空,它可能会出现错误:
current = head; // current <- NULL
while (current->next) // cannot dereference NULL
current = current->next;
像这样的东西你会过得更好:
current = head;
if (current != NULL)
while (current->next != NULL)
current = current->next;
如果列表为空,则将 current
设置为 NULL
,否则设置为最后一项的地址。这意味着您的反向循环将正常工作:
while (current != NULL) {
doSomethingWith (current);
current = current->prev;
}
第一次向前遍历列表以打印其元素时,循环在 current == NULL
时结束,然后您尝试在
之后立即取消引用 current
current = current->prev;
/* ^ NULL */
试试这个
current = head;
while (current->next) {
printf("%p\t%s\t%d\n", current, current->name, current->age);
current = current->next;
}
printf("%p\t%s\t%d\n", current, current->name, current->age);
while (current) {
printf("%p\t%s\t%d\n", current, current->name, current->age);
current = current->prev;
}
请注意,在您的 修复 中,您基本上就是这样做的。
我已经创建了双向链表,并且设法从头到尾打印它,但是我在向后打印时遇到了麻烦。我在 "current = current->prev" 行遇到分段错误,我不明白为什么。
current = head;
while (current) {
printf("%p\t%s\t%d\n", current, current->name, current->age);
current = current->next;
}
current = current->prev;
while (current) {
printf("%p\t%s\t%d\n", current, current->name, current->age);
current = current->prev;
}
我找到了解决这个问题的方法:
current = head;
while (current) {
printf("%p\t%s\t%d\n", current, current->name, current->age);
current = current->next;
}
current = head;
while (current->next) current = current->next;
while (current) {
printf("%p\t%s\t%d\n", current, current->name, current->age);
current = current->prev;
}
但是,我还是不明白为什么我的方法不起作用。如果有人能解释一下,我将不胜感激。
当你完成向前方向的循环遍历时,current
将被设置为 NULL
,因此使用行:
current = current->prev;
不会有好下场。不允许取消引用 NULL
.
你的第二个代码片段起作用的原因是:
current = head;
while (current->next) current = current->next;
它让 current
指向列表中的 last 项,而不是 NULL
。
大多数双向链表往往同时具有 head
和 以及 tail
,您将使用后者进行反向扫描。
如果您没有tail
,那么第二个代码片段可能看起来是一种可接受的查找方式最后,虽然效率不如 with a tail
.
然而,它有一个致命的缺陷,那就是如果列表为空,它可能会出现错误:
current = head; // current <- NULL
while (current->next) // cannot dereference NULL
current = current->next;
像这样的东西你会过得更好:
current = head;
if (current != NULL)
while (current->next != NULL)
current = current->next;
如果列表为空,则将 current
设置为 NULL
,否则设置为最后一项的地址。这意味着您的反向循环将正常工作:
while (current != NULL) {
doSomethingWith (current);
current = current->prev;
}
第一次向前遍历列表以打印其元素时,循环在 current == NULL
时结束,然后您尝试在
current
current = current->prev;
/* ^ NULL */
试试这个
current = head;
while (current->next) {
printf("%p\t%s\t%d\n", current, current->name, current->age);
current = current->next;
}
printf("%p\t%s\t%d\n", current, current->name, current->age);
while (current) {
printf("%p\t%s\t%d\n", current, current->name, current->age);
current = current->prev;
}
请注意,在您的 修复 中,您基本上就是这样做的。