SkipList 以及高度的确定
轉(zhuǎn)載:https://www.cnblogs.com/lnlvinso/p/8848883.html
? 結(jié)果:skiplist的高度是個(gè)隨機(jī)值。
SkipList理解
記下自己對(duì)跳表SkipList的理解。
? ? ? ??SkipList采用空間換時(shí)間的思想,通過增加數(shù)據(jù)間的鏈接,達(dá)到加快查找速度的目的。
? ? ? ? 數(shù)據(jù)庫LevelDB和RocksDB中用到了SkipList,Redis中的有序set即zset也用到了SkipList。Java中也提供了ConcurrentSkipListMap,在并發(fā)量大的情況下,ConcurrentSkipListMap性能好。
? ? ? ? 先看SkipList的查找過程,引用網(wǎng)上的經(jīng)典圖片,查找19。注意的是數(shù)據(jù)是有序的。
? ? ? ? ? 查找的過程從上至下,查找指針?biāo)?jīng)歷的位置順序如圖中的1,2,3,直到找到目標(biāo)數(shù)據(jù)19。
? ? ? ? ? 再加一張圖,是怎么二分法查找的。
??
? ? ? ? ? ?
? SkipList中創(chuàng)建新結(jié)點(diǎn)時(shí),產(chǎn)生一個(gè)在1~MAX_LEVEL之間的隨機(jī)level值作為該結(jié)點(diǎn)的level。每個(gè)節(jié)點(diǎn)的高度是隨機(jī)的。
? ? ? ? ? ? MAX_LEVEL可以靜態(tài)指定,也可以動(dòng)態(tài)增長(zhǎng)。
? ? ? ? ? ? 關(guān)于MAX_LEVEL,覺得這篇文章的解釋是比較清楚的:https://blog.csdn.net/kisimple/article/details/38706729。下面是復(fù)制了部分的內(nèi)容
? ? ? ? ? ??
每個(gè)節(jié)點(diǎn)所能reach到的最遠(yuǎn)的節(jié)點(diǎn)是隨機(jī)的,正如作者所說,SkipList使用的是概率平衡而不是強(qiáng)制平衡。
O(logN)?
既然是隨機(jī)算法,那怎么能保證O(logN)的復(fù)雜度?SkipList作者在論文中有給出了說明,這里從另一個(gè)角度說下我的理解。先定義一下,A node that has k forward pointers is called a level k node。假設(shè)k層節(jié)點(diǎn)的數(shù)量是k+1層節(jié)點(diǎn)的P倍,那么其實(shí)這個(gè)SkipList可以看成是一棵平衡的P叉樹,從最頂層開始查找某個(gè)節(jié)點(diǎn)需要的時(shí)間是O(logpN),which is O(logN) when p is a constant。
下面看下Redis與LevelDB中實(shí)現(xiàn)SkipList所使用的隨機(jī)算法。
Redis
? ?在t_zset.c中找到了redis使用的隨機(jī)算法。
?
/* 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; }?
執(zhí)行l(wèi)evel += 1;的概率為ZSKIPLIST_P,也就是說k層節(jié)點(diǎn)的數(shù)量是k+1層節(jié)點(diǎn)的1/ZSKIPLIST_P倍。ZSKIPLIST_P(這個(gè)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相當(dāng)于是一棵四叉樹。
LevelDB
在skiplist.h中找到了LevelDB使用的隨機(jī)算法。
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;不就是這個(gè)意思嗎^_^)。? ? ? ? ? ? 總結(jié):skiplist是有序的,采用類似二分法方式進(jìn)行查找。查找、插入的平均時(shí)間復(fù)雜度是O(ln2)。
總結(jié)
以上是生活随笔為你收集整理的SkipList 以及高度的确定的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于Proteus的51单片机超声波测距
- 下一篇: 触屏西门子plc和计算机通讯,西门子S7