1. 程式人生 > >Redis設計與實現筆記(二) | 連結串列結構

Redis設計與實現筆記(二) | 連結串列結構

沒錯,本篇我們要說一說連結串列在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)

還有一條就是連結串列是無環的