Redis設計與實現筆記(二) | 連結串列結構
阿新 • • 發佈:2018-11-10
沒錯,本篇我們要說一說連結串列在Redis中的應用。本打算寫Redis中的列表,但想來想去覺得列表僅僅是Redis連結串列的一部分,並不能完全說明連結串列這一資料結構在Redis中的應用。那就說說資料結構連結串列吧。小夥伴們,開始啦!
2.1 資料結構:連結串列
C語言中沒有內建這種資料結構(例如Java實現了連結串列結構 LinkedList),所以Redis需要自己實現連結串列結構。連結串列是一種基本的資料結構,就不再詳細的說明了。那對於Redis的連結串列是怎麼實現的呢?
2.1.1 連結串列節點
Redis中的連結串列節點是怎麼實現的呢?每一個連結串列節點都是使用 ListNode 結構體實現的,ListNode 結構體定義在adlist.h 標頭檔案中。定義如下:
typedef struct ListNode{
// 前(後)置節點
struct ListNode *prev;
struct ListNode *next;
// 值
void *value;
}ListNode;
由上述定義可知:
- Redis中連結串列是一個雙向鏈,每一個節點都指向前後節點。
- 每個節點值的型別都是void,可知節點可以儲存任意型別的值。也就是說,一個連結串列中可以儲存不同型別的資料。
由多個ListNode組成的連結串列結構,如下圖所示:
站在連結串列結構上來講,多個節點已經可以組成一個基本的連結串列了,但對於操作來說,還是需要一些其他資訊來管理這個連結串列。這些資訊包括連結串列長度、頭(尾)節點、判斷兩個節點是否相等、釋放節點空間、複製節點,上圖僅僅由ListNode 組成的連結串列無法方便的完成。(注意:“無法方便的完成” 是指可以通過複雜的操作完成,就是複雜、不方便)
2.1.2 list結構體
由於僅僅由ListNode組成的連結串列不易管理,使用list來持有連結串列,那麼,操作起來就easy多了。list結構體定義在adlist.h中,定義如下:
typedef struct list{ // 節點頭、尾、連結串列長度 ListNode *head; ListNode *tail; unsigned int len; // 複製節點、釋放節點、對比節點 void *(*dup)(void *ptr); void *(*free)(void *prt); int *(*match)(void *ptr,void *key); }
由上述定義可知:
- 獲取連結串列長度的複雜度O(1),無需遍歷整個連結串列
- 獲取頭尾節點的複雜度O(1)
還有一條就是連結串列是無環的