redis的資料結構——連結串列
阿新 • • 發佈:2020-08-10
一、前言
連結串列是一種常用的資料結構,大家肯定對它非常的熟悉。連結串列被內建在很多的高階語言中,但因為Redis是使用C語言實現的,而C語言並沒有這種資料結構,因此,Redis構建了自己的連結串列實現。連結串列在Redis中的使用非常廣泛,比如列表鍵的底層實現之一就是連結串列。當一個列表鍵包含的元素數量很多,又或者列表中包含的元素都是比較長的字串時,Redis就會使用連結串列作為列表鍵的底層實現。除了列表鍵之外,釋出與訂閱、慢查詢、監視器等功能也用到了連結串列,Redis伺服器本身還是用連結串列儲存多個客戶端的狀態資訊,以及使用連結串列來構建客戶端輸出緩衝區。
二、示例
如下圖,通過RPUSH命令插入一個長的字串,Redis的底層儲存結構就是一個連結串列。
三、連結串列和連結串列節點的實現
下面的程式碼展示了一個連結串列節點的資料結構。
typedef struct listNode { //前置節點 struct listNode *prev; //後置節點 struct listNode *next; //節點的值 void *value }
Redis中的連結串列是一個雙向連結串列,每一個節點中都儲存著指向前置節點和指向後置節點的指標,多個這樣的節點就組成了Redis的連結串列結構。如下圖。
雖然多個listNode結構就可以組成連結串列,但是使用如下結構來持有連結串列的話,操作起來會更加方便。
typedef struct list { //表頭節點 listNode *head; //表尾節點 listNode *tail; //連結串列包含的節點數量 unsigned long len; //複製函式 void *(*dup) (void *ptr); //節點值釋放函式 void *(*free) (void *ptr); //節點值對比函式 void *(*match) (void *ptr, void *key); } list;
list結構為連結串列提供了表頭指標、表尾指標,以及連結串列長度計數器len,而dup、free、match成員則是用於實現多型連結串列所需的型別特定函式。
如下圖是一個由list結構和三個listNode結構組成的連結串列。
四、總結
Redis的連結串列實現特性可以總結如下:
- 雙端:連結串列節點包含next和prev指標,獲取某個節點的前置節點和後置節點的時間複雜度都是O(1)。
- 無環:表頭節點的prev指標和表尾節點的next指標都指向NULL,對連結串列的訪問可以以NULL為終止。
- 帶表頭指標和表尾指標:通過list結構的head指標和tail指標,程式獲取連結串列的表頭節點和表尾節點的時間複雜度都是O(1)。
- 帶連結串列長度計數器:程式使用list的len屬性對list持有的連結串列節點進行計數,程式獲取連結串列節點的時間複雜度為O(1)。
- 多型:連結串列節點使用void*指標來儲存節點值,並且通過list結構的dup、free、match為節點設定型別特定的函式,所以連結串列可以用於儲存各種不同型別的值。