这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战
前言
面试造火箭,工作拧螺丝,这是造火箭系列第三期,今天我们来聊一下又一个面试官贼喜欢问,工作上没什么卵用的问题 —— Redis跳表实现。
什么是跳跃表
首先来介绍一下跳跃表,它是一种有序的数据结构,在Redis里面主要被用来做有序集合的一个底层实现之一,在使用跳跃表查询的过程中,它平均复杂度是O(logn)级别的,最差也就渠道O(n)级别,而且实现起来也简单,所以Redis就用了它。
跳跃表的实现
对于跳跃表的实现整体上可以分为两个部分来说,节点Node和用于保存节点信息的List
从图中我们可以看到List的结构同之前链表的实现非常类似,也是四个数据
type List struct {
Header *Node //指向表头节点
Tail *Node //指向表尾节点
Level int //记录跳表的最大层数(表头节点不算)
Leagth int //记录跳跃表的长度(表头节点不算)
}
而Node节点也是有四个值
type Node struct {
BackWard *Node //后退指针
Score int // 分值
Object interface{} // 成员对象
Level level //层级数据
}
type level struct {
ForWard *Node //前进指针
Span int //跨度
}
首先来解释一下值的一个作用
层Level
从上面的level结构体可以看出,每一个层内都包含了指向下一个节点的指针,程序可以通过这些层来加快访问速度,一般来说,层越多,访问速度越快。
后退指针
主要是表尾节点可以回访表头节点的一个作用,但是因为每个节点只有一个后退指针,所以在访问的时候,也就只能回退至前一个节点了。
分治和成员
节点的成员对象也是一个指针,它指向的是一个SDS对象,而对于分值,跳跃表中所有的节点都是按照从小到大排序的。
总结
通过跳跃表的一个实现,可以快速的定位到表头节点以及表尾节点,以及获取跳跃表的长度等等,通过指针访问表头和表尾的复杂度是O(1),而获取长度等的复杂度也是O(1)