转载: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 以及高度的确定相关推荐

  1. Leveldb skiplist 实现及解析

    skiplist 原理介绍 skiplist 由William Pugh 在论文Skip Lists: A Probabilistic Alternative to Balanced Trees 中提 ...

  2. folly::ConcurrentSkipList 详解

    SkipList 原理及构造过程 SkipList 是受多层链表的启发而设计出来的.实际上,最理想的情况是上面每一层链表的节点个数,是下面一层的节点个数的一半,这样查找过程就非常类似于一个二分查找,使 ...

  3. skiplist 跳表(1)

    最近学习中遇到一种新的数据结构,很实用,搬过来学习. 原文地址:skiplist 跳表   为什么选择跳表 目前经常使用的平衡数据结构有:B树,红黑树,AVL树,Splay Tree, Treep等. ...

  4. skiplist跳表的 实现

    文章目录 前言 跳表结构 时间复杂度 空间复杂度 高效的动态插入和删除 跳表索引的动态更新 总结 详细实现 前言 rocksdb 的memtable中默认使用跳表数据结构对有序数据进行的管理,为什么呢 ...

  5. SkipList 跳表

    转载:https://blog.csdn.net/fw0124/article/details/42780679 为什么选择跳表 说起跳表,我们还是要从二分查找开始. 二分查找的关键要求有两个, 1 ...

  6. SkipList 跳跃表

    http://blog.csdn.net/likun_tech/article/details/7354306 http://www.cnblogs.com/zhuangli/articles/127 ...

  7. 每日一博 - 如何理解跳表(SkipList)

    文章目录 什么是跳跃表SkipList 跳表关键字 Why Skip List Code 跳表-查询 跳表-删除 跳表-插入 小结 完整Code 什么是跳跃表SkipList 跳跃表(简称跳表)由美国 ...

  8. 跳表(skipList)

    一.为何有skipList这种数据结构的出现 我们知道二分查找算法之所以能达到 O(logn) 这样高效的一个重要原因在于它所依赖的数据结构是数组,数组支持随机访问一个元素,通过下标很容易定位到中间元 ...

  9. 数据映射--跳表(skiplist)

    http://blog.sina.com.cn/s/blog_693f08470101n2lv.html 本周我要介绍的数据结构,是我非常非常喜欢的一个数据结构,因为咱也是吃过平衡二叉树的苦的人啊T_ ...

最新文章

  1. linux监听9080,基于UPnP发现与组播技术的IPTV终端实现
  2. php 图片处理库 Imagick 代替 gd
  3. python分发包_Python 分发包中添加额外文件的方法
  4. mysql数据迁移到teradata_Mysql迁移到达梦数据库-Mysql到DM的应用迁移-给自增列赋值-GroupBy语法不兼容...
  5. python内置的读取文件函数_python基础(内置函数+文件操作+lambda)
  6. 简述systemd的新特性及unit常见类型分析、使用systemd管理编译安装的nginx
  7. html5 自定义 datepicker,如何使用 React 构建自定义日期选择器(3)
  8. 如何创建自定义性能计数器
  9. 诺基亚继续打情怀牌:怀旧小屏手机入网!
  10. c语言打程序时会遇到什么问题,Sublime text3 实现C语言编译运行以及过程中可能遇到的问题...
  11. Vue事件绑定(非常详细哦~)
  12. JAVA给枚举成员指定值
  13. Qcom 平台 camera 之 RAW+YUV图抓取
  14. 802.11ac中的Beamforming技术(4)
  15. 温度传感器—LM75
  16. 什么是OSINT?以及如何使用开源网络情报工具?
  17. 谈谈MATLAB数字滤波器频域响应
  18. 计算机桌面有阴影,电脑桌面图标有蓝色阴影怎么去掉
  19. mysql数据库--mysql的数据类型(数值型)
  20. 记录JVM中Eden区、Survivor from区和Survivor to区及Minor GC和Major GC的理解

热门文章

  1. day212223:线程、进程、协程
  2. 直击3.15 安防行业如何维护消费者权益
  3. 谷歌浏览器开发调试工具中Sources面板 js调试等 完全介绍
  4. jBPM4工作流开发实战 之 第五部分 其他知识
  5. 基于报文地址的策略路由配置示例
  6. Cisco无线AP的配置
  7. 进程的五种状态和线程的六种状态
  8. 【Sublime】使用 Sublime 工具时运行python文件
  9. ftp改为sftp_浅谈 FTP、FTPS 与 SFTP
  10. DES的原理及python实现