14 跳表思想

跳表

二分查找的依赖是数组的随机访问的特性,所以只能用数组实现。但是只要对链表进行 稍微改造也能支持类似“二分查找的”的算法功能。这个结构叫跳表。
跳表可以支持快速插入、删除、查找功能,写起来也不算复杂,是一种优秀的动态数据结构。

理解跳表

对于单链表,每次查找都要从头遍历到尾部,查找效率极低,时间复杂度高,是O(n)。
在这里插入图片描述

可以通过索引让链表查询得更快。
例如建立一级索引,由原始链表每两个结点到上一级,这个上一级就叫索引或者索引层。图中的down表示down指标,指向下一级。
在这里插入图片描述

例如查找16,可以先在索引层遍历,遍历到13的时候发现下一个结点是17,所以16在13和17中间,此时通过索引13结点的down指针下降到原始链表,继续遍历,下降到原始链表结点13后再遍历一次就寻得了 16。
总结:如果是直接遍历原始链表,需要遍历10个结点,现在通过一级索引只需要遍历7个结点即可, 即查找的效率提高了。
在这里插入图片描述

在一级索引之上建立二级索引,每两个一级索引结点就抽一个结点到二级索引,现在再查找16,只需要遍历6个结点。
在这里插入图片描述

以上两个例子数据量不大,体现不明显。现在有一个64结点的链表,建立五级索引,查找62。

原本需要遍历62个结点的链表,现在只需要遍历11个结点即可找到62,查询效率大大提升,这种结构就叫跳表。

分析跳表时间复杂度

按上面所讲,每两个结点建立一个上级索引,假设有n个结点,那么一级索引结点就说n/2,二级索引是n/4,三级索引是n/8,第k级索引就是n/2k 个。

再假如,最高级的索引只有两个结点(二分查找),就可以得到 n/2k =2,从而求得K=log2n -1 ,再加上原始链表,就是k= log2n,那么如果在查询的时候,每一层都要遍历m个结点,那么查询一整个跳表的时间复杂度就是O(m*logn)

这个m是3,也就是说每一级索引只需遍历3个结点。看图
在这里插入图片描述

例如要查找数据x,在k级索引种,遍历到y结点时,发现y<x<z
索引此时通过y的down指针下降到k-1级索引,此时在k-1级索引,y和z有三个结点,需要遍历这三个结点才再决定怎么下去。
总结:因为m=3,所以跳表的时间复杂度是O(logn),跟二分查找的时间复杂度一样。也就是说基于链表实现了二分查找。但是空间换取时间的设计思路,通过建立多层索引,提升查询效率。

跳表空间复杂度

跳表一级索引结点是n/2,二级索引结点是n/4,三级是n/8,最高级是2。这是一个等比数列。
在这里插入图片描述

通过等比数列求和公式Sn= (qan - a1)/(q-1),即(尾项公比-首相)/(公比-1),可算得节点总数是n-2。
所以索引空间复杂度是O(n)。所以跳表的空间复杂度=原始链表的空间复杂度O(n)+索引空间复杂度O(n)

上面是两个结点抽到上一级索引,那么当我们修改成每隔3个结点或者5个结点再抽节点到上级,是不是就不需要那么多结点呢。在这里插入图片描述

如图所示,一级索引需要n/3,二级n/9,,三级n/27个结点,这也是个等比数列。
在这里插入图片描述

根据等比公式求和算得结点总和是n/2,比上面2个结点抽一次索引少了一半的索引结点存储空间。

总结:实际开发种,不需要太过于在意索引占用的空间,因为在实际中,原始链表结点存储的是对象,而索引链表只需存储关键值和几个指针,远远比存储对象小的多。所以索引占用的空间可以省略。

跳表的插入和删除

对单链表,插入时间复杂度是O(1),但是在插入之前需要遍历一次链表找到插入的位置,遍历复杂度是O(n)。
但对于跳表而言,遍历某个结点的时间复杂度是O(logn),所以插入的效率很高。
在这里插入图片描述

对于删除操作,如果删除的结点在索引中出现过,那么除了要删除原始链表的结点外,还需要删除索引的结点。
且需要找到删除结点的前驱结点的位置(双向链表除外)。

索引的动态更新

如果一直插入数据不更新索引,会出现两个索引结点之间的数据非常多的情况。极端条件下会退化成单链表。
在这里插入图片描述

跳表作为一种动态数据结构,需要一种维护索引和原始链表大小之间的平衡:当原始链表的结点多了,索引节点也需要及时增加,避免复杂度退化,影响查询、插入、删除的性能下降。
可以通过一个随机函数将这个增加的结点随机插入到那几级索引中,例如随机函数随机生成了k,就把这个结点添加到一级索引到k级索引之中,
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值