数据结构与算法之美(七)跳表:链表的二分查找

介绍

跳表是一种链表加多级索引动态数据结构,具体来说是每两个结点提取一个结点到上一级作为索引,如下图所示:
在这里插入图片描述

所以跳表相对于普通单链表,查找一个结点所需要遍历的结点个数减少了,也即查找效率提高了。跳表是一种支持二分查找的链表,可以快速地插入、删除、查找,甚至可以替代红黑树。Redis里的有序集合就是用跳表来实现的。

复杂度分析

时间复杂度

在跳表中查找、插入、删除的时间复杂度都是 O ( l o g n ) O(logn) O(logn)

1.查找的时间复杂度推导

  • 查多少层:对于结点个数为n的链表,会有多少级索引?第一级有 n 2 \frac{n}{2} 2n个结点,第二级有 n 2 2 \frac{n}{2^2} 22n个结点,第k级有 n 2 k \frac{n}{2^k} 2kn个结点,最后一级是2个结点,所以通过 n 2 k = 2 \frac{n}{2^k}=2 2kn=2,得到最后一级 k = l o g 2 n − 1 k=log_2n-1 k=log2n1。如果把原始链表也算作一级,那么最后一级就是 l o g 2 n log_2n log2n,所以一共查 l o g 2 n log_2n log2n层就能查到
  • 每层内查几次:最多3次。因为上一层决定了所查找的数在结点j和j+1之间,才会下到下一层去找,而上一层的结点j和j+1之间对应到下一层,只有三个结点
  • 总结:跳表的查找时间复杂度为 O ( 3 l o g 2 n ) = O ( l o g n ) O(3log_2n)=O(log n) O(3log2n)=O(logn)

2.插入的时间复杂度推导

单链表的插入:查找 O ( n ) O(n) O(n) + 插入 O ( 1 ) O(1) O(1)
跳表的插入:查找 O ( l o g n ) O(logn) O(logn) + 插入 O ( 1 ) O(1) O(1)

3.删除的时间复杂度推导

查找 O ( l o g n ) O(logn) O(logn)+删除 O ( 1 ) O(1) O(1),删除时要注意:记住前驱结点、如果索引中有也要删除索引中的

空间复杂度

跳表的空间复杂度为 O ( n ) O(n) O(n),具体推导如下:

  • 在分析时间复杂度时已经提到,对于结点个数为n的链表,会有 l o g 2 n − 1 log_2n-1 log2n1层索引,各层索引的结点数分别是 n 2 \frac{n}{2} 2n n 2 2 \frac{n}{2^2} 22n,…, n 2 k \frac{n}{2^k} 2kn,…,2这样的等比数列
  • 根据等比数列求和公式:
    在这里插入图片描述
    得到跳表的空间复杂度为 O ( n ) O(n) O(n)
    在这里插入图片描述

跳表的动态更新

跳表是一种动态数据结构,就是指它的索引是要动态更新的,特别是当插入了很多个结点、或者删除了一些结点时,可能会出现两个索引结点之间的下一层结点很多的情况,造成复杂度退化。

跳表通过随机函数来维护,当往跳表中插入数据的时候,可以选择同时将这个数据插入到部分索引层中,具体插入到从哪一级开始的索引是由一个随机函数生成的。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值