双向链表head持续被设为NULL问题求助
问题分析与解决方案
核心错误:全局head未被正确更新
你的代码中,AddNode和AddNodeAt函数返回了新的链表头,但main函数里没有将返回值赋值给全局的head变量。因为函数参数是传值传递,函数内部修改的head只是局部变量,全局head始终保持初始的NULL,这是所有功能失效的根本原因。
比如main里的调用应该改成:
head = AddNode(head, value);
和
head = AddNodeAt(head, position, value);
其他关键错误
1. 结构体定义错误
结构体内部不能直接使用node别名,因为typedef struct node node;是在结构体定义之后,所以结构体中的指针必须写成struct node*:
struct node { struct node *prev; // 修正前是node *prev; int val; struct node *next; // 修正前是node *next; }; typedef struct node node;
2. AddNodeAt函数的逻辑漏洞
- 未处理malloc失败的情况:如果
malloc返回NULL,后续操作会导致崩溃,需要添加判断。 - 未处理头部插入(position=1)的场景:当插入到链表头部时,需要直接更新
head,并处理新节点的prev和next。 - 位置遍历逻辑错误:要插入到第
position个位置(从1开始计数),需要找到第position-1个节点作为前驱,原代码的循环会跳过目标前驱节点。 - 重复调用
ListLength导致冗余输出:多次调用ListLength会重复打印链表长度,应该先获取一次长度存到变量中复用。 - 空链表插入position=1时的崩溃问题:原代码中当链表为空且position=1时,会进入末尾插入分支,此时
temp是NULL,访问temp->next会触发崩溃。
修正后的完整代码
#include <stdio.h> #include <stdlib.h> struct node { struct node *prev; int val; struct node *next; }; typedef struct node node; node *head; node *AddNode(node *head, int value) { node *ptr = (node *)malloc(sizeof(node)); if (!ptr) { printf("No Memory Available"); return head; } ptr->val = value; ptr->next = NULL; ptr->prev = NULL; if (!head) { head = ptr; } else { node *temp = head; while (temp->next) { temp = temp->next; } temp->next = ptr; ptr->prev = temp; } return head; } int ListLength(node *head) { int count = 0; if (head == NULL) { return 0; } else { node *temp = head; count = 1; while (temp->next != NULL) { temp = temp->next; count++; } return count; } } node *AddNodeAt(node *head, int position, int value) { node *ptr = (node *)malloc(sizeof(node)); if (!ptr) { printf("No Memory Available"); return head; } ptr->val = value; ptr->next = NULL; ptr->prev = NULL; int len = ListLength(head); // 边界判断 if (position < 1 || position > len + 1) { printf("Invalid position"); free(ptr); // 避免内存泄漏 return head; } // 插入到头部 if (position == 1) { ptr->next = head; if (head != NULL) { head->prev = ptr; } head = ptr; } // 插入到尾部 else if (position == len + 1) { node *temp = head; while (temp->next) { temp = temp->next; } temp->next = ptr; ptr->prev = temp; } // 插入到中间 else { node *temp = head; // 找到第position-1个节点 for (int i = 1; i < position - 1; i++) { temp = temp->next; } ptr->next = temp->next; ptr->prev = temp; if (temp->next != NULL) { temp->next->prev = ptr; } temp->next = ptr; } return head; } void PrintList(node *head) { node *temp = head; if (!head) { printf("list empty"); } else { while (temp != NULL) { printf("%d", temp->val); if (temp->next != NULL) { printf("->"); } temp = temp->next; } } } void PrintLength(node *head) { int len = ListLength(head); if (len == 0) { printf("\nEmpty List\n"); } else { printf("\n%d nodes\n", len); } } int main() { int value = 0; int num = 0; int position = 0; printf("Number of nodes to be made: "); scanf("%d", &num); for (int i = 1; i <= num; i++) { printf("value in node number %d: ", i); scanf("%d", &value); head = AddNode(head, value); } PrintList(head); PrintLength(head); printf("\nPosition of new node: "); scanf("%d", &position); printf("\nValue of new node:"); scanf("%d", &value); head = AddNodeAt(head, position, value); PrintList(head); PrintLength(head); return 0; }
额外优化说明
- 将
ListLength改为只返回长度,单独写PrintLength函数负责打印,避免不必要的输出。 - 修正
PrintList的循环逻辑,确保最后一个节点后不会多打印箭头。 - 在
AddNodeAt中,当位置无效时释放已分配的内存,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Abhinav Sharma
相关产品推荐
相关产品推荐

