講講跳躍表(Skip Lists)

跳躍表(Skip Lists)是一種有序的數據結構,它經過在每一個節點中維持多個指向其餘節點的指針,從而達到快速訪問節點的目的。在大部分狀況下,跳躍表的效率能夠和平衡樹相媲美,而且在實現上比平衡樹要更爲簡單,於是獲得了普遍的應用。算法

如上圖所示,是一個跳躍表的示例。由此能夠看出跳躍表的幾個特色:編程

  • 有序性,如上圖中各節點呈遞增趨勢;數據結構

  • 跳躍表由多個層組成;架構

  • 跳躍表的第一層始終包含全部元素;框架

  • 若是某個元素位於第 i 層,那該層一下的全部層也會包含此元素。性能

既然是鏈表的一種,那在實現時,當然要考慮插入、刪除、查找等幾個主要方法,下面來一一解析。設計

查找3d

要查找一個元素,應從頂層開始,自頂向下查找,又由於其有序性,所以與平衡樹上的查找其實很相似。指針

以以前的圖爲例,要搜索 12,從頂層爲入口,步驟大體以下:blog

  1. 從 L3 的第一個節點查詢後一個節點 21,發現比 12 大,跳至下一層;

  2. 從 L2 的第一個節點查詢後一個節點 9,比 12 小,所以繼續向後;

  3. 繼續查詢 L2 的下一個節點 21,比 12 大,跳至下一層;

  4. 從 L1 的第一個節點開始查詢,直至 17 時發現比 12 大,再次調至下一層;

  5. 從 L0 的第一個節點開始查詢,最終發現 12 這個節點,查詢結束。

若是要查詢的節點在 L0 中都不存在,則應返回並告知「該節點不存在」。

插入

要插入一個節點,不難想象首先須要查詢插入的位置,所以首先實際上是相似的執行一次查詢。而後視狀況定是作替換操做仍是新增節點。插入的時候要利用一個隨機算法來獲取該元素要插入的層高,並根據「若是某個元素位於第 i 層,那該層一下的全部層也會包含此元素」這一特性,在要插入層和如下層中都要插入這個新元素。最後還要注意維護層高。如下是插入過程的一個示例:

刪除

刪除的第一步和插入很相似,首先要執行查找過程。若是查找到,則將該元素刪除。這裏也必須注意「若是某個元素位於第 i 層,那該層一下的全部層也會包含此元素」這一特性。最後還要注意維護層高。

性能上,跳躍表支持平均 O(log N)、最壞 O(N) 複雜度的節點查找,還能夠經過順序性操做來批量處理節點。

代碼實如今網上有不少代碼能夠參考,且實現方法和細節也不盡相同,所以不在這裏說起,而是更多的關注原理。有時候掌握基礎與原理其實更爲重要。

本文的插圖來自於 William Pugh 關於跳躍表的論文《Skip Lists: A Probabilistic Alternative to Balanced Trees》,其中分析了跳躍表的實現及性能,值得研讀。

——————————

推薦閱讀:

說框架設計思路

老王說架構

一次性講透Activiti工做流

FaaS技術架構

華爲Java編程軍規,每季度代碼驗收標準

相關文章
相關標籤/搜索