链表头插异常:使用替代头指针变量为何无法完成插入?
链表头节点插入时局部指针变量赋值失效的原因
你遇到的核心问题是局部指针变量的赋值无法影响外部的指针变量,下面拆解清楚:
指针变量的本质
hd是insert函数内部的局部指针变量,执行hd = *head时,只是把main函数里head指针的值(也就是原链表头节点的内存地址)拷贝给了hd。这时候hd和*head(即main里的head)指向同一个节点,但hd本身是完全独立的变量,和main里的head没有任何绑定关系。
为什么hd=ins没用?
当你在插入头节点时写hd=ins,只是把新节点ins的地址赋值给了局部变量hd,这个修改只在insert函数内部有效。函数执行完后,hd就会被销毁,main函数里的head指针根本没被改动,还是指向原来的节点(或者NULL),所以新节点根本没被当成链表头,插入操作等于没做。
为什么*head=ins就有效?
head是二级指针(list **),*head其实就是main函数里的head指针本身。执行*head=ins时,直接修改了main里head指针的内容,让它指向新的头节点ins。这样main里的链表头就更新了,新节点自然成为链表的第一个节点。
为什么else分支用hd没问题?
else分支是插入到链表中间或尾部,这时候我们操作的是链表节点的next指针(比如t->next=ins),这些节点是在堆内存上的,修改的是节点本身的内容,而不是hd这个局部变量的指向。hd只是用来遍历找到要插入的位置,它的指向变化只是为了移动遍历位置,不需要影响main里的head指针,所以用hd完全没问题。
整理后的规范代码
typedef struct ll { int data; struct ll *next; } list; // main函数中调用方式:insert(&head, &n); // 链表插入函数,n为链表长度 void insert(list **head, int *n) { list *hd; hd = *head; // 用hd简化遍历操作 int pos, i, value; list *ins, *t; printf("\nenter position to insert "); scanf("%d", &pos); if (pos > (*n + 1) || pos < 1) { printf("\ninvalid position\n"); return; } printf("enter value to insert "); scanf("%d", &value); ins = (list*) malloc(sizeof(list)); ins->data = value; if (pos == 1) { ins->next = hd; // 此处hd指向原头节点,没问题 *head = ins; // 必须修改外部的head指针,才能更新链表头 // 若写hd=ins,只是修改局部变量,外部head不会变 } else { // 用hd遍历找到插入位置的前一个节点 for (i = 1; i < pos - 1; i++) { hd = hd->next; } t = hd; hd = hd->next; t->next = ins; ins->next = hd; } *n = *n + 1; }
内容的提问来源于stack exchange,提问作者Abhinav Ojha
相关产品推荐
相关产品推荐

