資料結構之鍊錶

2022-09-16 22:27:23 字數 2354 閱讀 8292

資料需要一塊連續的記憶體空間來儲存,對記憶體的要求比較高。而鍊錶恰恰相反,它並不需要一塊連續的記憶體空間,它通過「指標」將一組零散的記憶體塊串聯起來使用。

最常見的鍊錶:單鏈表、雙鏈表、和迴圈鍊錶。

單鏈表

結點:除了儲存資料之外,還要記錄鏈上的下乙個節點的位址,如下圖,我們把這個記錄下個結點位址的指標叫作後繼指標 next

頭結點:用來記錄鍊錶的基位址。尾結點:指向乙個空位址null

針對鍊錶的插入和刪除操作,只需考慮相鄰結點的指標改變,所以對應的時間複雜度是o(1)。

鍊錶想要隨機訪問第k個元素,就沒有陣列那麼高效,鍊錶的資料並非連續儲存的,所以無法像陣列那樣,根據首位址和下標通過定址公式就能直接計算出對應的記憶體位址,而是要根據指標乙個結點乙個結點的一次遍歷,直到找到相應的結點。需要o(n)時間複雜度

迴圈鍊錶是一種特殊的單鏈表。它和單鏈表唯一的區別就在尾結點。迴圈鍊錶的尾結點指標是指向鍊錶的頭結點

當處理的資料具有環形結構特點時,就特別適合採用迴圈鍊錶。

雙向鍊錶

雙向鍊錶支援雙向遍歷,它需要額外的兩個空間來儲存後繼結點和前驅結點的位址。

時空替換思想:「用空間換時間」 與 「用時間換空間」

當記憶體空間充足的時候,如果我們更加追求**的執行速度,我們就可以選擇空間複雜度相對較高,時間複雜度小相對較低的演算法和資料結構,快取就是空間換時間的例子。如果記憶體比較緊缺,比如**跑在手機或者微控制器上,這時,就要反過來用時間換空間的思路。

陣列缺點

鍊錶缺點

快取淘汰策略

先進先出策略fifo(first in,first out)、最少使用策略lfu(least frequently used)、最近最少使用策略lru(least recently used)。

基於鍊錶實現最近最少使用策略

1.如果此資料之前已經被快取進鍊表中,我們遍歷得到這個資料對應的結點,將其從原來的位置刪除,然後再插入到鍊錶的頭部。

2.如果此資料沒有在快取鍊錶中,分兩種情況:

這種實現思路,快取的訪問的時間複雜度未o(n).

我們可以引入雜湊表(hash table)來記錄每個資料的位置,將快取的訪問的時間複雜度降到o(1).

理解指標和引用的含義

將某個變數賦值給指標,實際上就是將這個變數的位址賦值給指標,或者反過來說,指標中儲存了這個變數的位址,指向了這個變數,通過指標就能找到這個變數。

警惕指標丟失和記憶體洩漏

將 p 的 next 指標指向 x 結點;

x->next = p->next; //

將 x 的結點的 next 指標指向 b 結點;

p->next指標在完成第一步操作之後,已經不在指向結點b了,而是指向結點x,第二行**相當於把x賦值給x->next,自己指向自己。整個鍊錶斷成了兩半,從結點b往後的所有結點都無法訪問了。

插入結點時,一定要注意操作順序,把上面的兩行換乙個位置即可。

利用哨兵簡化實現難度

資料結構 表之煉表

頭插法建立 尾插法建立 顯示 銷毀 include include using namespace std typedef int elemtype typedef struct lnode linklist void createlinklistf linklist l,elemtype a,in...

資料結構之鍊錶

頭結點 第乙個有效結點之前的那個結點 頭結點並不存有效資料 加頭結點的目的主要是為了方便對鍊錶的操作 頭指標 指向頭結點的指標變數 尾指標 指向尾節點的指標變數 如果希望通過乙個函式對鍊錶進行處理,只需要乙個引數 頭指標 首先要定義乙個單鏈表儲存結構 然後建立乙個空表,即初始化,我寫的這個提前設定好...

資料結構之鍊錶

鍊錶是一種基本的資料結構型別,它由乙個個結點組成。每乙個結點包括乙個資料的儲存和乙個指向下乙個結點的引用。在這個定義中,結點是乙個可能含有任意型別資料的抽象實體,它所包含的指向結點的應用顯示了它在構造鍊錶之中的作用。和遞迴程式一樣,遞迴資料結構的概念一開始也令人費解,但其實它的簡潔性賦予了它巨大的價...