数据结构与算法(九) 跳表

25 阅读3分钟

跳表的定义

  • 跳表,又叫做跳跃表、跳跃列表,在有序链表的基础上增加了“跳跃”的功能
  • 跳表在原来的有序链表上加上了多级索引,通过索引来快速查找;可以支持快速的删除、插入和查找操作。
  • 跳表实际上是一种增加了前向指针的链表,是一种随机化的数据结构
  • Redis中 的 SortedSet、LevelDB 中的 MemTable 都用到了跳表
  • 对比平衡树, 跳表的实现和维护会更加简单, 跳表的搜索、删除、添加的平均时间复杂度是 O(logn)

跳表的演化过程

对于单链表来说,即使数据是已经排好序的,想要查询其中的一个数据,只能从头开始遍历链表,这样效率很低,时间复杂度很高,是 O(n)。 那我们有没有什么办法来提高查询的效率呢?我们可以为链表建立一个“索引”,这样查找起来就会更快,如下图所示,我们在原始链表的基础上,每两个结点提取一个结点建立索引,我们把抽取出来的结点叫作索引层或者索引,down 表示指向原始链表节点的指针。

现在如果我们想查找一个数据,比如说 15,我们首先在索引层遍历,当我们遍历到索引层中值为 14 的结点时,我们发现下一个结点的值为 17,所以我们要找的 15 肯定在这两个结点之间。这时我们就通过 14 结点的 down 指针,回到原始链表,然后继续遍历,这个时候我们只需要再遍历两个结点,就能找到我们想要的数据。好我们从头看一下,整个过程我们一共遍历了 7 个结点就找到我们想要的值,如果没有建立索引层,而是用原始链表的话,我们需要遍历 10 个节点。

通过这个例子我们可以看出来,通过建立一个索引层,我们查找一个基点需要遍历的次数变少了,也就是查询的效率提高了。

那么如果我们给索引层再加一层索引呢?遍历的节点会不会更少呢,效率会不会更高呢?我们试试就知道了。

image.png

现在我们再来查找 15,我们从第二级索引开始,最后找到 15,一共遍历了 6 个节点,果然效率更高。

当然,因为我们举的这个例子数据量很小,所以效率提升的不是特别明显,如果数据量非常大的时候,我们多建立几层索引,效率提升的将会非常的明显,感兴趣的可以自己试一下,这里我们就不举例子了。

这种通过对链表加多级索引的机构,就是跳表了。

参考链接

跳表(Skip List)

数据结构与算法——跳表