1. 程式人生 > >跳躍表,整數,壓縮列表

跳躍表,整數,壓縮列表

tail 所表 typedef obj 求解 但是 mage double struct

跳躍表事一種有序的結構,是有序集合鍵的底層實現

typedef struct zskiplistNode {

    // 後退指針
    struct zskiplistNode *backward;

    // 分值
    double score;

    // 成員對象
    robj *obj;

    //
    struct zskiplistLevel {

        // 前進指針
        struct zskiplistNode *forward;

        // 跨度
        unsigned int span;

    } level[];

} zskiplistNode;

跳躍表有兩種結構定義的,一個是node,一個是list,list控制著node

node就是上面的結構,一個層,每個層有兩個元素,一個是前進指針,一個是跨度。還有個後退指針,向後遍歷的時候使用,跨度恒為1,還有一個分值和對象。分值就是從小到大依次向後的,doubleleixing類型,節點的對象成員是一個指針,指向一個sds。

list的結構:

head指向頭

tail指向尾

lenght記錄著跳躍表的長度

level記錄著跳躍表內節點層數最高的那層

跨度的概念:

跨度不是用來便利的,是用來計算排位的,rank,通過跨度我們可以知道我們的某一個節點位於跳躍表的第幾位

指向null的跨度都是0

整數集合:

typedef struct intset {

    // 編碼方式
    uint32_t encoding;

    // 集合包含的元素數量
    uint32_t length;

    // 保存元素的數組
    int8_t contents[];

} intset;

整數集合是無重復的有序的,encoding是編碼方式,有16,32,64位的,分別表示不同的範圍,length代表的就是長度

因為底層實現是數組,所以有一個內置的數組,這個數組可以自動升級,當加進來的元素位數大於現有的就回自動升級,以最高的位標準,擴大內存,添加移動的時候從後向前進行

自動升級的好處就是

(1)增加靈活性

(2)節省內存,需要的時候擴展,一直秉承著最小對其原值

壓縮列表

技術分享

zlbytes:表示整個壓縮列表占用的大小,重分配的時候下需要使用

zltail:計算列表的最後節點距離起始位置的距離,可以分方便的知道尾地址

zllen(2字節):記錄節點個數,如果超過65535個的時候,我們需要自己遍歷求解

中間都是每一個節點

zlend:0xff表示終止符

中間的entry節點是一個整數或者數組

都包含三個元素

previous_entry_length

前一個節點的長度

可能是一個字節或者是5個字節,如果前一個長度小於254個字節,那就是一個字節存,否則用5個字節,但是5個字節中,第一個字節為0XFE,表示是用5字節存儲,後面4個字節表示的是實際長度

encoding:編碼方式

可以表示字符或者整數,如果是字符的花,前面分別是00,01,10編碼長度分別我1,2,5字節,所表示數組的長度也漸大

如果前面是11,只占一個字節,根據後6位的不同表示的整數的範圍也不同

content:存儲的數據

連鎖更新:

如果每一個元素的大小都在250-253之間,突然增加一個元素,使得第一個+4,造成第二個長度+4,依次類推,這樣的話需要進行n次重分配,每次的復雜度位n,那麽時間復雜度最壞就是n的2次冪。盡管這樣很糟糕,但是發生這種的情況不多,所以我們可以忽略不計

同理,刪除一個元素的時候,也有可能造成類似的連鎖更新

跳躍表,整數,壓縮列表