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的节点。

  1. 我们首先获取到头节点,从头检点的最高层开始(节点中的点表示指向节点的指针),下一个节点是17,很明显20>17所以应该在后面。继续往后结果是NULL那说明后面没有要找的节点了。
  2. 跳到下一层继续往后是25且20<25说明后面也没有我们要找的节点了。
  3. 再跳到下一层,往后就找到我们要的节点了。如果到最下面一层还找不到,那这个节点就肯定不在表中了(因为最低层包含所有节点)。

这里写图片描述

对比一下,如果只有一层(图中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(跳表)

原创粉丝点击