簡體   English   中英

鏈表實現的區別

[英]Linked list implementations difference

對於以下鏈接列表聲明,

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

typedef struct list
{
   int val;
   struct list *next;
} list;


void destroy (list *l)
{
    if (l)
    {
        destroy (l->next);
        free (l);
    }
}

為什么以下主要工作

int main()
{
    list *test;
    list *ptr1, *ptr2;
    int i;
    test = malloc (sizeof (list));
    test->val = 0;
    ptr2 = test;
    for (i = 1; i <= 10; i++)
    {
        ptr1 = (list *) malloc (sizeof (list));
        ptr1->val = i;
        ptr2->next = ptr1;
        ptr2 = ptr1;
    }
    ptr1 = test;
    while (ptr1)
    {
        printf ("%d\n", ptr1->val);
        ptr1 = ptr1->next ;
    }
    destroy (test);
    return 0;
}

而這個甚至沒有創建列表(它僅創建一個節點)?

int main()
{
    list *test;
    list *ptr;
    int i;
    test = malloc (sizeof (list));
    test->val = 0;
    ptr = test->next;
    for (i = 1; i <= 10; i++)
    {
        ptr = (list *) malloc (sizeof (list));
        ptr->val = i;
        ptr = ptr->next;
    }
    ptr = test;
    while (ptr)
    {
        printf ("%d\n", ptr->val);
        ptr = ptr->next ;
    }
    destroy (test);
    return 0;
}

他們不使用相同的邏輯嗎?

編碼

ptr = test->next;
for (i = 1; i <= 10; i++)
{
    ptr = (list *) malloc (sizeof (list));
    ptr->val = i;
    ptr = ptr->next;
}

首先獲取一份test->next副本,但從不給test->next本身分配任何內容。 因此,從test開始的列表只有一個項目。 更糟糕的是,該項目具有未初始化的next指針,因此嘗試在列表上進行迭代的代碼幾乎肯定會崩潰。

正如其他答案所暗示的那樣,對於每個新分配的節點重復此模式。

為了回答您的意見,使第二個功能起作用的最佳方法是使其更像第一個(起作用的)版本。 我已將其中的變量重命名以使其更清晰

list *head;
list *next, *curr;
int i;
head = malloc (sizeof(*head));
head->val = 0;
curr= head;
for (i = 1; i <= 10; i++)
{
    next = malloc (sizeof(*next));
    next->val = i;
    curr->next = next;
    curr= next;
}
curr= head;

在第二主要期間

ptr = test->next;

您正在嘗試訪問test-> next,而沒有為其分配內存。您可以嘗試按以下方式更改代碼以獲取第二個主要工作

test = malloc (sizeof (list));
    test->val = 0;
    test->next = (list *) malloc (sizeof (list));
    ptr = test->next;
    for (i = 1; i <= 10; i++)
    {
        ptr->val = i;
    ptr->next = (list *) malloc (sizeof (list));
        ptr = ptr->next;
    }

看起來在第一個示例中ptr2ptr2將先前創建的節點保存在列表中,因此可以將其重寫

last_created_node = test;
for (i = 1; i <= 10; i++)
{
    // create new node
    new_node = (list *) malloc (sizeof (list));
    new_node ->val = i;
    // chain newly created node onto list so far
    // make last created node point to new node
    last_created_node->next = new_node ;
    // last created node is now new node
    last_created_node = new_node ;
}
// terminate the list
last_created_node->next = 0;

在您提供的第二個代碼示例中,沒有等效的方法將新節點鏈接到鏈上。 正如其他人所評論的,統一內存也存在問題。 如上面示例的最后一行所示,添加終止條件會很好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM