二分法查找需要是有序的数据,并且数据是放在数组当中。
链表是否能实现二分查找呢?根据定义是无法实现的。
我们可以借助其他方式进行改造,就可以支持类似的二分查找算法。这种数据结构叫做跳表。
跳表
跳表是动态数据结构,可以支持快速的插入,删除,查找操作,甚至可以代替红黑树。
了解过数据库的同学都知道索引这个概念,数据库中借助索引来实现快速查询数据目的。
跳表中也是借用的这个思想实现的。
如上图所示,通过在链表的上层建立索引我们的数据量就减少了很多。
根据这个思想我们可以在索引的上层再次建立索引。然后在建立索引。逐层建立,能快速的进行查找到需要的数据
跳表的效率
根据两个点进行建立索引,那么一级索引上就需要n/2个节点个数,二级索引上就是n/4.....n/2^h 。 高度就是h = log2n -1。因为是中间两个节点,那么在索引期间,每一级索引就最多遍历三个节点包含头 - 中 - 尾。
时间复杂度就是log(3logn);
如果是按照中间间隔三个 或者5个 10个节点 计算方法也是类似的。
增加节点的方式也可以减少空间的占用,减少节点的数量。
计算方式是n/m,n/mm,n/mmm....1,
使用的空间就是将等比数列累加起来,求值。
高效的动态插入与删除
因为使用链表构成的,链表在做删除与插入的效率都是O(1).
在跳表中动态插入与删除的时间复杂度是O(logn).这个过程主要消耗的是查找的过程。
插入与删除需要更新索引序列。
动态更新
跳表通过随机函数进行更新数据索引的。
随机函数的选择根据概率来讲能够保证跳表的索引大小和数据大小平衡性。
Redis根据跳表实现有序集合
选择跳表的原因在于 有序集合查找需要实现区间的查找数据,在时间复杂度上跳表的实现要比红合数高效,直接从原始链表上往后遍历即可。
选择跳表还有其他原因,实现灵活,比红黑树简单,构建索引有效平衡效率与内存消耗。