Redis數據結構—跳躍表


Redis數據結構—跳躍表

大家好,我是白澤,最近學校有點事Redis知識點的更新就放緩了,趁着周六趕緊補一補,我們開始吧~

跳躍表產生的背景

對於有序列表的查找來說,無法找到類似用在有序數組上的二分查找這樣的查找算法,因此遍歷的效率比較低,跳躍表的出現就是為了提高有序鏈表的遍歷效率

跳躍表的結構

下圖是概念上的跳躍表,框中的部分是原始的有序鏈表,我們將其進行改造,抽離成多層,屬於同一列的節點的值相同,這就是一個跳躍表的雛形了(L1、L2、L3是每層對應的頭節點,此時共3層),然后我們就能用跳躍表來簡化我們的有序鏈表的查詢操作

此時你應該很疑惑,跳躍表是如何從一個有序單列表抽離成很多層的從而得到跳躍表的,很遺憾,跳躍表的建立將設計概率論的一些知識,我認為現在講解這部分並不合適,所以請假設跳躍表已經由一個有序單列表出發並建立成功了,接下來我們來看看跳躍表是如何簡化有序鏈表的查詢操作的

利用跳躍表查詢有序鏈表

查詢規則:如果查詢目標大於當前值,查當前節點的后一個(同層),如果小於當前值,則下降到當前節點的前一個節點的正下方,並從該節點的后一個開始查詢(正下方節點不用查),如果已經下降到第一層,且查到某個值已經大於查詢目標的值,則表示目標表示不存在,無需繼續查詢

  1. 現在我們要查詢有序鏈表中是否存在3這個值,此時跳躍表已經抽離成3層,我們從L3頭節點出發,它有一個指向后一個節點的指針,很辛運,后一個節點值為3,查詢結束

  1. 現在我們查詢有序鏈表中是否存在值為2.5的節點,依舊從第3層的頭節點L3開始查,后一個是值為3的節點,顯然,因為鏈表是有序的,因此往后查將沒有結果,所以下降到第2層的L2節點的后一個節點去查,值為1,繼續查它的后一位,值為3,因此需要再下降到第1層的值為1的節點的后一個節點開始查詢,值為2,繼續查后一個節點,值為3,此時無法下降,查詢結束

Redis跳躍表圖示

Redis的跳躍表本質上就是上面我們提到的跳躍表,它由一個個跳躍表Node節點組成,而整體由一個list表示,由list表示是因為list記錄了listNode網絡的頭指針,尾指針,層數,長度信息,有了list就可以操作跳躍表,這種list的用法出現在絕大多數Redis的數據結構中

光看下面這張圖你可能很疑惑,這和上面的跳躍表結構圖並不相同,別急,往下看~

Redis跳躍表數據結構

跳躍表的list結構實現

typedef struct zskiplist {
	struct zskiplistNode *header, *tail;//表頭節點和表尾節點
	unsigned long length;				//表中的節點數量
	int level;							//表中層數最大的節點數量
}

跳躍表的Node節點實現

typedef struct zskiplistNode {
    //后退指針,指向前一個節點的位置,用於逆向遍歷順序鏈表
	struct zskiplistNode *backward;
	//分值,因為需要建立有序鏈表,因此需要一個值去度量順序
    double score;
    //成員對象,用於存放可能需要保存的對象
	robj *obj;
    //層
	struct zskiplistLevel {
        //前進指針
		struct zskiplistNode *forward;
       	//跨度(上圖箭頭上的數值表示跨過了幾個節點)
        unsigned int span;
	} level[];
} zskiplistNode;

listNode中最重要的是level[]數組,這個數組就是圖上每個Node節點的L1~Ln的部分,它的作用就是雖然我們整個Redis跳躍表只有n個節點,但是我們在邏輯上將其抽離成了多層:同一列上節點,各個層其實共用一個節點,並沒有新創建多余的節點

上面整個跳躍表在Redis中只要4個listNode節點就能組成,且用一個list結構表示,如下:

再說一遍:每個紅框只代表一個listNode節點,而它內部的level[]數組,舉個例子:

節點A的level[1]的forward屬性表示:如果將節點A當作在第一層上,該節點的后一個節點的指針

同理,節點A的level[2]的forward屬性表示:如果將節點A當作在第二層,該節點的后一個節點的指針

小結

  1. 你一定要好好理解:level[i]中存放的是第i層上,當前節點的下一個節點的地址,每個節點是被各層共享的,不同的是在各層上,它指向的下一個節點的地址不同

  2. 每層形成長短不一的有序鏈表,配合下降層數進行有序鏈表的查詢,效率更高


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM