跳表是一种有序的数据结构,它通过在每个节点中维持多个指向其他节点的指针来达到快速访问的目的。平均复杂度为o(logn)最坏复杂度为o(n).
在大部分情况下,跳表的效率都能与平衡树相媲美,并且因其更加简单的实现方式所以有不少程序都使用跳表代替平衡树。
Redis使用跳表作为有序集合键的底层实现之一,如果一个有序集合包含的元素较多,或者有序集合中的元素是比较长的字符串时,Redis就会使用跳表来作为有序集合的底层实现。
和其他数据结构相比,跳表在Redis中的应用并没有这么广泛,Redis只有在两个地方用到了跳表,一个是实现有序集合键另一个是在集群节点中用作内部数据结构。
跳表的实现
Redis中的跳表实现由跳表节点和跳表结构组成
跳表结构中包含指向表头的header指针、指向表尾的tail指针、记录目前跳表中最高的层高level、目前包含的节点也是跳表的长度length
跳表节点结构包含层(每层带有两个属性 前进指针和跨度)、后退指针、分值score、成员对象
跳跃表节点
层:是一个数组,可以包含多层,每个数组成员中有一个前进指针和跨度,每次创建一个新跳表节点的时候,程序都会根据幂次定律随机生成一个1到32层之间的值作为数组大小,值越大概率越小,一般来说层数越高访问速度越快
前进指针:每一层都有一个指向表尾的前进指针,用于从表头向表尾方向访问节点
跨度:用于计算排位,在查找某个节点的过程中,将经过的所有层的跨度加起来得到的结果就是目标节点在跳跃表中的排位
后退指针:用于从表尾向表头的方向遍历节点,逆序搜索,跟前进指针不同的是一次只能跨越一个节点
分值和成员:节点的分值是一个double类型的浮点数,所有节点都按分值从小到大来排序。成员对象是一个指针,它指向一个字符串对象,而字符串对象则存着一个SDS(!在同一个跳跃表中,各个节点保存的成员对象必须唯一,但是多个节点保存的分值可以相同,分值相同的节点按照成员对象在字典序中的大小来进行排序,小的排在前面)
跳跃表
通过多个跳跃表节点组成一个跳跃表,通过跳跃表结构来管理跳跃表
头指针和尾指针:o(1)复杂度找到头尾指针
length:跳跃表中包含多少个节点
level:表中层数最大节点的层数
总结
1、跳跃表是有序集合键的底层实现之一
2、跳跃表的实现由跳跃表节点结构和跳跃表结构两部分组成
3、每一个跳跃表节点层高都是1到32之间的随机数
4、同一个跳跃表中可以包含同一个数值但是不可以包含同一个对象
5、跳跃表中节点按照从小到大依次排列,分值相同的对象按照对象在字典序中大小从小到大排列