1. 程式人生 > 其它 >跳錶的資料結構

跳錶的資料結構

調錶的核心思想

跳錶的核心思想是“剪枝”,具體是如下方式實現
如果是一個簡單的連結串列,那麼我們知道在連結串列中查詢一個元素I的話,需要將整個連結串列遍歷一次。

如果是說連結串列是排序的,並且節點中還儲存了“跳躍”的指向後續節點的指標的話,那麼在查詢一個節點時,僅僅需要遍歷N/2個節點即可。

從上圖中已經可以看到"層"的出現使得時間複雜度降為原來的一半。

一次典型的調錶查詢

skiplist上的查詢路徑展示

skiplist正是受這種多層連結串列的想法的啟發而設計出來的。實際上,按照上面生成連結串列的方式,上面每一層連結串列的節點個數,是下面一層的節點個數的1/P(redis中P為0.25),這樣查詢過程就非常類似於一個二分查詢,使得查詢的時間複雜度可以降低到O(log n)。

核心資料結構

#define ZSKIPLIST_MAXLEVEL 32 //最大層數
#define ZSKIPLIST_P 0.25 //P

typedef struct zskiplistNode {
    robj *obj;
    double score;
    struct zskiplistNode *backward; //後向指標
    struct zskiplistLevel {
        struct zskiplistNode *forward;//每一層中的前向指標
        unsigned int span;//x.level[i].span 表示節點x在第i層到其下一個節點需跳過的節點數。注:兩個相鄰節點span為1
    } level[];
} zskiplistNode;

typedef struct zskiplist {
    struct zskiplistNode *header, *tail;
    unsigned long length;//節點總數
    int level;//總層數
} zskiplis