从C中的列表中删除

时间:2015-11-28 14:49:25

标签: c pointers linked-list singly-linked-list

基本上我必须从链表中删除某个项目。 此代码有效:

void delete_(Item client){
    link s=head,r;
    if(head->item==client){
        r=head;
        head=head->next;
        free(r);
    }
    else{
        while(s->next!=NULL){
            if(s->next->item==client){
                r=s->next;
                s->next=s->next->next;
                free(r);
            }
            else
                s=s->next;
        }
    }
}

现在我尝试使用带有2指针的for来减少和压缩代码,但我无法弄清楚如何使其工作。 这是代码:

void delete_(Item client){
    link x,r,p;
    for(x=head;x!=NULL;p=x,x=x->next){
        if(x->item==client){
            r=x;
            p->next=x->next;
            free(r);
        }
    }
}

3 个答案:

答案 0 :(得分:1)

您可以使用以下附录

void delete( Item client )
{
    link current = head, previous = NULL;

    while ( current && current->item != client )
    {
        previous = current;
        current = current->next;
    }

    if ( current )
    {
        if ( !previous ) head = head->next;
        else previous->next = current->next;

        free( current );
    }
}

如果要删除成员item等于client的所有节点,那么确实可以使用for循环。

例如

void delete( Item client )
{
    for( link current = head, previous = NULL; current != NULL; )
    {
        if ( current->item == client )
        {
            link tmp = current;

            if ( previous != NULL ) 
            {
               previous->next = current->next;
               current = current->next;
            }
            else
            {
                head = current->next;
                current = head;
            }

            free( tmp );
        }
        else
        {
            previous = current;
            current = current->next;
        }
    }
}

答案 1 :(得分:1)

有两个错误点:

  • 如果第一个元素是需要删除的项目,则该项目的前一个不存在,并且代码p-> next = ...不是正确的操作。你应该改变列表的头部,这是正确的行动。
  • 当你删除当前项目(免费(r))时,如果你打电话给x = x->接下来你的程序可能会崩溃。您必须在删除之前备份x->。你需要改变的for循环

答案 2 :(得分:0)

删除项目时,必须知道要更新的指针。这意味着您必须知道列表中的上一个节点。弗拉德的答案通过保留一个额外的previous变量来做到这一点,你的第一个代码通过查看当前节点指向的指针来做到这一点。两者都必须将头部删除视为特例。

你的第二个代码试图简化代码,但是你会失去删除头部的特殊情况,并在删除后更新迭代器链接,你不应该这样做。 (您的原始代码正确地将更新放在else子句中。)

一种摆脱头部删除特殊情况的方法是通过指向节点指针的指针通过iterationg引入一级间接。该指针保存" previous"的地址。指针 - 前一节点的列表头或next指针。其余部分或多或少与原始代码相似,预计当前节点现在位于*l而不是l->next

void delete(Item client)
{
    link *l = &head;

    while (*l) {
        if ((*l)->client == client) {
            link r = *l;

            *l = (*l)->next;
            free(r);
        } else {
            l = &(*l)->next;
        }
    }
}

此代码会删除与client匹配的所有项目;我认为这是理想的行为。 (附加的间接也适用于插入。)