仅用一个局部指针删除链表节点:我的解法是否正确?
关于《C Programming: A Modern Approach》链表删除函数解法的疑问
这是K.N. King所著《C Programming: A Modern Approach》中的习题节选。我希望了解自己给出的解法最后部分是否有误。
习题要求
修改delete_from_list函数,使其仅使用一个指针变量(而非原代码中的cur和prev两个)。该函数用于删除链表中第一个.value等于参数n的节点。
原代码
struct node { int value; struct node *next; }; struct node *delete_from_list(struct node *list, int n) { struct node *cur, *prev; for (cur = list, prev = NULL; cur != NULL && cur->value != n; prev = cur, cur = cur->next) ; if (cur == NULL) return list; if (prev == NULL) list = list->next; else prev->next = cur->next; free(cur); return list; }
我的解法
struct node *delete_from_list(struct node **list, int n) { struct node *ptr = *list; while (ptr != NULL) { if (ptr->value == n) { *list = ptr->next; free(ptr); break; } list = &(ptr->next); ptr = ptr->next; } return *list; }
我认为这个解法几乎正确,但不确定最后一句return *list;是否真的返回链表的起始节点。这是我首次使用指向结构体的指针的指针,可能存在概念误解。我更想知道自己的解法是否有误,而非获取全新解法,以节省您的时间。
解法分析
你的核心逻辑(用指向指针的指针跟踪前驱节点的next)是可行的,但return *list;确实存在错误,无法正确返回链表的起始节点,具体问题出在这两种场景:
- 删除中间节点时
比如链表为1 -> 2 -> 3,要删除值为2的节点:
- 第一次循环:
ptr指向1,值不匹配,list变为&(1->next)(即指向节点1的next指针),ptr移动到2。 - 第二次循环:匹配值,执行
*list = ptr->next(让节点1的next指向3),释放节点2后跳出循环。 - 此时
list指向的是节点1的next指针,*list的值是3,但链表的起始节点仍然是1,返回3显然错误。
- 未找到匹配节点时
比如链表为1 -> 2 -> 3,要删除值为4的节点:
- 循环遍历到
ptr为NULL时结束,此时list已经指向最后一个节点(3)的next指针,*list的值是NULL,但原函数逻辑中这种情况应该返回原始的头节点1,你的返回结果错误。
针对你解法的修正
要正确返回链表起始节点,只需在函数开头保存原始头指针的副本,并在删除头节点时更新这个副本即可:
struct node *delete_from_list(struct node **list, int n) { struct node *head = *list; // 保存原始头指针 struct node *ptr = *list; while (ptr != NULL) { if (ptr->value == n) { *list = ptr->next; if (ptr == head) { // 删除的是头节点,更新头指针副本 head = *list; } free(ptr); break; } list = &(ptr->next); ptr = ptr->next; } return head; // 返回正确的头指针 }
另外补充:你的解法修改了原函数的接口(从传入struct node*改为struct node**),这本身没问题,但调用时需要传入头指针的地址,注意对应调整调用逻辑。
内容的提问来源于stack exchange,提问作者0jnats3
相关产品推荐
相关产品推荐

