数据结构 | SkipList(跳表)

Posted ENOC

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构 | SkipList(跳表)相关的知识,希望对你有一定的参考价值。

写在前面

该文并不是跳表的入门文章,而是致力于以简洁精炼的语言来描述 SkipList,来弥补上次面试时被问到跳表结果脑中只有图片没有文字的尴尬场景。。。



SkipList(跳表)

SkipList 是一种查找结构

结构

它的结构是一个有序链表,但是该链表的节点的具有多个指针,且不止指向下一个节点。在该链表上,每 N 个节点还会拥有一个指向后第 N 个节点的指针,N 值通常为 2 的幂。一个节点上可能具有多个 N 值指针,指针按照 N 值大小从高到低排序,分为多个"层"


查找

当要查找的时候:

  1. 头节点具有所有的 N 值的指针,头节点为当前节点
  2. 取出当前节点具有的最高的 N 值的指针
  3. 观察该指针指向的节点的值
  4. 如果等于目标值,说明节点找到,退出
  5. 如果大于目标值,将当前高度减一
    1. 若此时高度为零,说明值不存在,退出
    2. 否则,返回到 第 3 步
  6. 如果小于目标值,前进到该节点,返回到 第 2 步
  7. 当来到尾部时,代表值不存在,退出

在查找的时候,由于 N 值为 2 的幂,故每一次 高度减一 ,需要查找的节点就会减少一半,所以时间复杂度为 \\(O(logN)\\)

但如果这样,由于插入和删除时需要维护 N 值的正确性,时间复杂度可能退化为 \\(O(N)\\) 。所以改进为了插入时高度随机取值。

且为了保证层数越高越稀疏,该随机值不会随机分布,其计算过程如下:

  1. 起始高度为 1
  2. 下一层被创建的概率为 \\(P\\)
  3. 若未到达高度上限,且创建成功,则回到第二步
  4. 此时的高度值则为要插入节点的当前高度

插入

对于插入来讲,由于我们使用了随机高度的做法,所以不需要维护 N 值的正确性,故变得十分简单。

只需要先进行一次查找的过程,同时记录发生了高度下降的节点,在查找完成后根据高度,来从记录中更改引用关系。

时间复杂度为 \\(O(logN)\\)


删除

删除则也与插入同理,只不过更改引用关系时执行的是将前置节点与后置节点连接的操作。

但是需要这需要对所有高度进行查找,所以节点最好选用双向链表,可以减少复杂度。

时间复杂度为 \\(O(logN)\\)


与红黑树的对比

跳表的时间复杂度与红黑树相同,且都是用于在内存中的一种查找结构。

当然也有不同的地方,Redis 的开发者还给出了使用跳表的理由

There are a few reasons:

  1. They are not very memory intensive. It\'s up to you basically. Changing parameters about the probability of a node to have a given number of levels will make then less memory intensive than btrees.

  2. A sorted set is often target of many ZRANGE or ZREVRANGE operations, that is, traversing the skip list as a linked list. With this operation the cache locality of skip lists is at least as good as with other kind of balanced trees.

  3. They are simpler to implement, debug, and so forth. For instance thanks to the skip list simplicity I received a patch (already in Redis master) with augmented skip lists implementing ZRANK in O(log(N)). It required little changes to the code.


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


什么是跳跃表SkipList

跳跃表(简称跳表)由美国计算机科学家William Pugh于1989年发明

论文: Skip lists: a probabilistic alternative to balanced trees

跳表(SkipList,全称跳跃表)是用于有序元素序列快速搜索查找的一个数据结构,跳表是一个随机化的数据结构,实质就是一种可以进行二分查找的有序链表

跳表在原有的有序链表上面增加了多级索引,通过索引来实现快速查找。

跳表不仅能提高搜索性能,同时也可以提高插入和删除操作的性能。它在性能上和红黑树,AVL树不相上下,但是跳表的原理非常简单,实现也比红黑树简单很多。

以上是关于数据结构 | SkipList(跳表)的主要内容,如果未能解决你的问题,请参考以下文章

数据结构--跳表

数据结构--跳表

数据结构--跳表

五Redis源码数据结构之跳表skiplist

SkipList 跳表

数据结构与算法—跳表(skiplist)