二分查找法依赖于数组的随机访问特性,只能用数组实现
跳表是基于链表实现类似于二分查找的算法
查找、插入、删除各方面性能都不错的动态数据结构,甚至可以替代红黑树
Redis 中的有序集合(Sorted Set)就是用跳表来实现的
上级索引通过指针下降到下级索引
当每级索引都是两个结点抽出一个结点作为上一级索引的结点时,每一层最多遍历3个结点
时间复杂度为 $O(2*logn)$,即 $O(logn)$
如果每一层最多要遍历 m 个结点,那么时间复杂度为 $O(m*logn)$
在单链表中,如果知道要插入的位置,插入结点的时间复杂度是 $O(1)$
为了保证原始链表中数据的有序性,需要先找到要插入的位置,这个查找操作比较耗时
查找某个结点的的时间复杂度是 $O(logn)$,查找某个数据应该插入的位置,时间复杂度也是 $O(logn)$
比起单链表,跳表需要存储多级索引,要消耗更多的存储空间
如果将包含 n 个结点的单链表构造成跳表,需要额外再用接近 n 个结点的存储空间
每隔三个结点抽出一个结点比每隔两个会节省索引存储空间,但性能会下降
在实际的软件开发中,原始链表中存储的可能是很大的对象
而索引结点只需要存储关键值和几个指针,并不需要存储对象
所以当对象比索引结点大很多时,索引占用的额外空间可以忽略
跳表中插入数据,如果不更新索引,某 2 个索引结点之间数据过多,性能退化
跳表是通过随机函数来维护索引与原始链表大小之间的平衡
通过随机函数,来决定将这个结点插入到哪几级索引中
比如随机函数生成了值 K,就将这个结点添加到第一级到第 K 级索引中
随机函数的选取很重要,从概率上来讲,能够保证跳表的索引大小和数据大小平衡性,避免性能过度退化