拜託,面試別再問我跳錶了!

何爲跳錶?

跳錶是一個隨機化的數據結構,實質就是一種能夠進行二分查找的有序鏈表算法

跳錶在原有的有序鏈表上面增長了多級索引,經過索引來實現快速查找。數組

跳錶不只能提升搜索性能,同時也能夠提升插入和刪除操做的性能。緩存

跳錶詳解

有序鏈表

skiplist1

考慮一個有序鏈表,咱們要查找三、七、17這幾個元素,咱們只能從頭開始遍歷鏈表,直到查找到元素爲止。數據結構

上述這個鏈表是有序的,可是不能使用二分查找,是否是很捉急?(P.S.數組能夠實現二分查找)性能

那麼,有沒有什麼方法能夠實現有序鏈表的二分查找呢?學習

答案是確定的,那就是咱們將要介紹的這種數據結構——跳錶。指針

跳錶的演進

咱們把一些節點從有序表中提取出來,緩存一級索引,就組成了下面這樣的結構:code

skiplist2

如今,咱們要查找17這個元素是否是要快不少呢?排序

咱們只要從一級索引日後遍歷便可,只須要通過一、六、1五、17這幾個元素就能夠找到17了。索引

那麼,咱們要查找11這個元素呢?

咱們從一級索引的1開始,向右到6,再向右發現是15,它比11大,此路不通,從6往下走,再從下面的6往右走,到7,再到11。

一樣地,一級索引也能夠往上再提取一層,組成二級索引,以下:

skiplist3

這時候咱們再查找17這個元素呢?

只須要通過六、1五、17這幾個元素就能夠找到17了。

這基本上就是跳錶的核心思想了,其實這也是一個「空間換時間」的算法,經過向上提取索引增長了查找的效率。

跳錶的插入

上面講的都是跳錶的查詢,那麼,該如何向跳錶中插入元素呢?

好比,咱們要向上面這個跳錶添加一個元素8。

首先,咱們先根據投硬幣的方式,決定8這個元素要佔據的層數,沒錯就是扔硬幣,是否是很好玩兒^^

好比,層數level=2。

而後,找到8這個元素在下面兩層的前置節點。

接着,就是鏈表的插入元素操做了,比較簡單。

最後,就像下面這樣:

skiplist4

跳錶的刪除

查詢、插入元素都講了,下面咱們就來講說怎麼刪除元素。

首先,找到各層中包含元素x的節點。

而後,使用標準的鏈表刪除元素的方法刪除便可。

好比,要刪除17這個元素。

skiplist5

標準化的跳錶

上面舉的例子是徹底隨機的跳錶,那麼,若是咱們每兩個元素提取一個元素做爲上一級的索引會怎麼樣呢?

skiplist6

這是否是很像平衡二叉樹,如今這顆樹元素比較少,可能不太明顯,咱們來看個元素個數多的狀況。

skiplist6

能夠看到,上一級元素的個數是下一級的一半,這樣每次減小一半,就很接近平衡二叉樹了。

時間複雜度

咱們知道單鏈表查詢的時間複雜度爲O(n),而插入、刪除操做須要先找到對應的位置,因此插入、刪除的時間複雜度也是O(n)。

那麼,跳錶的時間複雜度是多少呢?

若是按照標準的跳錶來看的話,每一級索引減小k/2個元素(k爲其下面一級索引的個數),那麼整個跳錶的高度就是(log n)。

學習過平衡二叉樹的同窗都知道,它的時間複雜度與樹的高度成正比,即O(log n)。

因此,這裏跳錶的時間複雜度也是O(log n)。(這裏不一步步推倒了,只要記住,查詢時每次減小一半的元素的時間複雜度都是O(log n),好比二叉樹的查找、二分法查找、歸併排序、快速排序)

空間複雜度

咱們仍是以標準的跳錶來分析,每兩個元素向上提取一個元素,那麼,最後額外須要的空間就是:

n/2 + (n/2)^2 + (n/2)^3 + ... + 8 + 4 + 2 = n - 2

因此,跳錶的空間複雜度是O(n)。

總結

(1)跳錶是能夠實現二分查找的有序鏈表;

(2)每一個元素插入時隨機生成它的level;

(3)最低層包含全部的元素;

(4)若是一個元素出如今level(x),那麼它確定出如今x如下的level中;

(5)每一個索引節點包含兩個指針,一個向下,一個向右;

(6)跳錶查詢、插入、刪除的時間複雜度爲O(log n),與平衡二叉樹接近;

彩蛋

爲何Redis選擇使用跳錶而不是紅黑樹來實現有序集合?

首先,咱們來分析下Redis的有序集合支持的操做:

1)插入元素

2)刪除元素

3)查找元素

4)有序輸出全部元素

5)查找區間內全部元素

其中,前4項紅黑樹均可以完成,且時間複雜度與跳錶一致。

可是,最後一項,紅黑樹的效率就沒有跳錶高了。

在跳錶中,要查找區間的元素,咱們只要定位到兩個區間端點在最低層級的位置,而後按順序遍歷元素就能夠了,很是高效。

而紅黑樹只能定位到端點後,再從首位置開始每次都要查找後繼節點,相對來講是比較耗時的。

此外,跳錶實現起來很容易且易讀,紅黑樹實現起來相對困難,因此Redis選擇使用跳錶來實現有序集合。


歡迎關注個人公衆號「彤哥讀源碼」,查看更多源碼系列文章, 與彤哥一塊兒暢遊源碼的海洋。

qrcode

相關文章
相關標籤/搜索