【问题标题】:Delete elements from singly linked list从单链表中删除元素
【发布时间】:2015-01-19 13:06:12
【问题描述】:

我想从函数中的值指定的列表中删除一些元素。如果函数的 '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;
        }
    }
}

【问题讨论】:

  • 由于你是在del()中修改list,所以将其作为双指针传递。

标签: c algorithm list pointers


【解决方案1】:

您的调用函数无法知道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 可以有其他字段,例如用于快速附加到末尾的尾指针。您还可以跟踪列表长度。

【讨论】:

  • @pospeq 您可以在 del 函数中进行更改并返回 struct elem *,这样就不需要双指针了。保持你的head == list在这里完好无损并重新调整头部
  • @pospeq:我添加了一些其他方法来实现同样的效果。
  • 我特别喜欢拥有一个知道 head 的列表结构的方法。
猜你喜欢
  • 2018-05-23
  • 1970-01-01
  • 2020-10-29
  • 2018-07-08
  • 2017-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多