Redis底層資料結構之雙端連結串列
阿新 • • 發佈:2021-01-28
技術標籤:Redis
連結串列這種資料結構相信大家也不陌生,有很多型別,比如單向連結串列,雙向連結串列,迴圈連結串列等,連結串列相對於陣列來說,一是不需要連續的記憶體塊地址,二是刪除和插入的時間複雜度是 O(1) 級別的,非常的高效,但比不上陣列的隨機訪問查詢方式。
一樣的那句話,沒有最好的資料結構,只有恰到好處的資料結構,比如我們後面要介紹的更高層次的資料結構,字典,它的底層其實就依賴的連結串列規避雜湊衝突,具體的我們後面再說。
redis 中藉助 C 語言實現了一個雙向連結串列結構:
struct listNode{
// 前一個節點的指標
struct listNode *prev;
// 後一個節點的指標
struct listNode *next;
// 節點值
void *value;
};
prev 指標指向前一個節點,next 指標指向後一個節點,value 指向當前節點對應的資料物件。我盜一張圖描述整個串聯起來的連結串列結構:
雖然我通過連結串列的第一個頭節點就可以遍歷整個連結串列,但在 redis 向上封裝了一層結構,專門用於表示一個連結串列結構:
struct list {
// 表頭節點
listNode *head;
// 表尾節點
listNode *tail;
// 連結串列長度
unsigned long len;
// 節點值複製函式
void (*dup)(void *ptr);
// 節點值釋放函式
void (*free)(void *ptr);
// 節點值比對函式
int (*match)(void *ptr,void *key)
}
head 指向連結串列的頭節點,tail 指向連結串列的尾節點,dup 函式用於連結串列轉移複製時對節點 value 拷貝的一個實現,一般來說用等於號足以,但某些特殊情況下可能會用到節點轉移函式,預設可以給這個函式賦值 NULL 即表示使用等於號進行節點轉移。free 函式用於釋放一個節點所佔用的記憶體空間,預設賦值 NULL 的話,即使用 redis 自帶的 zfree 函式進行記憶體空間釋放,
Redis連結串列的特性和優點:
由於是雙向連結串列,具有前後節點的指標引用,所以對獲取這兩個節點的時間複雜度為O(1)。
通過連結串列長度len屬性,獲取長度的時間複雜度為O(1)。
由於節點值是一個指標,所以value可以指定任何型別。
頭節點的前指標和尾結點的後指標都為NULL,是無環的