将节点添加到列表的问题

issue with adding node to a list

我有一段代码,我试图在其中添加一个节点以从空链表创建列表。随后它不断添加到列表的末尾。我有一个代码块,只保留最后两个节点。假设如果我添加两个元素 - 10、11 它工作正常。但是当我执行 11、12、13、14 时,它只保留 13、14。我有一个工作正常的工作,但想知道是什么导致了这种行为。代码块如下。问题仅与 AddList 函数有关。

#include <stdio.h>
#include <stdlib.h>
    struct Node {
            int data;
            struct Node* next;
    };
    
    void AddList(struct Node** node, int value) {
            struct Node* new = (struct Node*)malloc(sizeof(struct Node));
            new->data = value;
            new->next = NULL;
            if (*node == NULL) {
                    *node = new;
                    return;
            }
            while ((*node)->next != NULL) {
                    *node = (*node)->next;
            }
            (*node)->next = new;            
            return;
    }
    void PrintList(struct Node** node) {
            printf("\n\n");
            if (node == NULL) {
                    printf("\n\nList is empty !! Nothing to Print. \n\n");
                    return;
            }
    
            while (*node != NULL) {
                    printf("%d--> ", (*node)->data);
                    *node = (*node)->next;
            }
            printf("\n\n");
            return;
    }
    
    void main() {
            struct Node* head = NULL;
            AddList(&head, 10);
            AddList(&head, 11);
            AddList(&head, 12);
            AddList(&head, 13);
            AddList(&head, 14);
            PrintList(&head);
    }

本次修改修正了问题:添加了一个新变量 struct Node* current

void AddList(struct Node** node, int value) {
        struct Node* new = (struct Node*)malloc(sizeof(struct Node));
        struct Node* current = *node;
        new->data = value;
        new->next = NULL;

        if (*node == NULL) {
                *node = new;
                return;
        }

        while(current->next != NULL) {
                current = current->next;
        }
        current->next = new;
        return;
}

您在函数 AddListPrintList 中都犯了同样的错误。这两个函数都通过引用接受指向头节点的指针,例如

AddList(&head, 14);
PrintList(&head);

因此,如果函数将指向的指针更改为头节点,那么它的值也会更改。

事实上,指向头节点的指针在函数内发生了变化。

在函数AddList这个循环

while ((*node)->next != NULL) {
        *node = (*node)->next;
        ^^^^^^^^^^^^^^^^^^^^^^
}

更改指向头节点的指针的值。

在函数PrintList中,由于这个while循环,指向头节点的指针甚至被设置为NULL

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

还有函数PrintListif语句中的条件

 if ( node == NULL) {
         printf("\n\nList is empty !! Nothing to Print. \n\n");
         return;
 }

没有意义。即指针节点可以等于NULL,但这并不意味着当前列表为空。

函数可以这样定义

int AddList( struct Node **head, int data ) 
{
    struct Node *new_node = ( struct Node* )malloc( sizeof( struct Node ) );
    int success = new_node != NULL;

    if ( success )
    {
        new_node->data = data;
        new_node->next = NULL;

        while ( *head ) head = &( *head )->next;

        *head = new_node;
    }

    return success;
}

void PrintList( const struct Node *head ) 
{
    printf("\n\n");
    if ( head == NULL ) 
    {
            printf("\n\nList is empty !! Nothing to Print. \n\n");
    }
    else
    {
        for ( ; head != NULL; head = head->next ) 
        {
            printf( "%d--> ", head->data );
        }
        printf("\n\n");
    }
}

不需要通过引用将指向头节点的指针传递给函数PrintList。即可以调用函数,例如

AddList( &head, 14 );
         ^^^^^

PrintList( head );
           ^^^^ 

如果你要在列表的尾部添加新节点,那么定义一个双向单链表会好得多。那就是您可以再引入一种结构,例如

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

struct List
{
    struct Node *head;
    struct Node *tail;
};

在这种情况下,将新节点添加到列表尾部的函数会更有效率,因为不需要遍历列表的所有节点。

请记住,根据 C 标准,函数 main 应声明为

int main( void )

而不是

void main()