有時候會被問到鏈表如果做到二分搜索,可能會有部分的人會去把鏈表中的值保存到數組來進行二分,但是如果知道跳躍表的話,那么這個數據結構就可以解決這個困惑,它允許快速查詢一個有序連續元素的數據鏈表,它的效率可以做到和二分相同,都是O(logn)的平均時間復雜度,其空間復雜度為O(n)。
跳躍列表是在很多應用中有可能替代平衡樹而作為實現方法的一種數據結構。跳躍列表的算法有同平衡樹一樣的漸進的預期時間邊界,並且更簡單、更快速和使用更少的空間。----by 發明者像是redis中有序集合就使用到了跳躍表。
首先,應該要了解跳躍表的性質;
- 由很多層結構組成;
- 每一層都是一個有序的鏈表,排列順序為由高層到底層,都至少包含兩個鏈表節點,分別是前面的head節點和后面的nil節點;
- 最底層的鏈表包含了所有的元素;
- 如果一個元素出現在某一層的鏈表中,那么在該層之下的鏈表也全都會出現(上一層的元素是當前層的元素的子集);
- 鏈表中的每個節點都包含兩個指針,一個指向同一層的下一個鏈表節點,另一個指向下一層的同一個鏈表節點;

可以看到,這里一共有4層,最上面就是最高層(Level 3),最下面的層就是最底層(Level 0),然后每一列中的鏈表節點中的值都是相同的,用指針來連接着。跳躍表的層數跟結構中最高節點的高度相同。理想情況下,跳躍表結構中第一層中存在所有的節點,第二層只有一半的節點,而且是均勻間隔,第三層則存在1/4的節點,並且是均勻間隔的,以此類推,這樣理想的層數就是logN。
其基本原理就是從最高層的鏈表節點開始,如果比當前節點要大和比當前層的下一個節點要小,那么則往下找,也就是和當前層的下一層的節點的下一個節點進行比較,以此類推,一直找到最底層的最后一個節點,如果找到則返回,反之則返回空。

代碼實現大致為:
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的時候,也就是拋硬幣的方法)。
當確定好要插入的層數以后,則需要將元素都插入到從最底層到第k層。
在各個層中找到包含指定值的節點,然后將節點從鏈表中刪除即可,如果刪除以后只剩下頭尾兩個節點,則刪除這一層。