C++双向链表仅显示头节点求助:排查Insert/Display函数问题
双向链表Display仅显示头节点问题排查与修复
问题描述
刚学习C++(实际使用C语言实现),尝试编写一个包含Insert、Delete、Display操作的简单双向链表。插入操作看似正常,但Display仅能显示头节点,不确定问题出在Insert函数还是Display函数上,期望显示格式为a->b->c......。
错误分析
1. Display函数核心问题
当前Display函数仅打印头节点的数据,未通过循环遍历整个链表,因此只能输出第一个节点。
2. Insert函数逻辑错误
- 嵌套的
while和for循环导致节点定位错误,无法正确找到指定插入位置的前驱节点; - 插入链表尾部时,未将前驱节点的
next指向新节点,导致新节点无法被链表引用,遍历不到; - 缺少内存分配失败的判断逻辑。
3. Delete函数潜在问题
- 未处理删除头节点、尾节点的边界情况;
- 删除节点后未释放内存,造成内存泄漏;
- 指定位置超出链表长度时,会访问空指针导致程序崩溃。
修正后的完整代码
#include <stdio.h> #include <stdlib.h> struct node { int data; struct node *prev; struct node *next; }; struct node *head = NULL; void insert(struct node **head) { struct node *newnode = (struct node *)malloc(sizeof(struct node)); if (newnode == NULL) { printf("\n内存分配失败\n"); return; } newnode->next = NULL; newnode->prev = NULL; if ((*head) == NULL) { int x; printf("\n请输入起始节点的值: "); scanf("%d", &x); newnode->data = x; (*head) = newnode; } else { int pos, x; printf("\n请输入插入位置: "); scanf("%d", &pos); if (pos == 0) { printf("\n请输入位置%d的数据: ", pos); scanf("%d", &x); newnode->data = x; newnode->next = (*head); (*head)->prev = newnode; (*head) = newnode; } else { struct node *ptr = (*head); // 定位到目标位置的前驱节点,若位置超出长度则插入到尾部 for (int i = 0; i < pos - 1; i++) { if (ptr->next == NULL) { break; } ptr = ptr->next; } printf("\n请输入位置%d的数据: ", pos); scanf("%d", &x); newnode->data = x; newnode->prev = ptr; newnode->next = ptr->next; if (ptr->next != NULL) { ptr->next->prev = newnode; } ptr->next = newnode; } } } void delete (struct node **head) { if ((*head) == NULL) { printf("\n下溢(链表为空)\n"); return; } int pos; printf("\n请输入要删除的位置: "); scanf("%d", &pos); struct node *ptr = (*head); // 定位到要删除的节点 for (int i = 0; i < pos; i++) { if (ptr == NULL) { printf("\n位置无效\n"); return; } ptr = ptr->next; } if (ptr == NULL) { printf("\n位置无效\n"); return; } // 处理头节点删除 if (ptr->prev == NULL) { (*head) = ptr->next; if ((*head) != NULL) { (*head)->prev = NULL; } } else { ptr->prev->next = ptr->next; // 处理尾节点删除 if (ptr->next != NULL) { ptr->next->prev = ptr->prev; } } free(ptr); printf("\n位置%d的节点已删除\n", pos); } void display(struct node **head) { struct node *ptr = (*head); if (ptr == NULL) { printf("\n链表为空\n"); return; } // 遍历链表并按指定格式输出 while (ptr != NULL) { printf("%d", ptr->data); if (ptr->next != NULL) { printf("->"); } ptr = ptr->next; } printf("\n"); } int main() { while (1) { int x; printf("\n1.插入\n2.删除\n3.显示\n4.退出\n\n请选择操作:\n"); scanf("%d", &x); switch (x) { case 1: insert(&head); break; case 2: delete (&head); break; case 3: display(&head); break; case 4: printf("\n程序退出\n"); exit(0); default: printf("\n无效操作,请重新选择:\n"); continue; } } return 0; }
关键修正说明
- Display函数:添加循环遍历逻辑,逐个打印节点数据,并用
->连接非尾节点; - Insert函数:移除错误的嵌套循环,正确定位插入位置的前驱节点,修复尾部插入时的链表连接逻辑,增加内存分配失败的判断;
- Delete函数:处理头/尾节点删除的边界情况,增加位置有效性检查,添加内存释放逻辑,避免内存泄漏;
- 主函数:增加退出选项的处理,优化提示信息的可读性。
内容的提问来源于stack exchange,提问作者user18918606
相关产品推荐
相关产品推荐

