1. 程式人生 > >跳躍表的分析與實現

跳躍表的分析與實現

insert text 站點 avi 初始 解析 鏈接 solid water

----《大規模分布式存儲系統:原理解析與架構實戰》讀書筆記

在了解了

Bitcask存儲模型後,又開始研究LSM樹存儲引擎。LSM在實現的過程中使用了一個非常有意思的數據結構:跳躍表。

之前在《算法導論公開課》中聽過這一節。當時感覺這樣的結構和二叉樹簡直是殊途同歸,可是一直沒有親自己主動手實現過。這次又遇到了。就來實現試試看。話說跳躍表和各種平衡樹一樣,都是用來加速查詢的。要隨手實現一個B樹不easy,可是實現一個跳躍表就簡單非常多。

跳躍表的簡介

跳躍列表一個有序鏈表,按層建造的。底層是一個普通的有序鏈表。每一個更高層都充當以下列表的"高速跑道",查找一個元素時,能夠先通過高層的“快車道”。在快車道上找不到時,從最接近目標元素的快車道逐步進入慢車道,直到最後找的目標元素。


分析的時候。經常使用的形狀例如以下:

技術分享


各層是全然分開的列表。可是在實際實現中,則使用的為例如以下結構:

技術分享

這樣的方式將多條聯表的值合並到一起,同一時候使用指針來構造高層"快車道"。這樣的方式管理起來簡單。節省空間。

更具體的介紹,請看跳表SkipList。

跳躍表的復雜度分析以及概率因子p

來看看跳躍表的復雜度分析:

  • 空間復雜度: O(n) (期望)
  • 跳躍表高度: O(logn) (期望)

相關操作的時間復雜度:

  • 查找: O(logn) (期望)
  • 插入: O(logn) (期望)
  • 刪除: O(logn) (期望)

跳躍表的操作時間負責度是基於概率的,全部加上了期望。


在層 i 中的元素按某個固定的概率 p 出如今層 i+1 中。當p=1/2或者1/e的時候查找的性能最好。

更具體的對照。請看到這篇文章:跳躍表。其中對不同概率的P對查詢性能的影響做了對照。

跳躍表的高度

實際使用時。假設高度太高。會造成空間浪費。我們要做一個空間和時間的平衡。那麽跳躍表的高度多少最合適?
如果跳躍表中的元素個數為N,當跳躍表的高度為log(N)時,跳躍表進化為一個二叉樹結構,其查詢次數與二分查找法一致。這無疑最理想的結果。

假設有一億條記錄,高度log(N)約等於30。redis中。最大高度也就是32。最多能夠存幾億條記錄。

通常,我們用不了這麽多記錄。所以高度能夠減少一點。

跳躍表的實現

跳躍表在levledb和redis中均有實現。

二者都是用C實現的。我這個實現是C++版本號的

  • skiplist
  • skiplist0.2。

主要特點為:

  • 支持模板
  • 0.2版本號添加了對叠代器和反向叠代器的支持
  • 可自己定義高度,默覺得8。0.2版本號版本號改為了16
    由於高度為8的話適合幾百條的記錄,這時候,選用跳躍表並沒有太多優勢,不如之間使用排序數組。將默認值改為16的話,能夠方便幾萬條記錄大小的地方使用。

  • 概率p:臨時使用p=1/2
  • 做過單元測試,放心使用啦

初始版本號簡單直接。支持的函數為insert,find,remove。不支持範圍操作。0.2版本號增了對了叠代器的支持。
另外,在實現的時候也遇到一些問題,要註意模板編程與平時編程有所不同,平時編程通常實現和定義分離,分別放在.cpp和.h中。

可是模板編程編寫的一般是沒有具現的實現。為了方便。一般定義和實現都會放在.h文件裏。

初始版本號簡單直接,支持的函數為insert,find,remove。不再介紹。以下是0.2版本號實現的函數及其功能:
void insert(const_value_type &value)
在當前表中插入value值。值能夠反復。
void remove(const_value_type &value)
刪除第一個值為value的元素。

反復值須要多次刪除
void clear()
清空跳躍表
iterator find(const_value_type &value)
返回第一個值為value的元素的叠代器,否則返回end.
iterator begin(int level = 0)
返回指向當前表中第level層的第一個元素的叠代器。使用begin的時候,能夠指定遍歷不同的層。默覺得最底層。這個實際上並非標準的叠代器。為了實現分層遍歷進行了特化。
iterator end() const
返回指向當前表中最後一個元素的叠代器。
iterator rbegin() const
返回指向當前表中最後一個元素的反向叠代器。
iterator rend() const
返回指向表中第一個元素的反向叠代器。
unsigned long size()
返回當前表中元素的數目
unsigned int level()
返回當前表的總層數
unsigned int maxlevel()
返回當前表的能使用的最大層數
bool empty()
推斷表是否為空

代碼地址見上面的鏈接。


歡迎光臨我的站點----蝴蝶忽然的博客園----人既無名的專欄。
假設閱讀本文過程中有不論什麽問題,請聯系作者,轉載請註明出處。


跳躍表的分析與實現