关于跳表一二三

什么是跳表SkipList?

跳表是一个随机化的数据结构,实质上是一种可以进行二分查找的有序链表

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

跳表不仅能提高搜索性能,同时也可以提高插入和删除操作的性能,

有序链表

skiplist1
我们来想一个有序链表,我们要查找3、7、17这几个元素,但是在有序链表中我们只能是从头开始遍历链表,直到查找到元素位置。(因为链表有序,不能使用二分查找)

那么有什么办法可以实现有序链表的二分查找呢?

噔噔噔噔,跳表 就这样粉墨登场~

跳表怎么跳?

跳表随机的来决定其中的一些节点,将它提取出来,缓存一级索引,于是乎:
skiplist2
那么现在俺们就可以很快的查找到17这个元素了,只要从一级索引往后遍历即可,只要经过1、6、15、17这几个元素就可以找到17✔️

如果我们要找11这个元素呢?

我们从一级索引的 1 开始,向右是 6,本着没事儿走两步的想法,我们再走,走到了15,比 11 大,此路不可行。然后我们从 6 往下走,再从下面的 6 往右走,到了 7,然后再到11~
(ps:每个索引节点包含两个指针,一个向右 一个向下–不懂没关系,后面会讲到)

如一级索引的提取,我们还可以进行二级索引:
skiplist3
此时此刻,再去找一哈儿17,你就会发现只需要经过6、15、17就可以找到 So Esay有木有

这也就是跳表的核心思想,通过向上提取索引增加查找效率

跳表的插入

跳表除了可以跳(查询),还可以添(插入)

比如我们要向上面这个跳表添加一个元素8

首先,我们先根据掷硬币的方式,决定8这个元素要占据的层数

比如,层数level=2。

然后,找到8这个元素在下面两层的前置节点。

接着,就是链表的插入元素操作了,比较简单。

最后,就像下面这样:
在这里插入图片描述

跳表的删除

查询、插入元素都讲了,下面我们来看一下怎么删除元素

First 找到各层中包含元素X的节点

Second 使用标准的链表删除元素的方法删除即可

比如,要删除 17 这个元素:
在这里插入图片描述

标准化的跳表

上面举的黎子完全随机的跳表,如果我们每两个元素提取一个元素作为上一季的索引:
在这里插入图片描述
有点点像平衡二叉树,现在这颗树元素较少,不太明显
我们来看一个元素个数较多的情况
在这里插入图片描述
可以看到上一级元素的个数是下一级的一般,这样每次减少一半,就很接近平衡二叉树了

时间复杂度

我们知道单链表查询的时间复杂度为O(n),而插入、删除操作需要先找到对应的位置,所以插入、删除的时间复杂度也是O(n)。
那么,跳表的时间复杂度是多少呢?
如果按照标准的跳表来看的话,每一级索引减少k/2个元素(k为其下面一级索引的个数),那么整个跳表的高度就是(log n)。
学习过平衡二叉树的同学都知道,它的时间复杂度与树的高度成正比,即O(log n)。
所以,这里跳表的时间复杂度也是O(log n)。(这里不一步步推倒了,只要记住,查询时每次减少一半的元素的时间复杂度都是O(log n),比如二叉树的查找、二分法查找、归并排序、快速排序)

空间复杂度

我们还是以标准的跳表来分析,每两个元素向上提取一个元素,那么,最后额外需要的空间就是:
n/2 + (n/2)^2 + (n/2)^3 + … + 8 + 4 + 2 = n - 2
所以,跳表的空间复杂度是O(n)。

总结

(1)跳表是可以实现二分查找的有序链表;
(2)每个元素插入时随机生成它的level;
(3)最低层包含所有的元素;
(4)如果一个元素出现在level(x),那么它肯定出现在x以下的level中;
(5)每个索引节点包含两个指针,一个向下,一个向右;
(6)跳表查询、插入、删除的时间复杂度为O(log n),与平衡二叉树接近;

为什么Redis选择使用跳表而不是红黑树来实现有序集合?

首先,我们来分析下Redis的有序集合支持的操作:
1)插入元素
2)删除元素
3)查找元素
4)有序输出所有元素
5)查找区间内所有元素
其中,前4项红黑树都可以完成,且时间复杂度与跳表一致。
但是,最后一项,红黑树的效率就没有跳表高了。
在跳表中,要查找区间的元素,我们只要定位到两个区间端点在最低层级的位置,然后按顺序遍历元素就可以了,非常高效。
而红黑树只能定位到端点后,再从首位置开始每次都要查找后继节点,相对来说是比较耗时的。
此外,跳表实现起来很容易且易读,红黑树实现起来相对困难,所以Redis选择使用跳表来实现有序集合。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值