跳表

Redis的有序集合使用的就是跳表来实现的。

正常的单链表在查找的过程中只能使用顺序遍历,即便强行使用二分查找,时间复杂度也在O(n)上。那么如何快速地对单链表进行查找呢,可以考虑使用索引。
在原始链表上隔一定位置提取出一个元素作为索引链表即可抽出一级索引

image.png

根据上图我们可以在一级索引中再抽出部分元素作为索引从而得出二级索引,最终可以得到下图
image.png

这种链表加多级索引的数据结构就是跳表
时间复杂度:按照每两个节点上升一个索引的方法,最上层的高度的索引节点个数为2,则一级索引节点个数为n/2,二级索引节点个数为n/4,可以得到n/(2^h)=2,h=log2n-1。而每一层最多遍历3个节点,因为上层是抽离的间隔为2,所以跳表中查询一个数据的时间复杂度为O(3*logn),即为O(logn),从而实现了二分查找的时间复杂度。
image.png

空间复杂度:这几级索引的结点总和就是 n/2+n/4+n/8…+8+4+2=n-2,所以时间复杂度为O(n)。
原始链表中存储的有可能是很大的对象,而索引结点只需要存储关键值和几个指针,并不需要存储对象,所以当对象比索引结点大很多时,那索引占用的额外空间就可以忽略了

跳表的插入删除

在跳表的插入删除后很可能会破坏索引的平衡,导致复杂度退化,所以需要动态维护跳表的索引。

为什么Redis一定要用跳表来实现有序集合而不是红黑树

Redis 中的有序集合支持的核心操作主要有下面这几个:插入一个数据;删除一个数据;查找一个数据;按照区间查找数据(比如查找值在 [100, 356] 之间的数据);迭代输出有序序列。在红黑树中插入一个数据;删除一个数据;查找一个数据也可以在O(logn)完成,但是区间查找却无法完成,跳表的区间查找只要在O(logn)中找到了起始节点,就可以顺序遍历区间元素了

跳表在Redis中的实现
image.png

这里跨度的意思就是节点与节点之间相隔距离,若为原始数据链表,则跨度为1。


image.png

这里节点数是指第一层的节点数(不包含头节点)。

你可能感兴趣的:(跳表)