1. 程式人生 > 實用技巧 >redis的資料結構——連結串列

redis的資料結構——連結串列

一、前言

連結串列是一種常用的資料結構,大家肯定對它非常的熟悉。連結串列被內建在很多的高階語言中,但因為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為節點設定型別特定的函式,所以連結串列可以用於儲存各種不同型別的值。