Skip List
来源:互联网 发布:win10 手写笔绘图软件 编辑:程序博客网 时间:2024/05/29 19:07
Skip List 是什么
我们常用数组和链表来组织数据,对于已排序的数据,数组的查询时间复杂度可以是Θ(lgn)(二分查找),插入和删除都是Θ(n)。
链表提供了一种更加灵活的组织方式,插入和删除的时间复杂度是Θ(1),查询的时间复杂度是Θ(n)。
平衡树是更好的方案,查询、插入、删除的时间复杂度都是Θ(lgn),但实现上比较复杂。
Skip List作为性能和实现难度的一个折中,它的查询、插入、删除等主要操作时间复杂度也都是Θ(lgn),空间复杂度是Θ(n)。
一个Skip List的结构如下图,除了数据域,每个节点还包括1个或多个域用来保存后续节点的位置。
从结构上看,Skip List就是带有层级结构的链表(节点都是排好序的),最下面一层(level-0)是所有节点组成的一个链表,依次往上,每一层都也都是一个链表。不同的是,它们只包含一部分节点,并且越往上节点越少。仔细的话你会发现,通过增加层数,节点上可以带有更多的信息,通过这些信息可以直接访问更远的节点(这也是Skip List精髓所在),就像跳过去一样,所以取名叫Skip List(跳表)。
Skip List查询
查询操作很简单,比如我们要找图中节点key为20的节点。
- 我们首先获取到头节点,从头检点的最高层开始(节点中的点表示指向节点的指针),下一个节点是17,很明显20>17所以应该在后面。继续往后结果是NULL那说明后面没有要找的节点了。
- 跳到下一层继续往后是25且20<25说明后面也没有我们要找的节点了。
- 再跳到下一层,往后就找到我们要的节点了。如果到最下面一层还找不到,那这个节点就肯定不在表中了(因为最低层包含所有节点)。
对比一下,如果只有一层(图中level-0),我们要找20这个节点是需要5次才能找到,但是加上层级,我们有了更远节点的信息,利用更远节点的信息缩小查找范围,这里例子中我们只需要2次就找到了。
Skip List插入
插入操作稍微复杂, 首先我们要找到插入位置,怎么找我们刚才已经描述过了。如下图所示,插入key为10的节点,插入点应该是节点9和节点12之间(紫色的线表示要更新的指向)。然后是插入节点10,其实就是链表的逐层插入。
这里的需要注意是,逐层插入需要知道节点在每一层的位置,如在level-2中,节点10前面应该是头结点,而后面应该是节点17。 因为查询操作得到的只是最后位置,所以通常需要一个临时的空间来记录这些信息。如果节点的高度超过超过了Skip List的最大层数,那么Skip List的层数相应的需要升高。如节点10的高度是4的话,根据Skip List的结构特点,那么层数需要提高到level-3。
节点高度与Skip List的最大层数
节点的高度可以理解为需要多少域来保存后续节点的信息,Skip List的层数跟结构中最高节点的高度相等。理想的SkipList结构(如图一)是第一层有所有的节点,第二层只有1/2的节点,且是均匀间隔的,第三层是1/4的节点,且是均匀间隔的…,那么理想的层数是lgnlgn。
每一次插入一个新节点时,最好的做法就是根据当前表的结构得到一个合适的高度,插入后可以让Skip List的尽量的接近理想的结构,但是实现上这会非常的复杂。
Pugh论文中提出的方法是根据概率随机为新节点生成一个高度,具体的算法如下:
- 给定一个概率pp, 产生一个[0,1) 之间的随机数
- 如果这个随机数小于pp,则高度加1
虽然随机生成的高度会打破理想的结构,Pugh在论文中证明,这种结构依然有非常高概率可以使得时间复杂度为Θ(lgn)。
通常我们还会约束Skip List的最大层数,公式:maxLevel= log 1/p n其中n表示节点总数。 根据Pugh论文中的结论,p为1/2或者1/4时,整体性能会比较好。(当p=1/2时,确定节点高度有的地方称为抛硬币的方法)。
Skip List删除
删除操作跟插入操作类似。 首先找到我们要删除节点的位置,在查找时使用临时空间记录节点在每一级的位置。 接着就是逐层的链表删除操作。 最后记住要释放空间。 删除节点之后,如果最高层没有节点存在,那Skip List的层数相应的需要降下来。 下图表示节点9的删除操作。
小结
如果对链表的实现很熟悉,实现Skip List也很容易。本文没有具体代码,一方面我不想文章篇幅因为代码变得很大,另一方面网上已经有很多实现。关于复杂度分析,当p=1/2时或者理想结构下,很好分析。推广到一般情况,那么分析也会比较复杂,需要比较高的数学功底,有兴趣可以看看Pugh在论文,另外MIT的算法公开课教授对Skip List的讲解也非常棒。
参考资料
Skip List(跳跃表)原理详解与实现
skip list跳跃表实现
数据结构-skiplist(跳表)
- skip list
- skip list
- Skip List
- Skip list
- Skip List
- Skip List(跳跃表)
- 跳跃表Skip List
- 跳表(skip list)
- 跳表(skip list)
- 跳表 skip list
- Skip list----跳表
- skip list介绍
- c++实现skip list
- LevelDB : Skip List
- 跳跃表 Skip List
- Skip List 实现思路
- 跳跃表(Skip List)
- Redis skip list结构分析
- win7&win10清理垃圾代码
- Spring Cloud构建微服务架构:服务网关(基础)【Dalston版】
- 图像处理的方法列举(普通处理、灰度变换、图像锐化)
- 云栖大会所感所想
- 算法爱好者——判断某整数是否为两数平方之和 ? 待解决
- Skip List
- stm32学习笔记 F1系列通用定时器
- Python学习之网络编程Socket
- input 上传图片显示预览、调用摄像头,ios和Android的兼容性解决
- 形式参数-返回值-内部类-匿名内部类
- Intellij Idea 导入多个maven项目展示在右侧栏Maven Projects
- Ymodem 协议 改进的CAN—Ymodem协议
- 自定义S函数模块构成的Simulink模型C代码转化
- win 定时执行Php ?