1. 程式人生 > 其它 >redis資料結構---跳躍表

redis資料結構---跳躍表

跳躍表(skiplist)是一種有序資料結構, 它通過在每個節點中維持多個指向其他節點的指標, 從而達到快速訪問節點的目的。

跳躍表支援平均O(\log N)最壞O(N)複雜度的節點查詢, 還可以通過順序性操作來批量處理節點。

跳躍表的實現

redis 的跳躍表由 zskiplistNode 和 zskiplist 兩個結構定義,zskiplistNode 結構用於表示跳躍表節點,zskiplist 結構則用於儲存跳躍表節點的相關資訊

跳躍表節點

typedef struct zskiplistNode {
    // 後退指標
    struct zskiplistNode *backward;
// 分值 double score; // 成員物件 robj *obj; // struct zskiplistLevel { // 前進指標 struct zskiplistNode *forward; // 跨度 unsigned int span; } level[]; } zskiplistNode;
  • 層:跳躍表節點的 level 陣列可以包含多個元素, 每個元素都包含一個指向其他節點的指標, 程式可以通過這些層來加快訪問其他節點的速度, 一般來說, 層的數量越多, 訪問其他節點的速度就越快。每次建立一個新跳躍表節點的時候, 程式會隨機生成一個介於 1 和 32 之間的值作為 level 陣列的大小, 這個大小就是層的“高度”。
  • 前進指標:用於從表頭向表尾方向訪問節點
  • 跨度:用於記錄兩個節點之間的距離,兩個節點之間的跨度越大, 它們相距得就越遠。指向 NULL 的所有前進指標的跨度都為 0, 因為它們沒有連向任何節點。
  • 後退指標:用於從表尾向表頭方向訪問節點:,跟可以一次跳過多個節點的前進指標不同, 因為每個節點只有一個後退指標, 所以每次只能後退至前一個節點。
  • 分值:是一個 double 型別的浮點數, 跳躍表中的所有節點都按分值從小到大來排序。
  • 成員:是一個指標, 它指向一個字串物件, 而字串物件則儲存著一個 SDS 值。

zskiplist結構

雖然僅靠多個跳躍表節點就可以組成一個跳躍表,但通過使用一個zskiplist結構來持有這些節點, 程式可以更方便地對整個跳躍表進行處理, 比如快速訪問跳躍表的表頭節點和表尾節點, 又或者快速地獲取跳躍表節點的數量(也即是跳躍表的長度)等資訊。

typedef struct zskiplist {

    // 表頭節點和表尾節點
    struct zskiplistNode *header, *tail;

    // 表中節點的數量
    unsigned long length;

    // 表中層數最大的節點的層數
    int level;

} zskiplist;

跳錶建立過程

跳錶查詢過程

本文參考《Redis設計與實現》(感覺書上的圖不太好理解,自己從網上找的圖)