伸展树原理介绍

news/2024/5/3 15:00:55/文章来源:https://blog.csdn.net/chengqiuming/article/details/128048468

一 点睛

伸展树,也叫作分裂树,是一种二叉搜索树,可以在 O (logn ) 内完成插入、查找和删除操作。在任意数据结构的生命周期内执行不同操作的概率往往极不均衡,而且各操作之间有极强的相关性,在整体上多呈现极强的规律性,其中最为典型的就是数据局部性(data locality)。数据局部性包括时间局部性和空间局部性。伸展树正是基于数据的时间局部性和空间局部性原理产生的。

二 时间局部性和空间局部性的原理

时间局部性和空间局部性的原理如下。

• 刚刚被访问的元素,极有可能在不久后再次被访问。

• 刚刚被访问的元素,它的相邻节点也很有可能被访问。

树的搜索时间复杂度与树的高度相关。二叉搜索树的高度在最坏情况下为 n ,每次搜索的时间复杂度都退化为线性 O (n )。平衡二叉树(AVL树)通过动态调整平衡,使树的高度保持在O (logn ),因此单次搜索的时间复杂度为O (logn )。但是AVL树为了严格保持平衡,在调整时会做过多旋转,影响了插入和删除的性能。

伸展树的实现更为简捷,它无须时刻保持全树平衡,任意节点的左右子树高差无限制。伸展树的单次搜索也可能需要 n 次操作,但可以在任意足够长的真实操作序列中保持均摊意义上的高效率 O (logn)。伸展树可以保证 m 次连续搜索操作的复杂度为 O (m logn),而不是O (mn)。伸展树的优势在于不需要记录平衡因子、树高、子树大小等额外信息,所以适用范围更广,对 m 次连续搜索操作具有较高的效率。

考虑到局部性原理,伸展树会在每次操作后都将刚被访问的节点旋转至树根,加速后续的操作。当然,旋转前后的搜索树必须相互等价。这样,查询频率高的节点应当经常处于靠近树根的位置。旋转的巧妙之处:在不打乱数列中数据大小关系(中序遍历有序性)的情况下,所有基本操作的均摊复杂度仍为O (logn)。

三 右旋和左旋

伸展操作 Splay(x , goal) 是在保持伸展树有序性的前提下,通过一系列旋转将伸展树中的元素 x 调整到 goal 的子节点,若 goal=0,则将元素 x 旋转到树的根部。伸展操作包括右旋和左旋两种基本操作。

1 右旋

节点 x 右旋时,携带自己的左子节点向右旋转到 y 位置,y 旋转到 x 的右子树位置,x 的右子树被抛弃,此时 y 右旋后左子树正好空闲,将 x 的右子树放到 y 的左子树位置,旋转后将 x 挂接到 y 的父节点,若原来 y 是其父节点的右子节点,则旋转后 x 也是其父节点的右子节点,否则是其父节点的左子节点。旋转时修改

了3对父子关系,即 y 和 xr 、y 的父节点 tr[y ].fa 和 x 、x 和 y ,如下图中的粗线所示。

2 左旋

节点 x 左旋时会携带自己的右子节点,向左旋转到 y 的位置,y 旋转到 x 的左子树位置,x 的左子树被抛弃,此时 y 左旋后其右子树正好空闲,将 x 的左子树放到 y 的右子树位置,旋转后将 x 挂接到 y 的父节点 tr[y ].fa ,若原来 y 是其父节点的右子节点,则旋转后 x 也是其父节点的右子节点,否则是其父节点的左

子节点。

四 伸展

伸展操作并不复杂,根据情况右旋或左旋就可以了。伸展操作分为逐层伸展和双层伸展。

1 逐层伸展

将 x 旋转到目标 goal之下,若 x 的父节点不是目标,则判断:若 x 是其父节点的左子节点,则执行 x 右旋;否则执行 x 左旋,直到 x 的父节点等于目标为止。若目标为 0,则 x 为树根。

例如,在下面的伸展树中将 1 旋转到树根,逐层伸展的旋转过程如下图所示。

算法分析: 采用逐层伸展的方法,每次访问的时间复杂度在最坏情况下都为O (n),如何避免最坏情况的发生呢?一个简单有效的方法是双层伸展,即每次都向上追溯两层,判断旋转类型并进行相应的旋转。

2 双层伸展

双层伸展每次都向上追溯两层,旋转类型分为 3 种情况。

情况1:Zig/Zag

若节点 x 的父节点 y 是根节点,则只需进行一次右旋或左旋操作即可。若 x 是其父节点 y 的左子节点,则执行 x 右旋,否则执行 x 左旋。

情况2:Zig-Zig / Zag-Zag

若节点 x 的父节点 y 不是根节点,y 的父节点为 z ,且 x、y 同时是各自父节点的左子节点或右子节点,则需要进行两次右旋或两次左旋操作。

情况3:Zig-Zag / Zag-Zig

若节点 x 的父节点 y 不是根节点,y 的父节点是 z ,且在 x、y 中一个是其父节点的左子节点,一个是其父节点的右子节点,则需要进行两次旋转:右旋-左旋或两次左旋-右旋操作。

3 分析

情况 1 和情况 3 都进行了 x 的右旋或左旋,和逐层伸展的方法完全一致,情况 2 则有所不同:逐层伸展时进行了两次 x 旋转,双层伸展时先进行 y 旋转再进行 x 旋转。

例如,在下面的伸展树中将 1 旋转到树根,双层伸展的旋转过程如下图所示。

旋转之后,双层伸展比逐层伸展得到的树高度更小,基本操作的时间复杂度和树高成正比,因此双层伸展比逐层伸展效率更高。

算法分析: 双层伸展可以使树的高度接近于减半的速度压缩。Tarjan 等人已经证明,双层伸展单次操作的均摊时间为 O(logn),比逐层伸展的效率高了很多。逐层伸展简单、易懂,在数据量不大的情况下可以通过,若数据量大或特殊数据卡点,则会超时。

五 查找

与二叉搜索树的查找一样,在伸展树中查找 val,若查找成功,则将 val 旋转到根。

六 插入

与二叉搜索树的插入一样,将 val 插入伸展树的相应位置,再执行 Splay(x , 0)。初始时,x=root,若 tr[x ].val<val,则到 x 的右子树中查找,否则到 x 的左子树中查找;若 x 的子树不存在,则停止,生成新节点挂到 x 的子树上,然后将新插入的节点旋转到树根。

七 分裂

以 val 为界,将伸展树分裂为两棵伸展树 t1 和 t2 ,t1 中的所有元素都小于 val , t2 中的所有元素都大于 val 。 首先执行 Find(val),将元素 val 调整为伸展树的根节点,则 val 的左子树就是 t1 ,右子树为 t2 。删除树根,分裂为 t1 和 t2 两棵伸展树。

八 合并

将两个伸展树 t1 和 t2 合并为一个伸展树,t1 的所有元素都小于 t2 的所有元素。首先,找到伸展树 t1 中的最大元素 x ,查找最大值时会通过伸展操作将 x 调整到伸展树的根;然后,将 t2 作为树根 x 的右子树。这样就得到了新的伸展树 root。

九 删除

将元素 val 从伸展树中删除。首先在伸展树中查找 val,然后以 val 为界,将伸展树分裂为两棵伸展树 t1 和 t2 ,再将两个伸展树合并。

十 区间操作

若伸展树中节点的值为数列中每个元素的位置,则可以利用伸展树实现线段树的所有功能,还可以实现线段树无法实现的功能,例如删除区间和插入区间。

1 删除区间

删除 [l , r ] 区间的所有元素。首先找到 l-1,将其旋转到树根;然后找到 r+1,将其旋转到树根的右子节点,此时 r +1 的左子树为 [l, r ]区间,将 r+1 的左子树置空。

2 插入区间

在 pos 后插入一些元素 {a1 , a2 , …, ak }。首先将这些元素建成一棵伸展树 t1,然后找到 pos,将其旋转到树根;最后找到 pos+1,将其旋转到树根的右子节点,将 t1 挂接到 pos+1 的左子树上。

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

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

相关文章

zabbix集群搭建分布式监控的操作步骤

作用&#xff1a; 分担server的集中式压力解决多机房之间的网络延迟问题环境准备&#xff1a; 服务器1&#xff1a;zabbix-server 服务器2&#xff1a;zabbix-proxy 服务器3&#xff1a;zabbix-agent 关系&#xff1a;zabbix-agent发送数据到代理&#xff0c;代理汇总数据发送…

学习Python要学习哪些课程?

通过学习 Python数据分析与应用课程&#xff0c;可以掌握Python进行科学计算、可视化绘图、数据处理&#xff0c;分析与建模、构建聚类、回归、分类模型的主要方法和技能&#xff0c;并为后续相关课程学习及将来从事数据分析挖掘研究、数据分析工作奠定基础。 Python数据分析与…

XSStrike工具使用说明

今天继续给大家介绍渗透测试相关知识&#xff0c;本文主要内容是XSStrike工具使用说明。 免责声明&#xff1a; 本文所介绍的内容仅做学习交流使用&#xff0c;严禁利用文中技术进行非法行为&#xff0c;否则造成一切严重后果自负&#xff01; 再次强调&#xff1a;严禁对未授权…

记录:微星 GE63 屏轴断裂 之后。。。

2022/11/25 记录 微星 GE63 1070 笔记本&#xff0c;使用的第三年&#xff0c;已过保了一年&#xff0c;上周使用时&#xff0c;准备合上笔记本盖。啪一下&#xff0c;左侧屏轴断裂&#xff0c;B面翘起&#xff0c;A面左下角轴盖断了一截。 网上好多人都有类似的情况&#xff…

Linux多核运行机制(SMP)

一、Linux内核兼容多处理器要求 有多个 CPU 处理器 的 系统中 , Linux 内核需要处理的问题 : 1、公平共享 : CPU 的负载 , 需要公平地共享 , 不能出现某个CPU空闲 , 造成资源浪费。 2、可设置进程 与 CPU 亲和性 : 可以为 某些类型的 进程 与 指定的 处理器设置亲和性 , 可以针…

数据结构与算法之让我们种下一棵字典树(Java/C++双语言实现)

⭐️前面的话⭐️ 本篇文章将介绍一种经常使用的数据结构——字典树&#xff0c;它又称Tire树&#xff0c;前缀树&#xff0c;字典树&#xff0c;顾名思义&#xff0c;是关于“字典”的一棵树。这个词典中的每个“单词”就是从根节点出发一直到某一个目标节点的路径&#xff0…

CSRF漏洞简介

今天继续给大家介绍渗透测试相关知识&#xff0c;本文主要内容是CSRF漏洞原理、产生与危害。 免责声明&#xff1a; 本文所介绍的内容仅做学习交流使用&#xff0c;严禁利用文中技术进行非法行为&#xff0c;否则造成一切严重后果自负&#xff01; 再次强调&#xff1a;严禁对未…

C语言 * 数组的解析 *

目录 一&#xff1a;一维数组的创建和初始化 1.1 数组的创建 1.2 数组的初始化 1.3 一维数组的使用 1.4 一维数组在内存中的存储 二&#xff1a;二维数组的创建和初始化 2.1 数组的创建 2.2 数组的初始化 2.3 一维数组的使用 2.4 一维数组在内存中的存储 2.5 数组越…

【蓝桥杯选拔赛真题30】python计算倒数和 青少年组蓝桥杯python 选拔赛STEMA比赛真题解析

目录 python计算倒数和 一、题目要求 1、编程实现 2、输入输出 3、评分标准

从01背包说起(上)

目录 引入 1.什么是动态规划? 2.什么是背包问题&#xff1f; 3.什么是01背包&#xff1f; 模板题 1.题面 2.思路 Ⅰ为何不可用贪心 Ⅱ状态转移方程 3.代码 下期预告 引入 1.什么是动态规划? 动态规划&#xff08;英语&#xff1a;Dynamic programming&#xff0…

收到多个20k+的offer!选哪一个呢?

“收到offer了&#xff01;”最近&#xff0c;黑马老师收到最多的消息就属这句了。随着黑马各个学科迎来毕业&#xff0c;班主任收到的喜讯越来越多。班主任说&#xff0c;没有比在接近年底时收到学生就业喜讯更让人开心的事了。今天&#xff0c;播妞给大家带来的是黑马HTML&am…

就两秒?这说出去谁信啊!

文 | xiaoyi&#xff08;转载请后台联系&#xff09;关注公众号&#xff1a;小一的学习笔记截止发文&#xff0c;北上广深一共有6510条公交线路为了获取上面的这些线路信息&#xff0c;我写了一个爬虫&#xff0c;大概用了2秒左右就搞定&#xff0c;真爽&#xff01;说出来你们…

【项目实战:核酸检测平台】第三章 利其器

第三章 利其器 摘要:俗话说的好工欲善其事&#xff0c;必先利其器&#xff0c;框架搭的好&#xff0c;开发起来很舒服&#xff0c;搭的不好&#xff0c;开发起来就很痛苦。 一个程序员只会写业务代码&#xff0c;最多算是个码农&#xff0c;搭框架的本事、遇到难题的解决能力…

第八章 兼容多种模块标准的软件包封装

第八章 如何封装兼容多种JS模块标准的软件包&#xff1f; 为了方便用户使用&#xff0c;一款成熟的类库都会提供多种模块封装形式&#xff0c;比如大家最常用到的 Vue&#xff0c;就提供了cjs、esm、umd 等多种封装模式&#xff0c;并且还会提供对应的压缩版本&#xff0c;方便…

微服务之间,最佳的调用方式是什么?

在微服务架构中&#xff0c;需要调用很多服务才能完成一项功能。服务之间如何互相调用就变成微服务架构中的一个关键问题。服务调用有两种方式&#xff0c;一种是RPC方式&#xff0c;另一种是事件驱动&#xff08;Event-driven&#xff09;方式&#xff0c;也就是发消息方式。消…

MySQL海量数据优化(理论+实战) 吊打面试官

一、准备表数据 咱们建一张用户表&#xff0c;表中的字段有用户ID、用户名、地址、记录创建时间&#xff0c;如图所示 ​OK&#xff0c;接下来准备写一个存储过程插入一百万条数据 CREATE TABLE t_user (id int NOT NULL,user_name varchar(32) CHARACTER SET utf8 COLLATE ut…

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java线上学习系统8e88w

做毕业设计一定要选好题目。毕设想简单&#xff0c;其实很简单。这里给几点建议&#xff1a; 1&#xff1a;首先&#xff0c;学会收集整理&#xff0c;年年专业都一样&#xff0c;岁岁毕业人不同。很多人在做毕业设计的时候&#xff0c;都犯了一个错误&#xff0c;那就是不借鉴…

路由策略和路由控制

路由策略和路由控制 路由策略 针对路由的发布&#xff0c;接收&#xff0c;引入进行控制&#xff0c;从而影响数据的路径或者可达性 路由匹配工具 ACL&#xff1a;访问前缀列表 一个ACL用多条规则组成&#xff0c;不同规则之间通过rule id进行区分&#xff0c;默认rule 步…

[附源码]java毕业设计智慧农业销售平台

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

XSS测试绕过WAF思路

今天继续给大家介绍渗透测试相关知识&#xff0c;本文主要内容是XSS测试绕过WAF思路。 免责声明&#xff1a; 本文所介绍的内容仅做学习交流使用&#xff0c;严禁利用文中技术进行非法行为&#xff0c;否则造成一切严重后果自负&#xff01; 再次强调&#xff1a;严禁对未授权设…