redis原始碼之跳躍表skiplist
阿新 • • 發佈:2019-01-09
未完待續…
跳躍表skiplist
1.簡介:
離散,有序的資料結構。和連結串列、字典等資料結構被廣泛地應用在Redis 內部不同, Redis 只在兩個地方用到了跳躍表,一個是實現有序集合鍵,另一個是在叢集節點中用作內部資料結構。
2.定義:
/*
* 跳躍表節點
*/
typedef struct zskiplistNode {
robj *obj;// 成員物件,它指向一個字串物件,而宇符串物件則儲存著一個SDS值
double score;// 分值,按此排序
struct zskiplistNode *backward;// 後退指標
struct zskiplistLevel {// 層
struct zskiplistNode *forward;// 前進指標
unsigned int span;// 跨度
} level[];
} zskiplistNode;
/*
* 跳躍表
*/
typedef struct zskiplist {
struct zskiplistNode *header, *tail;// 表頭節點和表尾節點
unsigned long length;// 表中節點的數量,表頭節點不計算在內
int level;// 表中層數最大的節點的層數,表頭節點的層數不計算在內
} zskiplist;
注意:
1.初看上去,很容易以為跨度和遍歷操作有關,但實際上並不是這樣,遍歷操作只使用前進指標就可以完成了,跨度實際上是用來計算排位( rank )的:在查詢某個節點的過程中,將沿途訪問過的所有層的跨度累計起來,得到的結果就是目標節點在跳躍表中的排位。
舉個例子,圖5-4 用虛線標記了在跳躍表中查詢分值為3.0 、成員物件為o3 的節點時,沿途經歷的層z 查詢的過程只經過了一個層,並且層的跨度為3 ,所以目標節點在跳躍表中的排位為3。類似的,跨度為1可以累加。
2.住意表頭節點和其他節點的構造是一樣的:表頭節點也有後退指標、分值和成員物件,不過表頭節點的這些屬性都不會被用到
3.在同一個跳躍表中,各個節點儲存的成員物件必須是唯一的,但是多個節點儲存的分值卻可以是相同的:分值相同的節點將按照成員物件在字典序中的大小來進行排序。
4.跳躍表節點的level 陣列可以包含多個元素,每個元素都包含一個指向其他節點的指標,程式可以通過這些層來加快訪問其他節點的速度,一般來說,層的數量越多,訪問其他節點的速度就越快。每個跳躍表節點的層高都是1 至32 之間的隨機數。