You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

仅用一个局部指针删除链表节点:我的解法是否正确?

关于《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. 删除中间节点时
    比如链表为 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. 未找到匹配节点时
    比如链表为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 06:03:11