SkipList 以及高度的确定
轉載:https://www.cnblogs.com/lnlvinso/p/8848883.html
? 結果:skiplist的高度是個隨機值。
SkipList理解
記下自己對跳表SkipList的理解。
? ? ? ??SkipList采用空間換時間的思想,通過增加數據間的鏈接,達到加快查找速度的目的。
? ? ? ? 數據庫LevelDB和RocksDB中用到了SkipList,Redis中的有序set即zset也用到了SkipList。Java中也提供了ConcurrentSkipListMap,在并發量大的情況下,ConcurrentSkipListMap性能好。
? ? ? ? 先看SkipList的查找過程,引用網上的經典圖片,查找19。注意的是數據是有序的。
? ? ? ? ? 查找的過程從上至下,查找指針所經歷的位置順序如圖中的1,2,3,直到找到目標數據19。
? ? ? ? ? 再加一張圖,是怎么二分法查找的。
??
? ? ? ? ? ?
? SkipList中創建新結點時,產生一個在1~MAX_LEVEL之間的隨機level值作為該結點的level。每個節點的高度是隨機的。
? ? ? ? ? ? MAX_LEVEL可以靜態指定,也可以動態增長。
? ? ? ? ? ? 關于MAX_LEVEL,覺得這篇文章的解釋是比較清楚的:https://blog.csdn.net/kisimple/article/details/38706729。下面是復制了部分的內容
? ? ? ? ? ??
每個節點所能reach到的最遠的節點是隨機的,正如作者所說,SkipList使用的是概率平衡而不是強制平衡。
O(logN)?
既然是隨機算法,那怎么能保證O(logN)的復雜度?SkipList作者在論文中有給出了說明,這里從另一個角度說下我的理解。先定義一下,A node that has k forward pointers is called a level k node。假設k層節點的數量是k+1層節點的P倍,那么其實這個SkipList可以看成是一棵平衡的P叉樹,從最頂層開始查找某個節點需要的時間是O(logpN),which is O(logN) when p is a constant。
下面看下Redis與LevelDB中實現SkipList所使用的隨機算法。
Redis
? ?在t_zset.c中找到了redis使用的隨機算法。
?
/* Returns a random level for the new skiplist node we are going to create.* The return value of this function is between 1 and ZSKIPLIST_MAXLEVEL* (both inclusive), with a powerlaw-alike distribution where higher* levels are less likely to be returned. */ int zslRandomLevel(void) {int level = 1;while ((random()&0xFFFF) < (ZSKIPLIST_P * 0xFFFF))level += 1;return (level<ZSKIPLIST_MAXLEVEL) ? level : ZSKIPLIST_MAXLEVEL; }?
執行level += 1;的概率為ZSKIPLIST_P,也就是說k層節點的數量是k+1層節點的1/ZSKIPLIST_P倍。ZSKIPLIST_P(這個P是作者論文中的p)與ZSKIPLIST_MAXLEVEL在redis.h中定義,
#define ZSKIPLIST_MAXLEVEL 32 /* Should be enough for 2^32 elements */ #define ZSKIPLIST_P 0.25 /* Skiplist P = 1/4 */所以redis中的SkipList相當于是一棵四叉樹。
LevelDB
在skiplist.h中找到了LevelDB使用的隨機算法。
template<typename Key, class Comparator> int SkipList<Key,Comparator>::RandomHeight() {// Increase height with probability 1 in kBranchingstatic const unsigned int kBranching = 4;int height = 1;while (height < kMaxHeight && ((rnd_.Next() % kBranching) == 0)) {height++;}assert(height > 0);assert(height <= kMaxHeight);return height; } (rnd_.Next() % kBranching) == 0)的概率為1/kBranching,所以LevelDB中的SkipList也是一棵四叉樹(kBranching = 4;不就是這個意思嗎^_^)。? ? ? ? ? ? 總結:skiplist是有序的,采用類似二分法方式進行查找。查找、插入的平均時間復雜度是O(ln2)。
總結
以上是生活随笔為你收集整理的SkipList 以及高度的确定的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于Proteus的51单片机超声波测距
- 下一篇: linux编译动态库之-fPIC