redis - 跳躍表詳細介紹

    redis吸引不少人使用的一個重要的緣由,就是它對衆多數據類型的支持。包括string,hash,set,zset,list等五種數據對象。redis

    其中zset用來保證數據的有序存儲,實現中,redis使用跳躍表和壓縮列表,做爲zset的底層實現。當元素數量比較多,或者元素成員是比較長的字符串時,底層實現採用跳躍表。算法


    跳躍表是什麼?數組

    一種有序的數據結構,經過在節點中維持多個指向其它節點的指針,達到快速訪問的目的。數據結構

      

    跳躍表的好處是什麼? ide

    1. 跟平衡樹相比,實現簡單;spa

    2. 平均複雜度爲O(logN),最壞爲O(N);指針

   

    跳躍表的數據結構由 zskiplistNode 和 zskiplist 兩個結構定義,zskiplistNode表示跳躍表節點,zskiplist保存跳躍表節點的相關信息。對象

    

    zskiplistNode的數據結構以下:blog

   typedef struct zskiplistNode {排序

    robj *obj;

    double score;

    struct zskiplistNode *backward;

    struct zskiplistLevel {

        struct zskiplistNode *forward;

        unsigned int span;

     } level[];

   } zskiplistNode

    skiplistLevel包含多個元素,每一個元素包含一個指向其它節點的前進指針,經過它來加快訪問其它節點。每次建立一個跳躍表節點的時候,會隨機生成一個值,該值介於1和32之間,做爲level數組的大小。span表示層的跨度,用來計算最終的位置,程序在遍歷時,會將沿途訪問過的全部層的跨度累計,得出目標節點的對應位置;

    backward用於從表尾向表頭訪問節點;

    score 全部節點都按照它進行排序;

    obj 指向一個字符串對象;


    zskiplist的數據結構:  

    typedef struct zskiplist {

       struct zskiplistNode *header, *tail;

       unsigned long length;

       int level;

    } zskiplist;

   header,tail用來表示跳躍表的表頭和表尾巴節點,length表示跳躍表的總體長度,level表示跳躍表的高度。

   zskiplist的主要做用,是能夠方便的對整個跳躍表進行處理,好比獲取跳躍表的整個長度的信息。

 

   跳躍表的層數如何生成?

   在插入的過程當中構造,向跳躍表中插入一個數值,至關於在表中插入一列從起始跳躍表節點S出發,向上的一段數值,須要肯定兩個元素:數值的位置和層數。因爲全部鏈是遞增序列的方式,因此位置主要是根據對應數值的比較對出。而層數,程序會先記錄比該節點小的值的span,而後,隨機生成介於1和32之間的數值,做爲該節點的層數,該算法主要是基於冥次定律,越大的數出現的機率越小。假設level爲2的機率爲P,則level爲3的機率爲p*p,以此類推。


   跳躍表查找的示例圖:

  

wKiom1RiVkqQnE8hAAE8Ajga6lE999.jpg

   圖中,表示有三個節點,他們對應的score分別爲1,2,3,其中,虛線,表明在跳躍表中,查找score爲2,成員對象爲02的節點,在查找過程當中,通過了兩個span爲1的節點,因此,能夠得出該節點在跳躍表中的排位爲2。 BW表示後退指針,實線的,表示節點間的span,因爲節點間的關係比較多,因此只畫了幾個。

相關文章
相關標籤/搜索