Redis學習筆記——ListNode

Redis定義了雙向鏈表,用來存儲列表鍵的值,還有其餘的我不知的。
雙向鏈表的節點定義爲:node

typedef struct listNode {

    // 前置節點
    struct listNode *prev;

    // 後置節點
    struct listNode *next;

    // 節點的值
    void *value;

} listNode;

這裏是把節點的值做爲了一個成員變量,Linux內核裏面節點的定義是這樣的git

struct list_head{
    struct list_head *next;
    struct list_head *prev;
}

這樣能夠沒有不用處理節點所帶數據的類型,可是要經過offsetof/container_of這類來處理。不過這是題外話了。
除此以外,Redis還定義了鏈表結構,以下:github

typedef struct list {

    // 表頭節點
    listNode *head;

    // 表尾節點
    listNode *tail;

    // 節點值複製函數
    void *(*dup)(void *ptr);

    // 節點值釋放函數
    void (*free)(void *ptr);

    // 節點值對比函數
    int (*match)(void *ptr, void *key);

    // 鏈表所包含的節點數量
    unsigned long len;

} list;

這樣定義的好處有:redis

  1. 快速獲取鏈表的頭尾算法

  2. 快速查詢鏈表的節點數,像動態字符串sdshr裏的len那樣,不用遍歷所有字符就能夠獲取字符串的長度,這裏也相似。函數

它裏面還定義了鏈表的迭代器,設計

typedef struct listIter {

    // 當前迭代到的節點
    listNode *next;

    // 迭代的方向
    int direction;

} listIter;

裏面迭代的方向爲指針

// 從表頭向表尾進行迭代
#define AL_START_HEAD 0
// 從表尾到表頭進行迭代
#define AL_START_TAIL 1

迭代器能夠經過如下幾個接口來使用(不徹底列出來)code

listIter *listGetIterator(list *list, int direction) //根據迭代方向給鏈表建立迭代器
listNode *listNext(listIter *iter) //返回迭代器當前指向的節點,而且把迭代器根據方向向前移動一下

假如我要遍歷整個鏈表,我能夠這樣作接口

iter = listGetIterator(list, AL_START_HEAD);
while ((node = listNext(iter)) != NULL) {
    doSomethingWith(node);
}

寫起來是比較簡單易懂的。
裏面還有個反轉節點的函數

void listRotate(list *list) {
    listNode *tail = list->tail;

    if (listLength(list) <= 1) return;

    /* Detach current tail */
    // 取出表尾節點
    list->tail = tail->prev;
    list->tail->next = NULL;

    /* Move it as head */
    // 插入到表頭
    list->head->prev = tail;
    tail->prev = NULL;
    tail->next = list->head;
    list->head = tail;
}

這個實際上是翻轉節點,不是倒序。是否是跟之前作過的算法題很像。有沒有想起手搖算法。

最後貼上《Redis設計與實現》裏的總結

鏈表被普遍用於實現 Redis 的各類功能, 好比列表鍵, 發佈與訂閱, 慢查詢, 監視器, 等等。
每一個鏈表節點由一個 listNode 結構來表示, 每一個節點都有一個指向前置節點和後置節點的指針, 因此 Redis 的鏈表實現是雙端鏈表。
每一個鏈表使用一個 list 結構來表示, 這個結構帶有表頭節點指針、表尾節點指針、以及鏈表長度等信息。
由於鏈表表頭節點的前置節點和表尾節點的後置節點都指向 NULL , 因此 Redis 的鏈表實現是無環鏈表。
經過爲鏈表設置不一樣的類型特定函數, Redis 的鏈表能夠用於保存各類不一樣類型的值。

參考:
1.《Redis設計與實現》
2.https://github.com/huangz1990...

相關文章
相關標籤/搜索