我的单链表实现有什么问题?

What is wrong with my Singly Linked List implementation?

这是实现单向链表的尝试。
问题是当尝试使用 while (traverse != NULL) 打印列表时,程序输出 1,即第一个节点的数据,但不打印所有其他节点的数据。我是否错误地链接了节点,如果是,在哪里?

#include <stdio.h>
#include <stdlib.h>

typedef struct node {
    int data;
    struct node *next;
} Node;

struct node *root;

int main(void) {
    Node *list, *traverse;
    /* root will always be the first of the list */
    root = malloc(sizeof(*list));

    list = root;

    list->data = 1;
    list->next = NULL;
    list = list->next;

    list = malloc(sizeof(*list));
    list->data = 2;
    list->next = NULL;
    list = list->next;

    list = malloc(sizeof(*list));
    list->data = 3;
    list->next = NULL;
    list = list->next;

    list = malloc(sizeof(*list));
    list->data = 4;
    list->next = NULL;
    list = list->next;

    list = malloc(sizeof(*list));
    list->data = 5;
    list->next = NULL;
    list = list->next;

    traverse = root;

    while (traverse != NULL) {
        printf("%d\n", traverse->data);
        traverse = traverse->next;
    }   
    return 0;
}

输出:

$ gcc main.c && ./a.out
1


预期输出:

$ gcc main.c && ./a.out
1
2
3
4
5

更新: 正如你们所有人所建议的那样,我已经更新了我的源文件:

#include <stdio.h>
#include <stdlib.h>

typedef struct node {
    int data;
    struct node *next;
} Node;

struct node *root;

int main(void) {
    Node *list, *traverse;
    /* root will always be the first of the list */
    root = malloc(sizeof(*list));

    list = root;

    list->data = 1;
    list->next = malloc(sizeof(*list));

    list = list->next;
    list->data = 2;
    list->next = malloc(sizeof(*list));

    list = list->next;
    list->data = 3;
    list->next = malloc(sizeof(*list));

    list = list->next;
    list->data = 4;
    list->next = malloc(sizeof(*list));

    list = list->next;
    list->data = 5;
    list->next = NULL;

    traverse = root;

    while (traverse != NULL) {
        printf("%d\n", traverse->data);
        traverse = traverse->next;
    }   
    return 0;
}

非常感谢大家!

当您获得指针的大小时,例如sizeof(list),那么你得到的是 指针 的大小,而不是它指向的内容。您应该改为 sizeof *list

下一个问题是:

list = list->next;

list = malloc(sizeof(list));

第一行让list指向list->next指向的地方,也就是NULL。下一行 重新分配 变量以指向一些新分配的内存。你实际上没有link将新节点放入列表中。

我建议改为这样:

list = root;

list->data = 1;
list->next = malloc(sizeof *list);
list = list->next;

list->data = 2;
// etc...

您链接不同节点的方式存在问题。仔细看这段代码:

list->data = 1;
list->next = NULL;
list = list->next;

list = malloc(sizeof(*list));
list->data = 2;
list->next = NULL;

您应该将新节点分配给前一个节点的下一个节点。但是当你这样做时 list = list->next。您的列表变量变为 NULL。相反,你应该这样做:

list->data = 1;
list->next = NULL;

list->next = (node *)malloc(sizeof(list));
list = list->next;
list->data = 3;
list->next = NULL;


list->next = (node *)malloc(sizeof(list));
list = list->next;
list->data = 4;
list->next = NULL;

当然,您的根节点的 next 项始终是 NULL,因为您没有为其分配任何其他值。 root->next = another_node 之类的东西丢失了。

有一些很好的教程可以帮助您实现此实现,例如

  1. learn-c.org
  2. cprogramming.com

您应该为新节点分配 malloc 内存:

#include<stdio.h>
#include <stdlib.h>

struct node {
    int data;
    struct node *next
};

int main(void) {
    struct node *root, *list;
    int i;
    root = malloc(sizeof(struct node));
    list = root;
    root->next = NULL;

    list->data = 1;
    list->next = malloc(sizeof(struct node));
    list = list->next;

    list->data = 2;
    list->next = malloc(sizeof(struct node));
    list = list->next;

    list->data = 3;
    list->next = malloc(sizeof(struct node));
    list = list->next;

    list->data = 4;
    list->next = malloc(sizeof(struct node));
    list = list->next;

    list->data = 5;
    list->next = malloc(sizeof(struct node));
    list = list->next;

    list->next = NULL;
    while (root->next != NULL) {
        printf("%d\n", root->data);
        root = root->next;
    }
}

测试

1
2
3
4
5

只需针对这两个语句重新检查您的代码:

list->next = NULL; list = list->next;

这里list->next指向NULL。你指向 list = list->next;你的假设在这里是不正确的。因此,您没有正确获取下一个元素。

首先为list->next分配内存,然后尝试指向那里。理想情况下,这不是我做事的方式。然而,为了纠正您的逻辑,我正在编写以下代码行:

list->data = 1;
list->next = malloc(sizeof(*list));
list = list->next;

您必须为每个节点进行此更改。