概念
跳躍表是一種有序的數據結構,它通過在每個節點維護多個指向其他節點的指針,以達到快速訪問的目的。跳躍表支持平均O(logN)最壞O(N)的複雜度查找節點。大多數情況下,其性能可以和平衡樹媲美。
跳躍表是有序集合鍵的底層實現之一,如果有序集合鍵包含的元素較多,或者成員是比較常的字符串的時候。Redis只有兩個地方使用到了跳躍表:有序集合鍵、集羣節點中用作內部數據結構。
結構描述
描述節點相關信息的zskiplist和存儲節點的zskiplistNode
zskiplist中保存有 header(指向頭結點)、tail(指向尾節點)、level(節點的最大層數,頭結點除外)、length(節點數目,頭結點除外)
zskiplistNode中又包含以下屬性
typedef struct zskiplistNode{
struct zskiplistNode* backward; //後退指針:每一個節點都有一個後退指針,跨度爲1
double score; //分值:節點按照分值排序
robj *obj; //成員對象
struct askiplistLevel{ //層:每一個節點有許多層,每一層包含前進指針,和其跨度
struct askiplistNode forward;
unsigned int span;
}level[];
}zskiplistNode;
1、層:每次生成一個跳躍表節點的時候,都會按照冪次定律(越大的數出現的機率越小)隨機生成一個1~32之間的數作爲level數組的大小,也就是層的高度。
2、前進指針:level[i].farword屬性,遍歷只需要使用前進指正就可以了
3、跨度:level[i].span屬性,用來計算排位,將遍歷的沿途所有的跨度相加就是排位。指向null的層跨度爲0,因爲沒有指向任何對象。
4、後退指針,每次只可以後退一個跨度。從tail遍歷,一直遇到null(head之後,排名第一的節點的後退指針不指向head,而是指向null,就像前面所述,head雖然有這些屬性,但是不用)
5、成員對象是一個指針,它指向一個sds,跳躍表中的節點按照分值排序(從小到大),如果分值相同,則按照對象在字典中的排序來確定順序。一個跳躍表中的兩個節點之間,分值大小可以相同,但是成員對象必須是唯一的。
注意頭結點也有上述的四個結構,但是其後退指針、分值、成員對象都沒有用到