Redis底層資料結構(6)跳躍表

2021-09-27 13:40:57 字數 1986 閱讀 6287

當乙個有序集合包含的元素數量多,又或者有序集合中的元素的成員是比較長的字串時,redis就會使用跳躍表作為有序集合鍵的底層實現。

簡介如果我們要實現按照成績對學生進行排名,可以選擇陣列、鍊錶、平衡樹或紅黑樹來實現,陣列的插入和刪除效率低,鍊錶查詢的效率低,平衡樹或紅黑樹雖然效率高但是實現複雜。跳躍表(後面簡稱跳表)就是一種改造了鍊錶,有點像「二分」查詢的結構。

下圖是乙個有序鍊錶:

如果將有序鍊錶的部分節點分層,每層都是乙個有序鍊錶。查詢時優先從最高層開始向後查詢,當到達某節點時,如果next節點值大於要查詢的值或next指標指向null,則從當前節點下降一層繼續向後找,這種「跳過一些節點」的方式就是跳表查詢的思路。如下圖所示是乙個有序分層鏈

查詢過程

上圖中,如果要查詢值為51的節點,步驟如下:

(1)從最高層即第2層開始,1節點比51小,繼續向後找

(2)21節點比51小,且21節點的next指標為null,跳到第1層查詢

(3)41節點比51節點小,繼續向後查詢

(4)61節點比51節點大,跳到第1層查詢

(5)51節點等於51,找到返回

下圖就是乙個redis有序集合的跳表結構:

跳表節點的結構體定義如下:

typedef

struct zskiplistnode level;

} zskiplistnode;

跳表結構:

typedef

struct zskiplist zskiplist;

【注:來自

上圖展示了跳表插入的乙個插入過程,跳表的插入過程也需要像平衡樹一樣維護「平衡性」,如果所有插入的資料都在11到37之間,則跳表的查詢時間複雜度很快就會退化成在單鏈表上的查詢時間複雜度了。在redis有序集合中維護跳表「平衡性」採用的是產生乙個隨機數k,將要新增的節點新增至第1層至第k層,上圖元素區域被拉長就是表明該元素同時也插入到了其他高層上。即zskiplistnode的level層數是隨機產生的乙個值。

如果煉表裡有n個結點,會有多少級索引呢?

假設平均每隔兩個結點會抽出乙個結點作為上一級索引的結點,那第一級索引的結點個數大約就是n/2,第二級索引的結點個數大約就是n/4,第**索引的結點個數大約就是n/8,依次類推,也就是說,第k級索引的結點個數是第k-1級索引的結點個數的1/2,那第k級索引結點的個數就是n/(2^ k)。

假設索引有h級,最高端的索引有2個結點,則n/(2^ h)=2得到h=log2n-1,所以包含原始資料這一層,跳表的高度就是log2n。假設每層都要遍歷m個節點,則在跳表中查詢乙個資料的時間複雜度就是o(m*logn)。那m的值是多少呢?

按照上面的說法「假設平均每隔兩個結點會抽出乙個結點作為上一級索引的結點」,可以得到下面這張圖:

假設我們要查詢的資料是x。在第k級索引中遍歷到y結點之後,發現x大於y,小於後面的結點z,所以我們通過y的down指標,從第k級索引下降到第k-1級索引。在第k-1級索引中,y和z之間只有3個結點(包含y和z),所以,我們在k-1級索引中最多隻需要遍歷3個結點,依次類推,每一級索引都最多隻需要遍歷3個結點。

因此,跳表查詢的平均時間複雜度就是o(logn),和二分查詢的平均時間複雜度一樣。

按照分析時間複雜度的假設: 「假設平均每隔兩個結點會抽出乙個結點作為上一級索引的結點」,原始資料有n個,則第1層索引有n/2個節點、第2層索引有n/4個節點…、第k層有n/(2^ k)個節點,依次累加,得到n-2。所以跳表的空間複雜度是o(n),即n個資料用跳表的結構儲存,還需要額外n個節點的儲存空間。

Redis底層資料結構?

福哥口訣法 簡鏈字跳整 壓快壓 sds synamic string 簡單動態字串。支援自動動態擴容的位元組陣列 list 鍊錶 雙端鍊錶。dict 字典。使用雙雜湊表實現的,支援平滑擴容的字典 zskiplist 跳躍表。附加了後向指標的跳躍表 intset 整數集合。用於儲存整數數值集合的自有結...

Redis底層資料結構

redis底層實現的8種資料結構 sds synamic string 支援自動動態擴容的位元組陣列 list 鍊錶 dict 使用雙雜湊表實現的,支援平滑擴容的字典 zskiplist 附加了後向指標的跳躍表 intset 用於儲存整數數值集合的自有結構 ziplist 一種實現上類似於tlv,但...

redis底層資料結構

1.1 string字串 表現形式為 資料結構 sds 簡單的動態字串 使用原因 redis是使用c語言開發的,但在c語言中是沒有字串型別的,只能使用指標或符陣列的形式表示乙個字串,所以在redis設計了一種簡單的動態字串 可以根據不同的資料型別不同的資料結構選擇不同的資料結構 支援的資料型別 字串...