算法通关村番外篇-跳表

大家好我是苏麟 , 今天来聊聊调表 .

跳表很少很少实现所以我们只了解就可以了 . 

跳表

链表在查找元素的时候,因为需要逐一查找,所以查询效率非常低,时间复杂度是O(N),于是就出现了跳表。跳表是在链表基础上改进过来的,实现了一种「多层」的有序链表,这样的好处是能快读定位数据。

那跳表长什么样呢?我这里举个例子,下图展示了一个层级为 3 的跳表。

图中头节点有 L0~L2 三个头指针,分别指向了不同层级的节点,然后每个层级的节点都通过指针连接起来:

  • L0 层级共有 5 个节点,分别是节点1、2、3、4、5;
  • L1 层级共有 3 个节点,分别是节点 2、3、5;
  • L2 层级只有 1 个节点,也就是节点 3 。

如果我们要在链表中查找节点 4 这个元素,只能从头开始遍历链表,需要查找 4 次,而使用了跳表后,只需要查找 2 次就能定位到节点 4,因为可以在头节点直接从 L2 层级跳到节点 3,然后再往前遍历找到节点 4。

可以看到,这个查找过程就是在多个层级上跳来跳去,最后定位到元素。当数据量很大时,跳表的查找复杂度就是 O(logN)。

跳表节点层数设置

跳表的相邻两层的节点数量的比例会影响跳表的查询性能。

举个例子,下图的跳表,第二层的节点数量只有 1 个,而第一层的节点数量有 6 个。

这时,如果想要查询节点 6,那基本就跟链表的查询复杂度一样,就需要在第一层的节点中依次顺序查找,复杂度就是 O(N) 了。所以,为了降低查询复杂度,我们就需要维持相邻层结点数间的关系。

跳表的相邻两层的节点数量最理想的比例是 2:1,查找复杂度可以降低到 O(logN)

下图的跳表就是,相邻两层的节点数量的比例是 2 : 1。

那怎样才能维持相邻两层的节点数量的比例为 2 : 1 呢?

如果采用新增节点或者删除节点时,来调整跳表节点以维持比例的方法的话,会带来额外的开销。

Redis 则采用一种巧妙的方法是,跳表在创建节点的时候,随机生成每个节点的层数,并没有严格维持相邻两层的节点数量比例为 2 : 1 的情况。

具体的做法是,跳表在创建节点时候,会生成范围为[0-1]的一个随机数,如果这个随机数小于 0.25(相当于概率 25%),那么层数就增加 1 层,然后继续生成下一个随机数,直到随机数的结果大于 0.25 结束,最终确定该节点的层数

这样的做法,相当于每增加一层的概率不超过 25%,层数越高,概率越低,层高最大限制是 64。

虽然我前面讲解跳表的时候,图中的跳表的「头节点」都是 3 层高,但是其实如果层高最大限制是 64,那么在创建跳表「头节点」的时候,就会直接创建 64 层高的头节点

跳表的插入与删除

假设我们要插入的节点是10,首先找到待插节点的前置节点(仅小于待插入节点):

接下来,按照一般链表的插入方式,把节点10插到节点9的下一个 位置:

这样是不是插入工作就完成了呢?并不是。随着原始链表的新节 点越来越多,索引会渐渐变得不够用了,因此索引节点也需要相应做 出调整

如何调整索引呢?我们让新插入的节点随机“晋升”,也就是成 为索引节点。新节点晋升成功的几率是50%。

假设第一次随机的结果是晋升成功,那么我们把节点10作为索引 节点,插到第1层索引的对应位置,并且向下指向原始链表的节点10:

新节点在成功晋升之后,仍然有机会继续向上一层索引晋升。我 们再进行一次随机,假设随机的结果是晋升失败,那么插入操作就告 一段落了。

新节点10已经晋升到 第2层索引,下一次随机的结果仍然是晋升成功,这时候我们该怎么 办?

这时候,我们直接让索引增加一层,就像下面这样:

至于跳表删除节点的过程,则是相反的思路。

假设我们要从跳表中删除节点10,首先按照跳表查找节点的方 法,找到待删除的节点:

接下来,按照一般链表的删除方式,把节点10从原始链表当中删 除:

这样是不是删除工作就完成了呢?并不是。我们需要顺藤摸瓜, 把索引当中的对应节点也一一删除:

那么,如果某一层索引的节点被删光了,该怎么办呢?

很好解决,直接把没有节点的那一层删去就好了。

在刚才的例子当中,第3层索引的节点已经没有了,因此我们把整 个第3层删去:

最终的删除结果如下:


这期就到这里 , 下期见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/614953.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV——图像按位运算

目录 一、算法概述1、逻辑运算2、函数解析3、用途 二、代码实现三、结果展示 OpenCV——图像按位运算由CSDN点云侠原创,爬虫自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、算法概述 1、逻辑运算 OpenCV4 针对两个图像之…

JDBC初体验(二)——增、删、改、查

本课目标 理解SQL注入的概念 掌握 PreparedStatement 接口的使用 熟练使用JDBC完成数据库的增、删、改、查操作 SQL注入 注入原理:利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行能力,它可以通过在…

银河麒麟v10安装前端环境(Node、vue、Electron+vite)

此帖子所提到的所有依赖包都是基于银河麒麟v10真机的arm架构包,如果是在windows上的虚拟机上 把依赖包换成x64的包即可,方法步骤都是一样 一.node安装 原始方法安装(建议用第二种nvm方法,因为更简单): 1…

基于Docker官方php:5.6.40-fpm镜像构建支持66个常见模组的php5.6.40镜像

实践说明:基于RHEL7(CentOS7.9)部署docker环境(23.0.1、24.0.2),所构建的php5.6.40镜像应用于RHEL7-9(如AlmaLinux9.1),但因为docker的特性,适用场景是不限于此的。 文档形成时期:2017-2023年 因系统或软件版本不同&am…

工业异常检测AnomalyGPT-训练试跑及问题解决

写在前面,AnomalyGPT训练试跑遇到的坑大部分好解决,只有在保存模型失败的地方卡了一天才解决,本来是个小问题,昨天没解决的时候尝试放弃在单卡的4090上训练,但换一台机器又遇到了新的问题,最后决定还是回来…

图像识别与计算机视觉有什么区别?

图像识别和计算机视觉在很多方面存在差异,这些差异主要体现在以下几个方面: 1. 研究范围 图像识别是计算机视觉领域的一个子集。计算机视觉不仅包括图像识别,还涵盖了更广泛的内容,如场景理解、目标跟踪、分割、识别和解释等。简而…

Android12 关机流程

Android12 关机流程 Android 关机流程的意义在于确保系统可以安全地关闭,并且所有用户数据得到妥善保存,以防止数据丢失和损坏。 Android 关机流程确保系统可以安全地关闭,并且所有用户数据得到妥善保存。 保存用户数据:在 Android 关机过程中,系统会通知应用程序和服务进…

jsPlumb、mxGraph和Antv x6实现流程图选型

解决方案 结合我们项目以及主流解决方案,提供以下几种方案: 序号技术栈性质是否开源说明1jsPlumb国外框架社区版、商业版中台项目现有方案2mxGraph国外框架开源比较有名的开源绘图网站draw.io (和processOn类似),使用…

力扣48. 旋转图像

几何翻转 思路: 顺时针旋转可以拆解成: 先沿着水平中轴线进行翻转: m[i][j] -> m[n - 1 - i][j] (x1 x2) / 2 (n - 1) / 2x1 (n - 1) - x2y 轴不变沿着主对角线进行翻转: m[i][j] -> m[j][i] class Solution { public:…

https 中 ssl/tls 的握手

如果使用了 https 协议,那么在建立 tcp 连接之后,还会进行 tls 握手。也就是 https 的证书验证和密钥传输的过程。简化的流程如下: 客户端发送请求服务端返回证书客户端验证证书,提取公钥,生成对称加密的密钥&#xf…

JavaScript基础02

1 - 运算符(操作符) 1.1 运算符的分类 运算符(operator)也被称为操作符,是用于实现赋值、比较和执行算数运算等功能的符号。 JavaScript中常用的运算符有: 算数运算符 递增和递减运算符 比较运算符 逻…

GBASE南大通用系统目录表

系统目录由描述数据库结构的表和视图组成。这些表对象有时称为数据字典,它们包含 数据库本身的所有信息。每个系统目录表都包含有关数据库中特定元素的信息。每个数据 库都有它自己的系统目录。 这些主题提供了有关系统目录表的结构、内容和使用的信息。还包含了有关…

第五站:C++的内存解析

目录 C内存分布 变量的四种存储方式 函数返回值使用指针(指针函数) 动态分配内存空间 不能使用外部函数的普通局部变量的地址 通过指针函数返回静态局部变量的地址 动态内存 根据需要分配内存,不浪费(根据用户的需求设置内存的容量) 被调用函数之外需要使用被调用函数内…

2024年1月11日 主题:非枪人生

2024年1月11日15:58:29 2024年1月11日15:35:13 2024年1月11日15:57:51 对物理进行大致预 2024年1月11日20:27:14 结论:不适合进行数据结构的训练和对电路的模拟感受 2024年1月11日20:28:32 今天也平静的结束了 不需要键盘的支持也就这么结束了我也不知道…

应用在LCD显示器电源插头里的氮化镓(GaN)MTC-65W1C

LCD(Liquid Crystal Display)显示器是利用液晶显示技术来进行图像表现的显示装置,从液晶显示器的结构来看,无论是笔记本电脑还是桌面系统,采用的LCD显示屏都是由不同部分组成的分层结构。LCD显示器按照控制方式不同可分…

适配 IOS 安全区域

安全区域指的是一个可视窗口范围,处于安全区域的内容不受圆角(corners)、齐刘海(sensor housing)、小黑条(Home Indicator)影响。 造成这个问题的主要原因就是 iphoneX 之后在屏幕上出现了所谓…

实现STM32烧写程序-(1)获取Bootloader版本信息

简介 如何像ST Flash Loader等工具一样写自己的烧写程序呢?文档 AN3155: USART protocol used in the STM32 bootloader 步骤 Boot模式 将 开发板例如STM32F103C8T6 Boot0->1 & Boo1->0 重启或复位进入系统存储模式 物理连接 将USART1 通过 USB转TTL线连接到…

NLP(十八):LLM 的推理优化技术纵览

原文:NLP(十八):LLM 的推理优化技术纵览 - 知乎 目录 收起 一、子图融合(subgraph fusion) 1.1 FasterTransformer by NVIDIA 1.2 DeepSpeed Inference by Microsoft 1.3 MLC LLM by TVM 二、模型压…

ListPreference详解与使用

ListPreference详解与使用 大家好,我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天,我们将深入探讨Android开发中常用的UI组件之一——“ListPreference”&a…

Windows7共享文档—开启方法及用户权限设置

使用计算机的朋友,在工作中经常需要在局域网中将文件共享给其他用户,这样其他人可以方便的通过局域网查看,甚至修改这些共享文件。当然,根据文件的重要程度,使用等级不同,不同的用户会赋予不同的权限&#…