簡體   English   中英

鏈表和結構體數組之間的區別?

[英]Difference between linked lists and array of structs?

這些代碼段有什么區別?

1)

struct MyStruct
{
    int num;
} ms[2];

ms[0].num = 5;
ms[1].num = 15;

2)

struct MyStruct
{
    int num;
    MyStruct *next;
};

MyStruct *ms = new MyStruct;
ms->num = 5;
ms->next = new MyStruct;
ms->next->num = 15;

一般而言,我可能對鏈接列表和列表有些困惑,它們對某些東西特別有用嗎? 請給我更多解釋。

您的第一個定義...

struct MyStruct
{
    int num;
} ms[1];

...創建一個具有單個元素的靜態分配數組。 您無法在程序運行時更改數組的大小; 此數組永遠不會包含一個以上的元素。 您可以通過直接索引訪問數組中的項目; 例如,假設您已定義了適當大小的數組,則ms[5]將為您提供數組中的第六個元素(請記住,C和C ++數組的索引為0,因此第一個元素為ms[0] )。

您的第二個定義...

struct MyStruct
{
    int num;
    MyStruct *next;
};

...創建一個動態分配的鏈表。 該列表的內存是在運行時動態分配的,並且鏈接列表可以在程序的生命周期內增長(或縮小)。 與數組不同,您不能直接訪問列表中的任何元素。 要到達第六個元素,您必須從第一個元素開始,然后重復5次。

關於代碼中的錯誤,第一個構造靜態數目的MyStruct元素並將它們存儲在ms數組中,因此ms是MyStruct結構的數組,當然,這意味着您只能將其包含2個元素,稍后您不能將任何其他元素添加到ms數組,盡管您限制了MyStruct元素的數量,但是在第二種情況下,當您擁有鏈接列表時,可以根據需要鏈接任意數量的MyStruct元素,這將導致動態數量在MyStruct元素中,第二種情況使您可以在運行時添加任意數量的MyStruct,第二種情況在概念上應在內存中看起來像這樣:

[ MyStruct#1 ] ----> [ MyStruct#2 ] ----> [ NULL ]

例如,NULL可能是MyStruct#3,而第一個是:

[ MyStruct#1 ] ----> [ MyStruct#2 ]

就是這樣,不能添加MyStruct#3。

現在,讓我們看一下您編寫的代碼:

struct MyStruct
{
    int num;
} ms[1];

ms[1]的確意味着為我創建一個包含MyStruct元素的ms數組。
接下來的代碼假定您創建了兩個:

ms[0].num = 5;
ms[1].num = 15

因此應該是:

struct MyStruct
{
    int num;
} ms[2];

它將正常工作! 並記住我為此所做的簡單說明:
[ MyStruct#1 ] ----> [ MyStruct#2 ]

第二種情況:

struct MyStruct
{
    int num;
    MyStruct *next;
};

MyStruct *ms = new MyStruct;
ms->num = 5;
ms->next = new MyStruct;
ms->next->num = 15;

如果將源代碼另存為.cpp則此代碼將使用new的C ++運算符,並且可以將其編譯為C ++應用程序而不會出錯,而對於C,語法應如下更改:

struct MyStruct
{
    int num;
    MyStruct *next;
};

MyStruct *ms = (MyStruct *) malloc(sizeof MyStruct);
ms->num = 5;
ms->next = (MyStruct *) malloc(sizeof MyStruct);
ms->next->num = 15;

並且不要忘記在malloc()函數中包含#include <stdlib.h> ,您可以在此處閱讀有關此函數的更多信息。
作為第一種情況,請記住我對鏈表的說明:
[ MyStruct#1 ] ----> [ MyStruct#2 ] ----> [ NULL ]

NULL實際上是ms-> next MyStruct結構的下一個元素,為解釋它,我們還記得ms-> next是MyStruct的指針,我們在堆中分配了一個空間,所以現在它指向一個內存塊具有相同大小的MyStruct結構 最后,這是一個Stackoverflow問題,涉及何時使用鏈表以及何時使用數組,因此您可以確切地知道為什么世界各地的人們有時更喜歡鏈表而其他時候更喜歡數組。

哦,我的朋友,有數十種不同類型的數據結構,它們幾乎只容納一堆num值或其他值。 程序員不只是對所有內容使用數組的原因是所需內存量的差異以及執行對您的特定需求最重要的任何操作的簡便性。

鏈接列表在添加或刪除單個項目時非常快。 折衷方案是在列表中間找到一個項目相對較慢,並且next指針需要額外的內存。 適當大小的數組在內存中非常緊湊,您可以非常快速地訪問中間的項目,但是要在末尾添加新項目,您必須事先知道最大元素數,這通常是不可能的或浪費的內存,或者重新分配更大的數組並復制所有內容,這很慢。

因此,某人不知道列表需要多大,而大多數人只需要處理列表開頭或結尾的項目,或者總是循環遍歷整個列表,並且比起保存列表來,他更關心執行速度。幾個字節的內存,很可能會在數組上選擇一個鏈表。

一般而言,列表和數組之間的主要區別是:

  • 列表中的順序是明確的 每個元素都存儲前一個/后一個元素的位置。 數組中的順序是隱式的 假定每個元素都具有一個前一個/后一個元素。 請注意,單個列表可能包含多個順序。 例如,您可能會遇到類似

     struct dualList { T data1; K data2; struct dualList *nextT; struct dualList *nextK; }; 
    這樣您就可以通過兩種不同的方式對同一列表進行排序,一種是通過data1 ,另一種是通過data2

  • 相鄰的數組元素位於相鄰的內存位置; 相鄰列表元素不必位於相鄰位置。

  • 數組提供對元素的隨機訪問; 列表僅提供順序訪問(即,您必須沿着列表查找元素)。

  • 數組(通常)的長度固定為1-向數組中添加元素或從數組中刪除元素不會改變數組的大小。 列表可以根據需要增加或縮小。

列表非常適合維護動態更改的值序列,尤其是在值需要保持順序的情況下。 由於您不能隨機訪問元素,因此它們對於存儲需要快速且頻繁地檢索的相對靜態數據並不那么熱。


  1. 您可以通過動態聲明內存來解決此問題,然后根據需要使用realloc調整該內存塊的大小,但是需要謹慎進行,並且可能有點PITA。

當元素順序很重要並且元素的數量事先未知時,鏈接列表很有用。 此外,訪問鏈表中的元素需要O(n)時間。 在列表中查找元素時,最壞的情況是,您必須查看列表中的每個元素。

對於數組,必須事先知道該數字。 在C語言中定義數組時,必須傳遞其大小。 另一方面,訪問數組元素需要O(1)時間,因為可以通過索引尋址元素。 對於鏈接列表,這是不可能的。

但是,這不是與C ++有關的問題,因為鏈接列表和數組的概念並不與C ++相關。

數組是連續的預分配內存塊,而鏈表是通過指針( *next )彼此鏈接的運行時分配的( malloc )內存(不一定是連續的)內存的集合。 如果您在編譯時知道需要存儲的最大元素數量,則通常將使用structs數組。 但是,如果您不知道將需要存儲的最大元素數量,則structs的鏈接列表很有用。 同樣,通過鏈接列表,元素的數量可以更改,添加和刪除元素。

暫無
暫無

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

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