有時候會被問到鏈表若是作到二分搜索,可能會有部分的人會去把鏈表中的值保存到數組來進行二分,可是若是知道跳躍表的話,那麼這個數據結構就能夠解決這個困惑,它容許快速查詢一個有序連續元素的數據鏈表,它的效率能夠作到和二分相同,都是O(logn)的平均時間複雜度,其空間複雜度爲O(n)。html
跳躍列表是在不少應用中有可能替代平衡樹而做爲實現方法的一種數據結構。跳躍列表的算法有同平衡樹同樣的漸進的預期時間邊界,而且更簡單、更快速和使用更少的空間。----by 發明者像是redis中有序集合就使用到了跳躍表。web
首先,應該要了解跳躍表的性質;redis
- 由不少層結構組成;
- 每一層都是一個有序的鏈表,排列順序爲由高層到底層,都至少包含兩個鏈表節點,分別是前面的head節點和後面的nil節點;
- 最底層的鏈表包含了全部的元素;
- 若是一個元素出如今某一層的鏈表中,那麼在該層之下的鏈表也全都會出現(上一層的元素是當前層的元素的子集);
- 鏈表中的每一個節點都包含兩個指針,一個指向同一層的下一個鏈表節點,另外一個指向下一層的同一個鏈表節點;
![](http://static.javashuo.com/static/loading.gif)
能夠看到,這裏一共有4層,最上面就是最高層(Level 3),最下面的層就是最底層(Level 0),而後每一列中的鏈表節點中的值都是相同的,用指針來鏈接着。跳躍表的層數跟結構中最高節點的高度相同。理想狀況下,跳躍表結構中第一層中存在全部的節點,第二層只有一半的節點,並且是均勻間隔,第三層則存在1/4的節點,而且是均勻間隔的,以此類推,這樣理想的層數就是logN。算法
其基本原理就是從最高層的鏈表節點開始,若是比當前節點要大和比當前層的下一個節點要小,那麼則往下找,也就是和當前層的下一層的節點的下一個節點進行比較,以此類推,一直找到最底層的最後一個節點,若是找到則返回,反之則返回空。數組
![](http://static.javashuo.com/static/loading.gif)
代碼實現大體爲:數據結構
find(x)
{
p = top;
while (1) {
while (p->next->key < x)
p = p->next;
if (p->down == NULL)
return p->next;
p = p->down;
}
}
既然要插入,首先須要肯定插入的層數,這裏有不同的方法。1. 看到一些博客寫的是拋硬幣,只要是正面就累加,直到碰見反面才中止,最後記錄正面的次數並將其做爲要添加新元素的層;2. 還有就是一些博客裏面寫的統計機率,先給定一個機率p,產生一個0到1之間的隨機數,若是這個隨機數小於p,則將高度加1,直到產生的隨機數大於機率p才中止,根據給出的結論,當機率爲1/2或者是1/4的時候,總體的性能會比較好(其實當p爲1/2的時候,也就是拋硬幣的方法)。app
當肯定好要插入的層數之後,則須要將元素都插入到從最底層到第k層。ide
在各個層中找到包含指定值的節點,而後將節點從鏈表中刪除便可,若是刪除之後只剩下頭尾兩個節點,則刪除這一層。性能