1. 程式人生 > >線性表之順序表與單鏈表的區別與優缺點

線性表之順序表與單鏈表的區別與優缺點

這裡比較的是基於C語言實現的順序表與單鏈表,與其他語言的實現可能會有差異,但我相信語言是相通的,它們的實現機制應該也差不多。 

1、What 
什麼是順序表和單鏈表 
①順序表: 
順序表是在計算機記憶體中以陣列的形式儲存的線性表,是指用一組地址連續的儲存單元依次儲存資料元素的線性結構。只要確定了起始位置,表中任一元素的地址都通過下列公式得到:LOC(ai)=LOC(a1)+(i-1)*L  1≤i≤n 其中,L是元素佔用儲存單元的長度。

這裡寫圖片描述

②單鏈表: 
單鏈表是一種鏈式存取的資料結構,用一組地址任意的儲存單元存放線性表中的資料元素。它的資料是以結點(型別一般為結構體)來表示的,每個結點的構成:資料(型別為要儲存的資料的型別) + 指標(結構體指標),資料就是連結串列裡具體要儲存的東西,指標就是用來把每個節點都連線起來,使它們形成一個鏈狀。

結點: 
這裡寫圖片描述

連結串列:

這裡寫圖片描述

這裡寫圖片描述

2、Compare 
二者的優缺點比較

①空間上的比較(Space) 
a. 空間的開闢: 
順序表的實現一般是實現連續開闢一段空間,然後在進行資料的增刪查改(靜態順序表),所以順序表一般是固定空間大小的;而單鏈表則是一次只開闢一個結點的空間,用來儲存當前要儲存的資料及指向下一個結點或NULL的指標,所以單鏈表的空間大小時動態變化的。(當然,順序表也可以在初始化時利用malloc函式來開闢一塊空間,每當空間不夠用時,再用realloc來把當前空間擴容成2倍,從而也能實現空間的動態變化(動態順序表))。 
、 
b. 空間的使用: 
當我們不知道要儲存多少資料時,用順序表來開闢的空間如果太大,就會造成一定程度上的浪費,而用單鏈表是實現時,因為是每需要儲存一個數據時,才開闢一個空間,雖然有非資料項的指標佔空間,但相比順序表來說,浪費不是那麼明顯;反之,當我們知道儲存的資料的數量時,用順序表來開闢對應的空間大小,來儲存資料,因為順序表中每個元素的儲存密度為 1,就完全不會有浪費的空間,而用單鏈表,因為每個結點都會有非資料項得指標,那麼就會造成空間的浪費。再者,編譯器會為每個程式從記憶體上分配一段空間,給該程式使用。然而我們每次開闢空間時都是在隨機的位置開闢的,那麼使用單鏈表,就會多次的在程式分配到的這塊空間上開闢空間,因為每次都是開闢的位置都是隨機的,那麼可能會把這塊空間搞得七零八碎,出現很多小的一般使用不到的碎片空間,這樣很大程度上造成了空間的浪費,而使用順序表的話,不會經常開闢空間,這樣就減少了碎片空間的出現,那麼就一定程度上節省了空間。 
這裡寫圖片描述

這裡寫圖片描述

c. 對CPU快取記憶體的影響: 
因為順序表的空間一般是連續開闢的,而且一次會開闢儲存多個元素的空間,所以在使用順序表時,可以一次把多個數據寫入快取記憶體,再寫入主存,順序表的CPU快取記憶體效率更高,且CPU流水線也不會總是被打斷;而單鏈表是每需要儲存一個數據才開闢一次空間,所以每個資料儲存時都要單獨的寫入快取記憶體區,再寫入主存,這樣就造成了,單鏈表CPU快取記憶體效率低,且CPU流水線會經常被打斷。

從這兒看,貌似順序表要更好一些,真是如此嗎?繼續看下去。

②時間上的比較(Time)

a. 訪問隨機元素的時間複雜度: 
因為順序表的結構就像是陣列一樣,可以用下標來訪問它的元素,所以它的元素是支援隨機訪問的;相比之下,單鏈表的資料是鏈式儲存的,它的元素是不支援隨機訪問的,想要知道某個元素,只能從頭結點開始遍歷整個連結串列,知道找到了該元素為止。因此順序表訪問隨機元素的時間複雜度是O(1),而單鏈表訪問隨機元素的平均時間複雜度是O(n)。

b. 隨機位置插入、刪除元素的時間複雜度: 
因為順序表的元素是連續儲存的,因此要在特定位置插入、刪除元素需要把它之後的元素全部後移或前移一個元素的位置,時間開銷很大;而單鏈表在插入或刪除元素時,只需要改變它的前驅元素及插入或刪除元素的指向即可。因此,順序表在插入隨機位置插入、刪除元素的平均時間複雜度是O(n),單鏈表在插入隨機位置插入、刪除元素的時間複雜度是O(1)。

一般來說線性表(順序表和單鏈表都屬於線性表)的插入刪除操作會被執行的頻繁一些,因此,使用單鏈表的頻率較大。

3、Summary

綜合上述所言,順序表和單鏈表各有各的優缺點,使用哪一種會好一些要結合具體的問題而言,不能一概而論。 
比如: 
在查詢操作使用的比較頻繁時,使用順序表會好一些;在插入、刪除操作使用的比較頻繁時,使用單鏈表會好一些。

PS:使用順序表和連結串列都必須滿足每個元素佔有相同大小的記憶體空間,並且這個大小是固定的