从链接列表中删除元素

时间:2014-09-26 13:46:35

标签: c linked-list

我正在重构一些C代码,因为有一段时间我挂起了与链表数据结构相关的问题。请查看以下简化代码段:

Link apply(Link first, pred_ptr cond)
{
    Link t=first->next,p=first;
    do{
        if(cond(t))
        {
            p->next=t->next;
            free(t);
            t=p;
        }
        p=t;
        t=t->next;
    }while(t!=first);
    //Check the first
    if(cond(first))
    {
        t=first->next;
        free(first);
        first=t;
        p->next=t;
    }
    return first;
}

函数 apply 删除链接列表中 cond 函数返回非零值的所有元素。 链接是这样的:

struct node
{
    struct node* next;
    //Stuff
};

typedef struct node* Link

嗯,我唯一的问题是如何应用删除链接列表的第一个元素 - first - ,看起来像循环中的额外代码为了评估第一个元素是必需的,我没有能够在没有额外的 if 语句的情况下将这个检查放在循环中,也许你可能知道如何从循环中删除额外的代码 - 如果可能 - 你呢?

谢谢,

度过愉快的一天。

2 个答案:

答案 0 :(得分:0)

第一个元素是一个特例,所以你会得到一个与其他案例略有不同的代码就不足为奇了。所以你的选择是(1)在你的例子中完成它的方式,(2)将特殊情况代码放在主循环中,每次迭代执行if比较,或者(3)使用指针指针的不易理解的版本。 / p>

你应该问自己的第一个问题是:你为什么要重构?为清楚起见,还是因为需要更快的实施?或者......?

答案 1 :(得分:0)

您的代码逻辑几乎正确,但在某些地方存在各种问题:

  • 阅读代码,我猜link list实际上是circular link list,因为如果没有,某些节点中的某些->next将是== NULL。并且代码不会在任何地方检查NULL,在while循环结束之前的t=t->next;之类的行将在达到NULL时执行未定义的行为。假设cond函数与NULL一起正常工作而不输入if语句(如果输入, UB 将在此处执行p->next=t->next;)。如果link list只是link list而不是循环,则代码需要大量重构。

linked listcircular linked list中的第一个元素可以单独分析,在简单linked list的情况下,这样做会更好,因为循环分析其余的节点的可读性更强,无需处理特定情况(将在循环中处理,并且在{{1}的情况下,您不会通过检查第一个节点来重载另一个节点的分析。第一个元素可以优雅地在循环中进行分析,但也可以在循环中进行分析。

顺便提一下,如果这是实际代码中使用的变量名,那么你已经在重构中了(p - > previous,t - > test?我认为等等......)