Что не так с моей реализацией Singlely Linked List?

Вот попытка реализации односвязного списка.
Проблема в том, что при попытке распечатать список 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;
}

Спасибо всем большое!

5 ответов

Решение

Когда вы получите размер указателя, например, например, sizeof(list), тогда вы получите размер указателя, а не то, на что он указывает. Ты должен сделать sizeof *list вместо.

Следующая проблема заключается в следующем:

list = list->next;

list = malloc(sizeof(list));

Первая строка делает list указать, где list->next указывает, что NULL, Следующая строка переназначает переменную так, чтобы она указывала на недавно выделенную память. Нигде вы фактически не связываете новый узел в списке.

Вместо этого я предлагаю что-то вроде этого:

list = root;

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

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

Просто перепроверьте свой код специально для этих двух утверждений:

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;

Вы должны сделать это изменение для каждого вашего узла.

Существует проблема в том, как вы связываете разные узлы. Посмотрите внимательно на этот раздел кода:

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;

Вы должны назначить с памятью 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

Конечно next элемент вашего корневого узла всегда NULL, так как вы не назначаете ему никакого другого значения. Что-то вроде root->next = another_node пропал, отсутствует.

Есть несколько хороших учебных пособий, которые могут помочь вам в этой реализации, например,

  1. learn-c.org
  2. cprogramming.com
Другие вопросы по тегам