跳跃列表是一种数据结构。它允许快速查询一个有序连续元素的数据链表。跳跃列表的平均查找和插入时间复杂度都是 O (log n), 优于普通队列的 O (n)。
白话跳跃表
我们知道如果是普通的链表,查找为 O (n), 插入也会 O (n), 如果是数据量过大的情况下,肯定是无法忍受的,怎么办?给链表加索引,比如说给 100 个数里面随机给 10 个数加索引,如果索引分布均匀的话,那么时间复杂是不是最多查找 11 次?, 如果 11 次还嫌长了怎么办?继续提升索引,提升索引这个比例我们设置为 50%, 这样可以保证索引在每一层都能分布均匀,且上一层的索引数,差不多是下一层的两倍。听我这样讲是不是感觉很像平衡树的样子,是不是过程看起来很像。
跳跃表和平衡树的区别
跳跃列表不像平衡树等数据结构那样提供对最坏情况的性能保证:由于用来建造跳跃列表采用随机选取元素进入更高层的方法,在小概率情况下会生成一个不平衡的跳跃列表(最坏情况例如最底层仅有一个元素进入了更高层,此时跳跃列表的查找与普通列表一致)。但是在实际中它通常工作良好,随机化平衡方案也比平衡二叉查找树等数据结构中使用的确定性平衡方案容易实现。跳跃列表在并行计算中也很有用:插入可以在跳跃列表不同的部分并行地进行,而不用对数据结构进行全局的重新平衡。
跳跃表实现原理
从上面 skiplist 的创建和插入过程可以看出,每一个节点的层数(level)是随机出来的,而且新插入一个节点不会影响其它节点的层数。因此,插入操作只需要修改插入节点前后的指针,而不需要对很多节点都进行调整。这就降低了插入操作的复杂度。实际上,这是 skiplist 的一个很重要的特性,这让它在插入性能上明显优于平衡树
代码实现
下面我粘贴的是维基百科的伪代码实现,具体实现过程和伪代码差不多,提升节点采用是 50% 概率提升,来保证跳表索引高度为 log n。
伪代码如下
1 | make all nodes level 1 |
使用 golang 实现跳跃表
node 节点
1 | package jumptable |
跳跃表
1 | package jumptable |
进行测试
1 | package jumptable |
walkPreviousNode
k: 13 level 12
curNode.down 18542 --> 18542
k: 13 level 11
curNode.down 18542 --> 18542
k: 13 level 10
curNode.down 18542 --> 18542
k: 13 level 9
curNode.down 18542 --> 18542
k: 13 level 8
curNode.key > k 18542 --> 2659
curNode.down 2659 --> 2659
k: 13 level 7
curNode.down 2659 --> 2659
k: 13 level 6
curNode.down 2659 --> 2659
k: 13 level 5
curNode.down 2659 --> 2659
k: 13 level 4
curNode.down 2659 --> 2659
k: 13 level 3
curNode.key > k 2659 --> 1626
curNode.down 1626 --> 1626
k: 13 level 2
curNode.down 1626 --> 1626
k: 13 level 1
curNode.key > k 1626 --> 1436
curNode.down 1436 --> 1436
k: 13 level 0
curNode.key > k 1436 --> 1270
curNode.key > k 1270 --> 996
curNode.key > k 996 --> 964
curNode.key > k 964 --> 957
curNode.key > k 957 --> 848
curNode.key > k 848 --> 792
curNode.key > k 792 --> 759
curNode.key > k 759 --> 671
curNode.key > k 671 --> 513
curNode.key > k 513 --> 413
curNode.key > k 413 --> 99
curNode.key > k 99 --> 28
curNode.key > k 28 --> 13
共需要 28 步
13
可以看见差不多时间复杂度是 O (log n)
总结
作为一种简单的数据结构,在大多数应用中 Skip lists 能够代替平衡树。Skiplists 算法非常容易实现、扩展和修改。Skip lists 和进行过优化的平衡树有着同样高的性能,Skip lists 的性能远远超过未经优化的平衡二叉树。
Be the first person to leave a comment!