鏈表

鏈表通過指針將一組零散的內存塊串聯在一起,每個內存塊稱爲鏈表的結點。

這篇文章介紹三種常見的鏈表結構:單向鏈表、雙向鏈表、循環鏈表。

單向鏈表

單向鏈表只有一個方向,結點只有一個後繼指針next指向後面的結點。單項鍊表有兩個點比較特殊。第一個結點也叫頭結點,是用來記錄鏈表的基地址,有了它我們可以遍歷整條鏈表。最後一個結點也叫尾結點,尾結點指向一個空地址Null,表示這是鏈表上最後一個結點。

鏈表也支持查找、插入、刪除操作。跟數組相比,鏈表的插入和刪除操作只需改變相鄰結點的指針,對應的時間複雜度爲O(1)。而鏈表因爲內存不連續,先要訪問第K個元素只能根據指針依次遍歷結點,直到找到相應的結點,對應的時間複雜度爲O(n)。

循環鏈表

循環鏈表是一種特殊的單向鏈表,它和單向鏈表唯一的區別是尾結點指向鏈表的頭結點。

循環鏈表的優點是從鏈尾到鏈頭比較方便,當要處理的數據具有環形結構特點,適合採用循環列表,例如約瑟夫問題

雙向鏈表

雙向鏈表,支持兩個方向,每個結點的後繼指針next指向後面的結點,前驅指針prev指向前面的結點。

雙向鏈表需要額外的空間存儲後繼和前驅結點的地址,所以雙向鏈表佔用內存更多,但可以支持雙向遍歷,使得雙向鏈表在某些情況的下的插入、刪除、查詢操作更高效。比如刪除指定指針指向的結點,因爲雙向鏈表中保存了前驅結點的指針,單向鏈表爲了找到前驅結點要從頭遍歷。再比如向指定結點前插入一個結點,查詢一個有序鏈表等,雙向鏈表的效率都要更高。

這就是用“空間換時間”的設計思想。當內存空間充足,追求代碼執行速度,可以選擇空間複雜度相對高但時間複雜度低的算法或數據結構。反過來,內存緊缺,使用時間複雜度高但空間複雜度低的算法或數據結構,這就是“時間換空間”設計思想。

雙向循環鏈表

把循環鏈表和雙向鏈表結合在一起就是雙向循環鏈表。


鏈表實現LRU緩存淘汰策略

緩存是一種提高數據讀取性能的技術,但緩存大小有限,需要制定策略當緩存用滿時,將哪些數據清理出去哪些數據保留。常見策略有三種:

  • 先進先出策略FIFO(First in First out)
  • 最少使用策略LFU(Least Frequently Used)
  • 最近最少使用策略LRU(Least Recently Used)

下面說一些基於鏈表實現LRU緩存淘汰算法,維護一個有序單向鏈表,越靠近鏈表尾部的結點是越早訪問的數據。當有新數據被訪問,從鏈表頭部開始遍歷鏈表:

  • 如果此數據已經緩存在鏈表中,將遍歷得到的結點從原來的位置刪除,再插入到鏈表的頭部;
  • 如果鏈表中沒有緩存過,且緩存未滿,直接將結點插入鏈表頭部;
  • 如果鏈表中沒有緩存過,且緩存已滿,將尾結點刪除,再將新的數據插入鏈表頭部;

這樣就用鏈表實現了LRU緩存。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章