数据结构与算法篇 跳表(Skip list)

跳表(Skip list),就是会跳的链表。。。。。。是一种在各方面性能都比较优秀的数据结构,可以支持快速的插入,删除,查找操作,写起来完全没有红黑树那么复杂和难理解。

其中在Redis中的有序集合就是用跳表来实现的,其实红黑树也是一样的支持快速插入,删除和查找,那么为什么Redis要使用跳表实现有序集合,而在很多语言里为什么要使用红黑树来实现Map,例如C++STL

讲了这么多,我们来看一下怎么来理解跳表这种数据结构?就是链表+索引

在查找的时候,假如你想查找16,那么先会找到13,13小于16,然后就下一个17大于16,那么就是13的下一个,这样遍历的话只需要7次就可以找到了,就减少了3次遍历。

那我们再网上加一层索引会有怎样的效果呢?

这样我们只需要遍历6个节点就能找到了16了,当数据量和索引表都增加的时候,效果就会更加明显

到了这里大概对跳表有了大概了解了

那么接下来我们来看一下时间复杂度和空间复杂度

按照上图,我们是从每两个节点中抽出一个结点作为上一级的索引结点,第一级索引的结点数n/2  第二级是n/4  第三级是n/8,那么第k-1级是1/2,第k级是索引结点的个数是n/(2^k)

假如索引有h级,最高索引有2个结点

,通过上面的公式我们可以得到n/(2^h)=2,就可以得到h=log2n-1,假如包含最原始的链表,那么就是log2n,那么我们在每一次需要遍历m个结点,那么时间复杂度是O(m*logn),你试试自己取算算,发现m最大也就是3,综上所述时间复杂度是O(logn),这就是用空间换时间的

跳表的空间复杂度并不复杂,n/2,n/4,n/8,...8,4,2 = n-2,也就是一个等比数列,所以它的空间复杂度是O(n)

当我们每三个结点抽一个索引,那么就是n/3,n/9,n/27,...,9,3,1 = n/2,尽管空间复杂度还是O(n),但是减少了索引空间,当结点的数据量大的时候,索引这个结点就可以被忽略了。

接下来我们来看一下跳表的高效插入和删除,删除和插入的操作时间复杂度还是O(logn),无论是插入还是删除我们都是需要先进行查找找到位置先,然后插入结点或者是删除结点,也就是链表的操作,突然发现我没有写链表的学习记录,找一天补上。

 

当我学到这里的时候我第一反应就是,这样不会把跳表的性质给破坏了嘛,然后退化成了链表,就像二叉树一样,所以才有了AVL二叉树,那么这里也是一样,所以我们需要取动态维护跳表,避免产生退化,性能下降。

当我们往跳表插入数据的时候,我们同是将这个数据插入到部分索引层中,我们可以通过一个随机函数,来决定结点插入那几级索引中,比如产生了k=2,就是如图所示,从概率上来讲能保证跳表的索引大小和数据的平衡性,不至于性能过度退化。

关于开头讲到的为什么用跳表而不用红黑树,作者是这样说的

Redis 中的有序集合是通过跳表来实现的,严格点讲,其实还用到了散列表。不过散列表我们后面才会讲到,所以我们现在暂且忽略这部分。如果你去查看 Redis 的开发手册,就会发现,Redis 中的有序集合支持的核心操作主要有下面这几个:

插入一个数据;

删除一个数据;

查找一个数据;

按照区间查找数据(比如查找值在 [100, 356] 之间的数据);

迭代输出有序序列。

其中,插入、删除、查找以及迭代输出有序序列这几个操作,红黑树也可以完成,时间复杂度跟跳表是一样的。但是,按照区间来查找数据这个操作,红黑树的效率没有跳表高。

对于按照区间查找数据这个操作,跳表可以做到 O(logn) 的时间复杂度定位区间的起点,然后在原始链表中顺序往后遍历就可以了。这样做非常高效。

当然,Redis 之所以用跳表来实现有序集合,还有其他原因,比如,跳表更容易代码实现。虽然跳表的实现也不简单,但比起红黑树来说还是好懂、好写多了,而简单就意味着可读性好,不容易出错。还有,跳表更加灵活,它可以通过改变索引构建策略,有效平衡执行效率和内存消耗。

不过,跳表也不能完全替代红黑树。因为红黑树比跳表的出现要早一些,很多编程语言中的 Map 类型都是通过红黑树来实现的。我们做业务开发的时候,直接拿来用就可以了,不用费劲自己去实现一个红黑树,但是跳表并没有一个现成的实现,所以在开发中,如果你想使用跳表,必须要自己实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值