什么是跳跃表

引子

能够完成动态数据的增删改查最简便的数据结构是什么?

链表

什么是跳跃表
链表查询的时间复杂度是O(n)。如何修改最简单的链表,能够让它查得快一点呢?

什么是跳跃表
我们可以多增加一些连接,让它形成网络的结构。

什么是跳跃表
你也可以把它改成一棵树,当然这也可以说是另一种数据结构了。

我们今天要讲跳跃表,skip list。

再增加一张链表,情况会变得很不同。


地铁的例子

某城市的地铁有两条线,一条慢线,它包含所有的车站;一条快线,它的车站是慢线的一个真子集。

什么是跳跃表
数字表示街道号。

慢线位于第二层(最底层),快线在第一层。

比如你要去121街道。

什么是跳跃表

最好的选择是先走快线,走开100街道,然后走慢线,到121街道。

这个就是跳跃表。

跳跃表的第一条规则就是:最底层(在这里我们用L2表示)要包含所有的节点。

那么问题来了:L1(上一层)应该设置几个呢?


L1的理想数值

L1的合理设计是:均匀分布。

既然L1均匀分布,那么查询一个节点的时间就是:
T=L1+L2L1 T=|L_1|+\frac{|L_2|}{|L_1|}

L1|L_1|表示L1L_1的长度或者说节点数量。

假设最初的节点数量是nn。也就是说L2=n|L_2|=n,要使得TT尽量的小,L1|L_1|要取什么值呢?

T=L1+nL12n T=|L_1|+\frac{n}{|L_1|} \geq 2 \sqrt{n}

当且仅当L1=n|L_1|=\sqrt{n}时取到最小值。

所以完美的跳跃表应该是这个样子的:

什么是跳跃表

让跳跃表更快

如何让跳跃表查得更快?

设计更多的层。

什么是跳跃表
以上的结果是推测的,当然也可以证明。

现在的关键问题是kk等于几,使得查询时间最小?

或者说,在已知最底层的数量的情况下(nn),跳跃表应该设计几层?

什么是跳跃表

所以查询的时间复杂度是O(log2n)O(\log_2n)

重新设计地铁线

按照上面的推理,我们重新设计地铁线。

因为n=8n=8,所以我们设计三层。

那么层与层之间的比率是多少呢?假设第一层的节点数是是rr,于是r3=8r^3=8,因此第一层有两个节点。第二层我们设置4个节点。

什么是跳跃表