c - 从单链表中删除元素

标签 c algorithm list pointers

我想从函数中的值指定的列表中删除一些元素。如果函数的“val”等于列表中的第一个元素,我的函数将不起作用。否则效果很好。有什么想法吗?

struct elem {
    int val;
    struct elem *next;
};

void del(struct elem *list, int val) {
    struct elem* tmp = list;
    struct elem* prev = NULL;

    while (tmp != NULL) {
        if (tmp->val == val) {
            if (prev == NULL) {
                tmp = tmp->next;
                free(list);
                list = tmp;
            } else {
                prev->next = tmp->next;
                free(tmp);
                tmp = prev->next;
            }
        } else {
            prev = tmp;
            tmp = tmp->next;
        }
    }
}

最佳答案

您的调用函数无法知道 list 已更新。它甚至会继续引用相同的 list,但已被删除。这不好。

一种解决方案是将列表作为 struct elem **list 传递:

void del(struct elem **list, int val) {
    struct elem* tmp = *list;
    struct elem* prev = NULL;

    while (tmp != NULL) {
        if (tmp->val == val) {
            if (prev == NULL) {
                tmp = tmp->next;
                free(*list);
                *list = tmp;
            } else {
                prev->next = tmp->next;
                free(tmp);
                tmp = prev->next;
            }
        } else {
            prev = tmp;
            tmp = tmp->next;
        }
    }
}

编辑:还有其他解决方案。您可以返回新的列表指针:

struct elem *del(struct elem *list, int val) { ... }

你这样调用它:

list = del(list, 12);

这个解决方案的缺点是list在调用中有些冗余,省略返回值是合法的,因此实际上并没有更新列表。

我喜欢的解决方案是为您的列表定义一个控制结构。目前,它只包含头指针:

struct list {
    struct elem *head;
};

然后,您对列表进行操作的函数将指向此结构的指针作为参数:

void del(struct list *list, int val) {
    struct elem* tmp = list->head;
    struct elem* prev = NULL;

    while (tmp != NULL) {
        if (tmp->val == val) {
            if (prev == NULL) {
                tmp = tmp->next;
                free(list->head);
                list->head = tmp;
            } else {
                prev->next = tmp->next;
                free(tmp);
                tmp = prev->next;
            }
        } else {
            prev = tmp;
            tmp = tmp->next;
        }
    }
}

struct list 可以有额外的字段,例如用于快速附加到末尾的尾指针。您还可以跟踪列表长度。

关于c - 从单链表中删除元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28025304/

相关文章:

将客户端连接到服务器?

c - 文件输入 int 字符串 c

python - 合并排序python无限循环

python - 与内置函数命名冲突

c - C 中的命名空间库

c - 将包含数据的文本文件读取到链接列表中

python - 从列表范围中获取随机项目

javascript - 增加或减少色彩饱和度

c# - 如何删除计数最低的子列表并保留主列表中计数最高的子列表?

java - 使用ListIterator删除重复项