什么是跳跃链表
开发时经常使用的平衡数据结构有B数、红黑数,AVL数。但是如果让你实现其中一种,很难,实现起来费时间。而跳跃链表一种基于链表数组实现的快速查找数据结构,目前开源软件 Redis 和 LevelDB 都有用到它。它的效率和红黑树以及 AVL 树不相上下
跳跃链表结构
结构

- header:指向跳跃表的头节点
- maxLevel:记录目前跳跃表,层数最大节点的层数
- length:链表存在的元素长度
节点
跳跃链表节点的组成:前节点、后节点、分值(map的key值)、及存储对象 value
跳表是用空间来换时间
- 在我实现的跳跃链表节点,包括一个 levelNode 成员属性。它就是节点层。跳跃链表能实现快速访问的关键点就是它
- 平时访问一个数组,我们是顺序遍历的,而跳跃链表效率比数组链表高,是因为它使用节点层存储多级索引,形成一个稀疏索引,所以需要的更多的内存空间
跳跃链表有多快

- 如果一个链表有 n 个结点,每两个结点抽取出一个结点建立索引的话,那么第一层索引的结点数大约就是 n/2,第二层索引的结点数大约为 n/4,以此类推第 m 层索引的节点数大约为 n/(2^m)
- 访问数据时可以从 m 层索引查询定位到 m-1 层索引数据。而 m-1 大约是 m 层的1/2。也就是说最优的时间复杂度为O(log/N)
- 最差情况。在实际实现中,每一层索引是无法每次以数据数量对折一次实现一层索引。因此折中的方式,每一层的索引是随机用全量数据建一条。也就是说最差情况时间复杂度为O(N),但最优时间复杂度不变
查询
- 查询一开始是遍历最高层 maxLevel 的索引 m。按照以下步骤查询出等于 score 或者最接近 score 的左节点
○ 1:如果同层索引的 next 节点分值小于查询分值,则跳到 next 节点。cur = next
○ 2:如果 next 为空。或者next节点分值大于查询分值。则跳到下一层 m-1 索引,循环 2
○ 循环 1、2 步骤直到访问到节点分值和查询分值一致,或者索引层为零
插入
- 如果分值存在则替换 value
- 如果分值对应节点不存在,则随机一个索引层数 level (取值 0~31)。然后依靠节点属性 levelNode 加入 0 到 level 层的索引
删除
- 使用 get 方法找到元素,然后解除节点属性 levelNode 在每一层索引的前后引用关系即可
使用示例
参考文章
- redis设计与实现
- 跳表(跳跃表,skipList)总结-java版[1]
- 数据结构与算法——跳表[2]
文章转载自公众号:潜行前行