redis跳錶的實現

看了redis的跳錶的源碼,感覺代碼的實現非常短小精悍。

redis中跳錶主要實現:增刪改查, 除了這幾個常規功能之外,還有一個很牛逼且很實用的功能:獲取節點的rank排名、或者獲取指定範圍rank的節點。

redis中跳錶的實現

typedef struct zskiplistNode {

    robj *obj;      

    double score;       // 內部節點排序的依據,如果值相等根據obj對象排序。

    struct zskiplistNode *backward;        //後退指針。每次只能後退一個節點

    struct zskiplistLevel {

        struct zskiplistNode *forward;      //前進指針。一次可能跳過多個節點

        unsigned int span;               //跨度。 表示當前節點在當前層到達下一個節點的距離。後續查找節點的時候,每層會獲取一個節點,這些節點的span加起來,就是節點的rank。

    } level[];                                    

} zskiplistNode;

 

typedef struct zskiplist {

    struct zskiplistNode *header, *tail;     //頭結點和尾節點。tail是爲了實現反向查找,即根據score從大到小的 順序查找。注意header中的第一個節點是空節點。如果當前層的鏈爲null,span表示鏈表的長度。header->forward節點的backward指向null。

    unsigned long length;            //節點的數量

    int level;                     //跳躍表中節點的最大層數。根據實際需要增加或者減小。因此每個節點level不同,分配的空間大小也不同。

} zskiplist;

 

主要函數:

zslInsert函數:添加一個節點

    update[ZSKIPLIST_MAXLEVEL]變量:每層待插入節點的上一個節點。

    rank[ZSKIPLIST_MAXLEVEL]變量:update[i]節點的rank,即鏈表頭到update[i]節點的距離。

   函數主要邏輯:

   1.計算每層要插入節點的前一個節點,以及該節點的rank,這段代碼實現的很精簡,而且後續增刪改查都用到。

   2.根據zslRandomLevel函數獲取新結點的level,如果大於當前的最大level,新的level上第一個節點初始化。注意新的level上由於第一個節點的後繼節點是NULL,即鏈表結尾,因此第一個節點的跨度爲鏈表長度。

   3.創建新節點,更新每層中的鏈表關係和span。主要分2部分:一部分是底層要插入節點的level,這部分要更改update[i]節點在第i層和新插入節點的鏈表指針、span;第二部分由於沒有插入節點,只要更改update[i]->level[i].span++

   4.如果新插入的節點是頭節點或者尾節點,修改zskiplist

zslDelete函數:刪除一個節點

  1.找到每層中要處理節點的前一個節點,保存在update[i]

  2.如果鏈表中存在該節點,檢查每層中update[i]的下一個節點是不是要刪除的節點,如果是則刪除,並且update[i]對應的第i層的span要和下一個節點的span合併。如果不是,update[i]第i層的span-1

 

  其他功能的實現和上面兩個函數的基本一致,這裏不在贅述。

 

redis中跳錶相比紅黑樹、hash的優點:

1.跳錶和紅黑樹可以實現有序排列,即可以進行範圍查詢,hash只支持單值查詢。

2.跳錶的修改和刪除的複雜度爲O(n),redis中採用zslRandomLevel計算不同點的層次,不用嚴格維護上次節點是下層節點一半數量,將複雜度降低爲O(logn)。雖然和紅黑樹的時間複雜度相等,但是實際操作中不需要考慮樹的維護,只要處理相鄰的節點指針,操作簡單快速。

3.算法的遠比紅黑樹簡單的多。

4.redis中獲取某段範圍的節點,紅黑樹根據中序遍歷,跳錶只需要根據鏈表指針順序讀取,執行速度和實現複雜度都優於紅黑樹

5.redi的跳錶跳錶平均每個節點有1.33個指針(根據zslRandomLevel計算平均指針數量),紅黑樹至少有2個,佔用空間少一些。

6.redis的跳錶維護了span字段,可以快速計算出節點的rank或者獲取指定rank的節點

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章