跳躍表(Skip Lists)是一種有序的數據結構,它經過在每一個節點中維持多個指向其餘節點的指針,從而達到快速訪問節點的目的。在大部分狀況下,跳躍表的效率能夠和平衡樹相媲美,而且在實現上比平衡樹要更爲簡單,於是獲得了普遍的應用。算法
如上圖所示,是一個跳躍表的示例。由此能夠看出跳躍表的幾個特色:編程
有序性,如上圖中各節點呈遞增趨勢;數據結構
跳躍表由多個層組成;架構
跳躍表的第一層始終包含全部元素;框架
若是某個元素位於第 i 層,那該層一下的全部層也會包含此元素。性能
既然是鏈表的一種,那在實現時,當然要考慮插入、刪除、查找等幾個主要方法,下面來一一解析。設計
查找3d
要查找一個元素,應從頂層開始,自頂向下查找,又由於其有序性,所以與平衡樹上的查找其實很相似。指針
以以前的圖爲例,要搜索 12,從頂層爲入口,步驟大體以下:blog
從 L3 的第一個節點查詢後一個節點 21,發現比 12 大,跳至下一層;
從 L2 的第一個節點查詢後一個節點 9,比 12 小,所以繼續向後;
繼續查詢 L2 的下一個節點 21,比 12 大,跳至下一層;
從 L1 的第一個節點開始查詢,直至 17 時發現比 12 大,再次調至下一層;
從 L0 的第一個節點開始查詢,最終發現 12 這個節點,查詢結束。
若是要查詢的節點在 L0 中都不存在,則應返回並告知「該節點不存在」。
插入
要插入一個節點,不難想象首先須要查詢插入的位置,所以首先實際上是相似的執行一次查詢。而後視狀況定是作替換操做仍是新增節點。插入的時候要利用一個隨機算法來獲取該元素要插入的層高,並根據「若是某個元素位於第 i 層,那該層一下的全部層也會包含此元素」這一特性,在要插入層和如下層中都要插入這個新元素。最後還要注意維護層高。如下是插入過程的一個示例:
刪除
刪除的第一步和插入很相似,首先要執行查找過程。若是查找到,則將該元素刪除。這裏也必須注意「若是某個元素位於第 i 層,那該層一下的全部層也會包含此元素」這一特性。最後還要注意維護層高。
性能上,跳躍表支持平均 O(log N)、最壞 O(N) 複雜度的節點查找,還能夠經過順序性操做來批量處理節點。
代碼實如今網上有不少代碼能夠參考,且實現方法和細節也不盡相同,所以不在這裏說起,而是更多的關注原理。有時候掌握基礎與原理其實更爲重要。
本文的插圖來自於 William Pugh 關於跳躍表的論文《Skip Lists: A Probabilistic Alternative to Balanced Trees》,其中分析了跳躍表的實現及性能,值得研讀。
——————————
推薦閱讀: