Redis設計與實現之連結串列--閱讀筆記
阿新 • • 發佈:2018-12-20
前言
連結串列提供了高效的節點重排能力,以及順序性的節點訪問方式,連結串列在 Redis 中的應用很廣泛,比如列表鍵的底層實現之一就是連結串列,除此之外,釋出與訂閱、慢查詢、監視器等功能也用到了連結串列,Redis 伺服器本身使用連結串列儲存多個客戶端的狀態資訊,使用連結串列構建客戶端輸出緩衝區。
連結串列的底層實現
學習過演算法的同學都知道資料結構中的連結串列的相關概念了,這裡簡單介紹一下連結串列的資料結構:
連結串列是常見的基礎資料結構,是一種線性表,但是並不會按線性的順序儲存資料,而是在每一個節點裡存到下一個節點的指標(Pointer)。由於不必須按順序儲存,連結串列在插入的時候可以達到O(1)的複雜度,比另一種線性表 順序錶快得多,但是查詢一個節點或者訪問特定編號的節點則需要O(n)的時間,而順序表相應的時間複雜度分別是O(logn)和O(1)。(來源於維基百科)
先來看看一個連結串列節點的資料結構:
typedef struct listNode {
// 前置節點
struct listNode *prev;
// 後置節點
struct listNode *next;
// 節點的值
void *value;
}listNode;
多個 listNode (連結串列節點)通過 prev 和 next 指標組成雙向連結串列
下面使用 list 資料結構來管理連結串列:
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 結構為連結串列提供了表頭指標head, 表尾指標tail,以及連結串列長度計數器len, 而dup、free 和match 函式的作用如下:
- dup 函式用於複製連結串列節點所儲存的值
- free 函式用於釋放連結串列節點所儲存的值
- match 函式用於對比連結串列節點所儲存的值與另外一個輸入值是否相等
list 結構與 listNode 結構組成的連結串列
Redis 連結串列特點總結
- 雙向: 連結串列節點都有 prev 和 next 指標,可以獲取某個節點的前置節點和後置節點,複雜度為O(1)
- 無環:上面圖片顯示,表頭節點的 prev 指標和表尾節點的 next 指標都指向 NULL
- 帶表頭指標和表尾指標: 通過 list 結構的 head 和 tail 指標,獲取表頭節點和表尾節點的複雜度為O(1)
- 帶連結串列長度計數器:通過 list 結構的 len 欄位記錄了 連結串列中的連結串列節點(listNode)數,獲取連結串列長度的複雜度為O(1)
- 多型:連結串列節點使用 void * 指標來儲存節點值,可以通過 list 結構的 dup、free和match 屬性為節點值設定型別特定函式,所有連結串列可用於儲存不同型別的值
這章內容比較少,基本就是 Redis 設計與實現 原樣搬過來的,很容易瞭解,講的特別好,主要是做個記錄,以後可以翻閱。