1. 程式人生 > >資料結構之——陣列和連結串列

資料結構之——陣列和連結串列

1. 陣列

1.1 陣列為什麼從零編號?

陣列名代表陣列的首地址,陣列的下標其實代表陣列中某個元素相對首地址的偏移量,陣列的第一個元素是零偏移,因此從 0 開始。

上面其實也只是一個解釋, C 語言設計者用零開始編號,後來的各種語言也便紛紛效仿,因此就形成了這個習慣。

1.2 陣列的特點?

  • 陣列是一種線性結構,在記憶體上按順序存放,支援隨機訪問,但需要足夠的連續記憶體空間。在陣列中增加或者刪除元素時需要大量的移動操作,效率較低。

  • 警惕陣列越界,對陣列進行越界訪問時就相當於在其他未知記憶體上進行了操作,這些區域可能 原本存放著重要的系統資訊或者其他資料,錯誤操作會對程式帶來無法估計的結果。

  • 容器支援動態擴容,且一般封裝了許多操作的方法,但如果事先知道陣列大小,或者表示多維資料,還是可以考慮使用陣列這種資料結構。


2. 連結串列

2.1 連結串列的特點?

  • 不需要連續的記憶體,通過指標的關聯可以任意存放在零散的空間上。在連結串列中插入或者刪除資料比較方便,只需要更改相鄰兩個節點即可,但查詢某一特定元素效率較低,只能從頭指標開始一個一個地按照順序訪問

2.2 常見連結串列分類?

  • 單鏈表
    單鏈表

單鏈表只支援一個方向的訪問,第一個節點稱為頭結點,最後一個節點稱為尾結點。

  • 迴圈連結串列
    迴圈連結串列

迴圈連結串列是一種特殊的單向連結串列,其尾結點指向頭結點,從鏈尾訪問鏈頭比較方便。

  • 雙向連結串列
    雙向連結串列

雙向連結串列的每一個結點同時指向其前面的結點和其後面的結點,因此可以雙向訪問,但兩個指標要佔用更多的記憶體空間。

在向連結串列中插入或者刪除某個結點時,我們需要知道該結點的前向結點,這時候,雙向連結串列就顯示出其優勢來了。

  • 雙向迴圈連結串列
    雙向迴圈連結串列

3. 陣列 VS 連結串列

  • 插入、刪除元素時時間複雜度,陣列為 O (

    n ) O(n) ,連結串列為 O ( 1 ) O(1)

  • 隨機訪問時間複雜度,陣列為 O ( 1 ) O(1) ,連結串列為 O ( n ) O(n)

  • 陣列簡單易用,還可以藉助 CPU 的快取機制,預讀資料,訪問效率更高,但一經申請就大小固定。

  • 連結串列本身沒有大小的限制,支援動態擴容,但每個結點都需要額外的空間存放指標,頻繁的刪除和插入操作還會造成記憶體碎片。


4. 連結串列的一些注意事項

  • 指標和引用都可以看作是變數的地址,通過地址可以訪問到變數。

  • 警惕指標丟失和記憶體洩露。連結串列中丟失了某一結點的指標,其後所有的資料都會丟失,另外,刪除節點時一定記得手動釋放記憶體。

  • 利用哨兵簡化實現難度。沒有哨兵,在頭結點插入新的結點和在中間位置插入新的節點操作可能會不一樣。但引入哨兵後就只有一種情況,可以簡化實現難度。

  • 留意邊界條件,重點考慮連結串列為空、連結串列只有一個結點和連結串列頭尾結點的處理情況。

參考資料-極客時間專欄《資料結構與演算法之美》

獲取更多精彩,請關注「seniusen」!
seniusen