什么是跳表

对于单链表这种数据结构,如果我们想查找一个结点需要从头到尾遍历所有结点,时间复杂度为O(n)效率非常低效。

如果我们想办法在单链表的一些结点上加索引呢?如图

图中原始链表每隔2个节点就抽出一个结点作为索引,抽出的这一层我们称之为“索引层”,第一层索引层我们称之为第一层索引。

就比如我们想此时要查找10这个节点,我们需要遍历6个节点就可以找到。

如果再抽取一个索引层,效率会更高,我这里虽然还是遍历了6个节点,不过这是因为例子中的单链表数据量小看不出来。

这种链表+多级索引的结构就是跳表

跳表查询的时间复杂度

假如原始单链表节点数为N,按照之前每两个节点抽取一个索引节点,则第一层索引结点个数约为N/2,第二层索引的节点个数约为N/4,第三层的索引个数为N/8,依次类推,第K层索引的节点个数是第K-1层索引节点个数的1/2,那么第K层索引的节点个数为N/2^k.假设索引层有h层,最高层索引有2个节点,则可以得到N/2^h=2,则h=logN-1,如果包含原始链表层,整个跳表高度是logN.

如果在跳表中每一层索引需要遍历m个节点,则在跳表中查询一个数据的时间复杂度为O(m*logN).

那么m的值是多少?按照每两个节点抽取一个索引节点的逻辑,每一层最多需要遍历3个节点,所以m=3.则跳表的时间复杂度为O(logN).效率的确是很高的。

那么为什么m就等于3呢?

结合下图应该可以看出来,查找10,需要确定9,而确定9需要在第一层索引确定位置,确定9需要确定前驱节点7的位置,确定7则需要在第二层索引确定7的位置,而确定这些索引节点最多每层遍历3个元素。

也就是这些多级索引把一个单链表分成了一个个的区间段,每次索引层的查找都确定了一个小的区间段,于是就提高了效率,但是却浪费了建立索引需要的空间,这就是空间换时间的思路。

跳表的空间复杂度分析

假设单链表的长度为N,第一级索引大概N/2个节点,第二级索引大概N/4个节点,第三级索引大概N/4个节点。依次类推直到剩下2个索引节点。于是组成了一个等比数列:N/2、N/4、N/8、.........8、4、2,这些级的索引加起来等于n-2,所以跳表的空间复杂度O(N),即长度为N单链表在每隔两个节点抽取一个索引节点时,组成的跳表需要额外N个节点来存储索引。

如何降低空间复杂度?很容易想到就是每隔三个或者五个再抽取出一个索引节点,这样的索引节点就会大大减少。

如果每隔三个节点抽取一个索引节点,那么第一层索引节点数大概为N/3,第二层索引的节点数大概为N/9,依次类推假设最后一层索引节点数为1,则组成的等比数列是N/3、N/9、N/27、.......9、3、1.加起来的和为N/2,空间占用差不多减少了一半的存储。

实际上索引占用空间相比原始单链表本身节点小巫见大巫了,毕竟一半节点中存储的是对象,而索引中只是id什么的。占不了多少。

高效的动态插入和删除

跳表不仅支持查找,而且支持动态插入和删除,而且动态插入和删除的时间复杂度也是O(logN).

单链表在确定操作位置时,进行插入和删除的时间复杂度都为O(1),所以通过跳表在O(logN)内确定操作位置后,对原始链表的插入和删除时间复杂度就是O(1),总体时间复杂度为O(logN).

如图是一个插入数据6的过程。

在删除节点的时候,跟插入略有不同,就是如果删除的节点出现在索引中,需要一并删除索引。

跳表增删查操作时间复杂度退化问题

在不停往跳表中插入数据而不更新跳表索引的情况下,很容易造成跳表某个索引区间内数据过多,造成跳表退化成单链表的情况。

所以我们应当在插入时维护原始链表和索引之间的平衡关系,比如可以使用一个随机函数决定插入的数据作为索引插入到哪些索引层中。如图

Redis为何使用跳表实现Zset

首先是跳表支持动态插入和删除以及查询的时间复杂度都是O(logN)表现的很高效,

其次则是跳表的代码实现相对如红黑树来说是比较容易的,虽然跳表的实现也不简单。

其实我这里跳表的代码和红黑树的代码实现都没有去研究,只是介绍了跳表做一个简单的入门。

如果有不明白的可以一起交流,欢迎留言~

查找算法-跳跃表(SkipList)入门及复杂度分析相关推荐

  1. Redis中ZSet的底层数据结构跳跃表skiplist,你真的了解吗?

    欢迎大家关注我的微信公众号[老周聊架构],Java后端主流技术栈的原理.源码分析.架构以及各种互联网高并发.高性能.高可用的解决方案. 一.前言 老周写这篇文章的初衷是这样的,之前项目中有大量使用 R ...

  2. Redis 为什么这么快? Redis 的有序集合 zset 的底层实现原理是什么? —— 跳跃表 skiplist

    Redis有序集合 zset 的底层实现--跳跃表skiplist Redis简介 Redis是一个开源的内存中的数据结构存储系统,它可以用作:数据库.缓存和消息中间件. 它支持多种类型的数据结构,如 ...

  3. 跳跃表 skipList 跳表的原理以及golang实现

    跳跃表 skipList 调表的原理以及golang实现 调表skiplist 是一个特殊的链表,相比一般的链表有更高的查找效率,跳跃表的查找,插入,删除的时间复杂度O(logN) Redis中的有序 ...

  4. 高级数据结构与算法 | 跳跃表(Skip List)

    文章目录 区间查询时链表与顺序表的局限 跳表=链表+索引 跳表的原理 晋升 插入 删除 跳表的实现 跳表VS红黑树 区间查询时链表与顺序表的局限 假设有这样一个情景, 此时需要设计一个拍卖系统,对于商 ...

  5. Redis数据结构——跳跃表-skiplist

    跳跃表简介: 跳跃表是一种有序数据结构,通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的. 跳跃表支持评价O(logN).最坏O(N)复杂度的节点查找,还可以通过顺序性操作来批量 ...

  6. 算法笔记(一):复杂度分析:最好、最坏、平均、均摊

    数据结构指的是"一组数据的存储结构", 算法指的是"操作数据的一组方法". 数据结构是为算法服务的,算法是要作用再特定的数据结构上的. 效率和资源消耗的度量衡- ...

  7. redis sorted_set跳跃表(skiplist)

    Sortedset底层存储结构 两种数据结构支持 ziplist和 skiplist 只有同时满足如下条件是,使用的是ziplist 1.有序集合保存的元素数量小于128个 2.有序集合保存的所有元素 ...

  8. 0046算法笔记——【随机化算法】舍伍德随机化思想解决跳跃表问题

    问题描述 如果用有序链表来表示一个含有n个元素的有序集S,则在最坏情况下,搜索S中一个元素需要O(n)计算时间.提高有序链表效率的一个技巧是在有序链表的部分结点处增设附加指针以提高其搜索性能.在增设附 ...

  9. 大话数据结构读书笔记艾提拉总结 查找算法 和排序算法比较好 第1章数据结构绪论 1 第2章算法 17 第3章线性表 41 第4章栈与队列 87 第5章串 123 第6章树 149 第7章图 21

    大话数据结构读书笔记艾提拉总结 查找算法 和排序算法比较好 第1章数据结构绪论 1 第2章算法 17 第3章线性表 41 第4章栈与队列 87 第5章串 123 第6章树 149 第7章图 211 第 ...

  10. 每日一博 - 如何理解跳表(SkipList)

    文章目录 什么是跳跃表SkipList 跳表关键字 Why Skip List Code 跳表-查询 跳表-删除 跳表-插入 小结 完整Code 什么是跳跃表SkipList 跳跃表(简称跳表)由美国 ...

最新文章

  1. html中单双引号嵌套,[转]详细讲述asp中单引号与双引号(即引号多重嵌套)的用法...
  2. R语言包_plotly
  3. DayDayUp:本博主预计2019下半年将会出两本书(关于人工智能算法及其实战案例应用方向、计算机算法竞赛集锦方向),如有合作意向,请留言告知
  4. NOIP2018退役记
  5. 北斗导航 | Select Satellite 选星算法
  6. border-radius圆角兼容方案
  7. JavaScript的运动 —— 缓冲运动及其应用篇
  8. Lattice 的 Framebuffer IP核使用调试笔记之datasheet笔记
  9. jrebel 远程部署 配置记录
  10. (译)如何使用cocos2d来制作简单的iphone游戏:更猛的怪物和更多的关卡。(第三部分。完!)...
  11. codeforces 615B. Longtail Hedgehog
  12. micropython api_micropython和python 微云
  13. 马云的至暗时刻:支付宝事件、十月围城 | 阿里巴巴20年
  14. google检索技巧-从菜鸟到黑客
  15. 游戏角色模型怎么做?3D建模小白学习从什么软件开始?
  16. 山西对口升学本科学校计算机,2019山西中职对口升学本科第一批院校录取分数线公布...
  17. matlab中的AR模型短时预测交通流
  18. 关于苹果审核4.3的一些猜想
  19. 安卓手机APP播放系统铃声,不同于媒体铃声
  20. Java程序员,面试阿里Java开发你必需要先理解的题库!

热门文章

  1. 多线程批量检测未注册域名
  2. IOS------网易新闻滚动标题
  3. IT运维面试问题总结
  4. lightoj1138
  5. 特殊字符在英语中的读法
  6. httclient出现的entity consumed
  7. Python Spider入门
  8. poi操作word,写入一个图片,并且设置其大小,以及图片和base64之间的互相转换,以及表格内容替换和插入
  9. Exiting because of unfinished merge.
  10. L1-1 寻找250(10 分)