首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >链表删除节点,简单链表

链表删除节点,简单链表
EN

Stack Overflow用户
提问于 2020-04-28 04:43:16
回答 3查看 97关注 0票数 1

我正在尝试实现一个从链表中删除节点的函数。到目前为止,我只能删除列表的第一个节点(3)。

我试着从delete转到for循环,我认为内存分配不好,我已经挣扎了几天,我不明白,请帮我一点忙,这是我在大学里收到的话题。

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>

typedef struct nod
{
    int key;
    struct nod *urm;
} NOD;

NOD *first=0,*last=0;

void add(int x)
{
    NOD *p=(NOD*)malloc(sizeof(NOD));
    p->key=x;
    p->urm=0;
    if(0==first)
    {
        first=p;
        last=p;
    }
    else{
        last->urm=p;
        last=p;
    }
}

void delete(int x)
{
    NOD *q,*p;
    if(first->key==x)
    {
        p=first;
        first=first->urm;
        free(p);

    }
    else{
        for(p=q=first;p=0;q=p,p=p->urm)
        {
            if(p->key==x)
            {
            q->urm=p->urm;
            if(p==last)
            {
                last=q;
            }
            free(p);
            }
        }
    }
}

void show()
{
    for(NOD *p=first;p!=0;p=p->urm)
    {
        printf("%d ",p->key);
    }
    printf("\n");
}
int main()
{
    add(3);
    add(1);
    add(2);
    add(5);
    show();

    delete(2);
    show();

    return 0;
}
EN

回答 3

Stack Overflow用户

发布于 2020-04-28 04:59:52

对于初学者来说,您显示的代码不是C++代码。这是一个C代码。

当函数依赖于全局变量时,定义像firstlast这样的全局变量并不是一个好主意。在这种情况下,您不能在一个程序中创建多个列表。

至于函数delete,一般来说,它具有未定义的行为。可以为空列表调用它。

此外,在这个循环中

代码语言:javascript
复制
for(p=q=first;p=0;q=p,p=p->urm)

条件表达式中有一个拼写错误。您正在使用赋值运算符,而不是比较运算符。

当列表只包含一个节点时,函数忽略大小写,因为在这种情况下,它不会更新最后一个节点。

不过,使用您的方法时,函数delete可能如下所示。

代码语言:javascript
复制
void delete(int x)
{
    if ( first )
    {
        if ( first->key == x )
        {
            NOD *tmp = first;
            first = first->urm;

            free( tmp );

            if ( first == NULL ) last = NULL;
        }
        else
        {
            NOD *p = first;
            while ( p->urm != NULL && p->urm->key != x )
            {
                p = p->urm;
            }

            if ( p->urm != NULL )
            {
                NOD *tmp = p->urm;
                p->urm = p->urm->urm;

                free( tmp );

                if ( p->urm == NULL ) last = p;
            }
        }
    }
}     

这是一个演示程序。

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>

    typedef struct nod
    {

    int key;
    struct nod *urm;
    } NOD;

    NOD *first=0,*last=0;


    void add(int x)
    {

    NOD *p=(NOD*)malloc(sizeof(NOD));
    p->key=x;
    p->urm=0;
    if(0==first)
    {
        first=p;
        last=p;
    }
    else{
        last->urm=p;
        last=p;
    }

    }

void delete(int x)
{
    if ( first )
    {
        if ( first->key == x )
        {
            NOD *tmp = first;
            first = first->urm;

            free( tmp );

            if ( first == NULL ) last = NULL;
        }
        else
        {
            NOD *p = first;
            while ( p->urm != NULL && p->urm->key != x )
            {
                p = p->urm;
            }

            if ( p->urm != NULL )
            {
                NOD *tmp = p->urm;
                p->urm = p->urm->urm;

                free( tmp );

                if ( p->urm == NULL ) last = p;
            }
        }
    }
}  

    void show()
    {
        for(NOD *p=first;p!=0;p=p->urm)
        {
            printf("%d ",p->key);
        }
        printf("\n");
    }
    int main()
    {
        add(10);
        add(20);
        add(30);
        add(40);

        show();

        delete(30);
        show();

        add( 50 );
        add( 60 );
        add( 70 );
        add( 80 );
        show();

        delete(80);
        show();


    return 0;
    }

它的输出是

代码语言:javascript
复制
10 20 30 40 
10 20 40 
10 20 40 50 60 70 80 
10 20 40 50 60 70 
票数 1
EN

Stack Overflow用户

发布于 2020-04-28 06:43:14

通过同时使用指向NOD的指针和指向NOD的指针遍历列表,可以大大简化从列表中删除节点的过程。这允许您将当前地址处的节点设置为node->urm,而无需跟踪列表中的前一个节点,例如

代码语言:javascript
复制
/** delete node with key v from list (for loop) */
void delete (int v)
{
    NOD **ppn = &first;        /* pointer to pointer to first*/
    NOD *pn = first;            /* pointer to first */

    for (; pn; ppn = &pn->urm, pn = pn->urm) {
        if (pn->key == v) {
            *ppn = pn->urm;     /* set node at address to next node */
            free (pn);          /* free deleted node */
            break;
        }
    }
}

有关除指向节点的指针之外还使用节点地址的优点的进一步讨论,请参阅Linus on Understanding Pointers

票数 0
EN

Stack Overflow用户

发布于 2020-04-28 05:09:26

我认为您的for循环条件在delete函数中是不正确的:

代码语言:javascript
复制
for(q=first, p=first->urm; p!=0; q=p, p=p->urm)

只要改变条件,它就应该可以工作了。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61468120

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档