C 删除链表中的节点

C delete node in a linked list

我有这个程序,它具有创建列表的功能,如果节点的值等于函数 delete_node() 的参数 x 则删除节点,然后打印链表节点。创建和打印工作正常,但我无法删除值为 x 的节点。我得到原始列表或空白列表。

#include <stdio.h>

struct list {
    int value;
    struct list *next;
};

struct list *create_list(struct list *l, int x) {

    //allocate memory for new tmp node
    struct list *tmp = malloc(sizeof(struct list));

    tmp->value = x;

    //tmp shtohet ne koke te listes
    tmp->next = l;

    //l behet koka e listes
    l = tmp;

    return l;
}

struct list *delete_node(struct list *l, int x) {

    while (l) {
        if (l->value == x) {
            //printf("%d", x);
            struct list *tmp = malloc(sizeof(struct list));

            tmp->value = l->next->value;
            tmp->next = l->next->next;
            l = tmp;

            printf("%d ", tmp->value);

        }

        l = l->next;
    }

    return l;
}

int main() {

    struct list *l = NULL;

    for (int i = 5; i > -6; --i)
        l = create_list(l, i);

    l = delete_node(l, 3);

    while (l) {
        printf("%d ", l->value);
        l = l->next;
    }

    printf("\n");

    return 0;
}

这是对有问题的代码的修复。

struct list *delete_node(struct list *l, int x) {
    struct list *prev, *retval=l;
    while (l) {
        if(l->value == x) {
            if(l==retval) {
                retval=l->next;
                free(l);
                l=retval;
            } else {
                prev->next=l->next;
                free(l);
                l=prev;
            }
        }
        prev = l;
        l = l->next;
    }

    return retval;
}

您不需要分配更多内存来丢弃不需要的节点。这样做会严重泄漏内存。

您需要跟踪列表的头部。这就是 retval 的用途。如果 x 未找到或在非头节点中找到,您将 return 相同的头。如果在头节点中找到 x,您将 return 下一个节点。

您还需要跟踪前一个节点,以便能够告诉前一个节点当前节点将被释放。这对于单个 link 列表是必需的。

删除的关键是保持对之前模式的跟踪。

通过以 "fake" 头节点开始,简化了 while 循环。

  struct list *delete_node(struct list *l, int x) {
    struct list start;  // Code only uses the next field
    start.next = l;
    struct list *p = &start;
    while (p->next) {
      struct list *q = p->next;
      if (q->value == x) {
        p->next = q->next;
        free(q);
        break;
        }
      p->next = q;
    }
    return start.next;
  }