鏈表
Redis 使用鏈表作爲列表的鍵底層實現。
3.1 鏈表和鏈表節點的實現
每個鏈表節點使用一個 adlist.h/listNode 結構來表示:
typedef struct listNode{
// 前置節點
struct listNode *prev;
// 後置節點
struct listNode *next;
// 節點的值
void *value;
}listNode;
多個 listNode 可以通過 prev 和 next 指針組成雙端鏈表
可以通過 adlist.h/list 來持有鏈表的話,操作起來會更方便:
typedef struct list{
// 表頭節點
listNode *head;
// 表尾節點
listNode *tail;
// 鏈表所包含的節點數量
unsigned long len;
// 節點值複製函數
void *(*dup)(void *ptr);
// 節點值釋放函數
void *(*free)(void *ptr);
// 節點值對比函數
int (*match)(void *ptr, void *key);
}list;
list 結構爲鏈表提供了表頭指針 head、表尾指針 tail,以及鏈表長度計數器 len,而 dup、free 和 match 成員則是用於實現多態鏈表所需的類型特定函數:
- dup 函數用於複製鏈表節點所保存的值
- free 函數用於釋放鏈表節點所保存的值
- match 函數則用於對比鏈表節點所保存的值和另一個輸入值是否相等
Redis 的鏈表實現的特性可以總結如下:
- 雙端:鏈表節點帶有 prev 和 next 指針,獲取某個節點的前置節點和後置節點的複雜度都是 O(1)。
- 無環:表頭節點的 prev 指針和表尾節點的 next 指針都指向 NULL,對鏈表的訪問以 NULL 爲終點。
- 帶表頭指針和表尾指針:通過 list 結構的 head 指針和 tail 指針,程序獲取鏈表的表頭節點和表尾節點的複雜度爲 O(1)。
- 帶鏈表長度計數器:程序使用 list 結構的 len 屬性來對 list 持有的鏈表節點進行計數,程序獲取鏈表中節點數量的複雜度爲 O(1)。
- 多態:鏈表節點使用 void* 指針來保存節點值,並且可以通過 list 結構的 dup、free、match 三個屬性爲節點值設置類型特定函數,所以鏈表可以用於保存各種不同類型的值。