为什么打印单向链表时有一个虚拟节点?

Why there is a dummy node when I am printing a singly linked list?

为什么我的代码打印了一个额外的节点(垃圾值)? 我的代码有什么问题吗? 让我如何解决它。

void push(node **head_ref,int value)  //function to insert a new node on front of the list
{
    node *new_node=(node*)malloc(sizeof(node));
    new_node->data=value;
    new_node->next=*head_ref;
    *head_ref=new_node;
}

void printll(node *head)    //function to print the list
{
    node *temp = head;
    while(temp!=NULL)
    {
        printf("%d ",temp->data);
        temp=temp->next;
    }
}

实际输出:
45 88 24 34 77 0

预期输出:
45 88 24 34 77


完整代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cassert>

using namespace std;

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

void push(node **head_ref,int value)
{
    node *new_node=(node*)malloc(sizeof(node));
    new_node->data=value;
    new_node->next=*head_ref;
    *head_ref=new_node;
}

void printll(node *head)
{
    node *temp = head;
    while(temp!=NULL)
    {
        printf("%d ",temp->data);
        temp=temp->next;
    }

}

int main()
{
    node *head= (node*)malloc(sizeof(node));
    push(&head,77);
    push(&head,34);
    push(&head,24);
    push(&head,88);
    push(&head,45);
    printll(head);
    printf("\n");
    return 0;
}

您的设计中有一个虚拟节点(head 本身)。所以打印函数需要跳过那个虚拟节点。

当您使用 malloc 分配内存时,内存不会以任何方式初始化,它的内容是 不确定。这意味着当您分配第一个节点(这是一个不需要的虚拟额外节点)时,它的 next 指针不为空,并且取消引用这个不确定的指针会导致 未定义的行为 .

最简单的解决方案?考虑到你的代码比 C++ 更接近 C,一开始不要分配内存,而是创建一个指针 并将其初始化为 NULL:

node *head = NULL;

One 在 C++ 中正确的做法是根本不使用 malloc,而是使用 C++ 运算符 new 并添加一个 constructor 到初始化它的 node 结构:

struct node
{
    node() : data(0), next(nullptr) {}
    node(int d, node* n) : data(d), next(n) {}

    int data;
    node* next;
};

void push(node** head_ref, int value)
{
    *head_ref = new node(value, *head_ref);
}

...

int main()
{
    node* head = nullptr;
    ...
}

现在您可以创建一个新节点,它将具有 0 的初始 value,并且其 next 指针将为空指针。您还可以如上所示,使用特定的 valuenext.

创建并初始化一个新节点

[如果您的编译器不支持 C++11 nullptr 值,请将 nullptr 替换为 0]

而不是这个定义

node *head= (node*)malloc(sizeof(node));

你应该写得简单

node *head = NULL;

node *head = nullptr; // C++

否则你的程序有未定义的行为,因为分配给头部的节点没有初始化。

此外,如果它是 C++ 程序,您应该使用运算符 new 而不是 C 函数 malloc。例如函数 push 看起来像

void push( node * &head_ref, int value )
{
    head_ref = new node { value, head_ref };
}

并称赞

push( head, 77 );

考虑到您还必须编写一个函数来释放列表的所有分配内存。