数据结构与算法之美【11】-跳表

目录

一、什么是跳表

二、跳表的内存问题

三、跳表的复杂度分析

四、跳表索引动态更新


一、什么是跳表

我们知道链表这种结构,虽然他的插入和删除的时间复杂度很高,只有O(1),但是它的查找却很慢,为O(n)。例如我们要查找一个元素,不得不遍历一边链表才能找到:

但是其实我们能像下图中那样,对链表建立一级“索引”,以提高查找速度,即每两个结点提取一个结点到上一级,我们把抽出来的那一级叫做索引或索引层,索引层有个next指针指向索引在链表中位置:

当然这只是一级索引,如果数据量庞大,我们可以建立两级、三级,甚至十级索引,这样的链表查找时间复杂度可以高达O(logn)。

这种链表加多级索引的结构,就是跳表。

二、跳表的内存问题

也许你也已经发现了,在链表上添加这些索引,会明显的增大内存,因为需要额外的空间来存储这些索引层元素。

这几级索引的结点总和就是 n/2+n/4+n/8…+8+4+2=n-2。所以,跳表的空间复杂度是 O(n)。

但是因为索引层元素实际上只是存储了一个next指针(指向下一个索引)以及down指针(指向下一级索引),所以如果链表内的实际有效数据很大,那这些指针的内存完全可以忽略不计。

而且我们也可以通过跳转索引间隔,来动态的控制索引所占内存,例如我们修改索引间隔为3时。

总的索引结点大约就是 n/3+n/9+n/27+...+9+3+1=n/2。尽管空间复杂度还是 O(n),但比上面的每两个结点抽一个结点的索引构建方法,要减少了一半的索引结点存储空间。

三、跳表的复杂度分析

跳表的查找、删除和插入的时间复杂度都是O(logn)。

四、跳表索引动态更新

当我们不停地往跳表中插入数据时,如果我们不更新索引,就有可能出现某 2 个索引结点之间数据非常多的情况。极端情况下,跳表还会退化成单链表。

所以当我们往跳表中插入数据的时候,我们可以选择同时将这个数据插入到部分索引层中。如何选择加入哪些索引层呢?我们通过一个随机函数,来决定将这个结点插入到哪几级索引中,比如随机函数生成了值 K,那我们就将这个结点添加到第一级到第 K 级这 K 级索引中。随机函数的选择很有讲究,从概率上来讲,能够保证跳表的索引大小和数据大小平衡性,不至于性能过度退化。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chiang木

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值