跳躍表,整數,壓縮列表
跳躍表事一種有序的結構,是有序集合鍵的底層實現
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次冪。盡管這樣很糟糕,但是發生這種的情況不多,所以我們可以忽略不計
同理,刪除一個元素的時候,也有可能造成類似的連鎖更新
跳躍表,整數,壓縮列表