12.1平衡树(splay),旋转操作及代码

平衡树

变量定义

tot表示结点数量,rt表示根的编号

v[i]表示结点i的权值

fa[i]表示结点i的父亲节点

chi[i][2]表示结点i的左右孩子

cnt[i]表示结点i的权值存在数量,如1123,v[3]=1,则cnt[3]=2;就是说i=3的三号结点的权值为1,那么三号结点的权值存在数量为2,即有两个1存在于数列当中,也就是说自变量是结点编号,因变量是结点的权值以及对应权值出现的次数

sz[i]表示结点i的子树中权值数量。sz[i]=sz[chi[i][0]]+sz[chi[i][1]]+cnt[i]

就是说i号结点存在的value的值的数量,chi[i][0]与chi[i][1]返回的是i号结点对应的两个孩子的编号,加起来就是左边的数量和右边的数量与根节点的数量和

操作

查询x的前驱:如果x有左子树,那么前驱是左子树里最靠右的结点;如果x没有左子树但有父亲结点,那么前驱是它左子树内最靠右的结点。

查询x的排名:如果x小于当前权值,则向左子树。答案加上左子树大小,如果x等于当前权值,将答案+1并返回;否则加上当前节点的cnt并向右子树

查询排名为k的数值:如果k小于左子树的大小,则向左子树

将k减去左子树大小,如果k<=0,则返回当前权值,否则向右子树

旋转

旋转操作的输入是原根节点,输出是新根结点

旋转的操作是对根节点而言的,就是说左旋是右孩子向左旋转上来;右旋是左孩子旋转上来

左旋就是右孩子成为根节点,然后原根节点成为新根结点的左孩子,新根结点的左孩子成为原根节点的最右侧孩子;右旋是左孩子成为新根节点,然后原根节点成为新根结点的右孩子,新根结点的右孩子成为

就右旋而言,要变的就两步,一步是让左孩子成为新根(也意味着左孩子失去原来的右孩子,原根节点失去原来的左孩子),另一步是让左孩子(新根)失去的右孩子接到原根(新根的右子树)的左侧

注意,由于原根失去左孩子(失去的左孩子成为了新根),所以原根在成为新根的右孩子节点时,是一定没有左孩子的,所以不用担心接不上以及接的位置,原根的左孩子的右孩子是一定可以接到原根的左孩子上的

原根A,原根左孩子B,原根左孩子的右孩子C,

用一个指针,定义为A的左孩子(即B),即表示右旋后的新的新根结点B。然后让A的左孩子为新根结点B的右孩子C(此时B还没发生改变),之后A就发生了变化,即左孩子不再是B而是C,然后再用新根指针,使B的右孩子为A

就是说在这一过程中,用了两个指针,一个指针为原根结点(输入),一个指针为新根结点(输出)

class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None

def left_rotation(node):
    new_root = node.right
    node.right = new_root.left
    new_root.left = node
    return new_root

def right_rotation(node):
    new_root = node.left
    node.left = new_root.right
    new_root.right = node
    return new_root

左旋:

旋转操作是平衡二叉树中常用的操作,用于调整树的结构以保持平衡性。平衡二叉树的旋转操作包括左旋、右旋、左右旋和右左旋。

1. 左旋(Left Rotation):对于一个节点,将其右子节点变为新的根节点,原根节点成为新根节点的左子节点,原右子节点的左子节点成为原根节点的右子节点。这个操作用于解决在插入或删除某个节点导致右子树过高的情况。

2. 右旋(Right Rotation):对于一个节点,将其左子节点变为新的根节点原根节点成为新根节点的右子节点,原左子节点的右子节点成为原根节点的左子节点。这个操作用于解决在插入或删除某个节点导致左子树过高的情况。

3. 左右旋(Left-Right Rotation):先对节点的左子节点进行左旋,然后再对节点自身进行右旋。这个操作用于解决在插入或删除某个节点导致左子树过高,且其左子节点的右子树过高的情况。

4. 右左旋(Right-Left Rotation):先对节点的右子节点进行右旋,然后再对节点自身进行左旋。这个操作用于解决在插入或删除某个节点导致右子树过高,且其右子节点的左子树过高的情况。

通过这些旋转操作,可以调整树的结构并保持树的平衡性。旋转操作的实质是通过节点之间的连接关系进行调整,从而改变树的形态。在实际应用中,旋转操作通常会涉及到节点的左右子树的高度计算、节点指针的重连等步骤。

需要注意的是,旋转操作只能保持局部的平衡性,有时可能需要多次旋转来达到整体的平衡。另外,旋转操作可能会改变树中节点的相对顺序,因此在进行旋转操作时需要注意维护节点的排序和二叉搜索树的性质。

struct Node
{
    int ch[2];
    int val;
    int ff;
}t[MAX];

ch是左右孩子。ff是记录这个结点的父节点 

inline void rotate(int x)
{
    int y=t[x].ff;
    int z=t[y].ff;
    int k=(x==t[y].ch[1]);
    t[z].ch[y==t[z].ch[1]]=x;
    t[x].ff=z;
    t[y].ch[k]=t[x].ch[k^1];
    t[t[x].ch[k^1]].ff=y;
    t[x].ch[k^1]=y;
    t[y].ff=x;
}

 输入是x,表示要旋转的结点的编号。通过y记录x的父节点,就是说y是x的父节点;z是y的父节点,是x的爷爷结点

k是表示结点x是其父结点的什么孩子。t[y].ch[1]返回的是y号结点的右孩子编号。如果是右孩子,则判断出来是1.不然则判断出来是0,就是说是左孩子就返回0,是右孩子就返回1

对于旋转的操作,就是利用了两个指针,借助了爷爷结点,即把x接到了爷爷结点上,然后就是确定接到爷爷结点的哪个孩子结点上。

具体步骤是先让爷爷节点的孩子结点设置为x,这时会断掉z与y的联系,z与x联系上;

然后让x的父节点设置为z,这时会断掉x与y的联系,x与z联系上。此时,y的孩子结点上记录的依然是x

然后让y的孩子结点变为x的孩子结点,让x的孩子结点的父节点变为y结点

最后让x的孩子结点设置为y,把y的父节点设置为x

设x为y的k孩子(k为0时为左孩子,k为1时为右孩子),则需要进行相反的旋转操作,即k^1(与1异或;如果k为0,x为左孩子,则进行右旋操作,x变为根节点;如果k为1,则进行左旋操作)

1把x设置为新根结点

    t[z].ch[y==t[z].ch[1]]=x;
    t[x].ff=z;

z的作用就是接口,省去了最后返回新根结点的过程,就是让z的相应孩子结点位置变为x,即所谓新根结点。 

2.把原根结点的k孩子设为新根结点的k^1孩子

 t[y].ch[k]=t[x].ch[k^1];
    t[t[x].ch[k^1]].ff=y;

3.让新根结点的孩子设为原根节点

  t[x].ch[k^1]=y;
    t[y].ff=x;
2与3不能反转,因为如果先3的话,新根结点的原孩子就会丢失,就会导致在2的时候接不上原来的孩子,导致丢失。而如果先2的话,会使原根结点的孩子结点丢失,但是其相应位置上孩子就是x,x已经成为新根结点,所以无所谓.具体就是t[x].ch[k^1]


 

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

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

相关文章

深入理解贝叶斯分类与朴素贝叶斯模型(Naive Bayes, NB):从基础到实战

目录 贝叶斯分类 公式 决策规则 优点 贝叶斯分类器的例子——垃圾邮件问题 1. 特征&#xff08;输入&#xff09;&#xff1a; 2. 类别&#xff1a; 3. 数据&#xff1a; 4. 模型训练&#xff1a; 注&#xff1a;类别先验概率 5. 模型预测&#xff1a; 朴素贝叶斯模…

为自己创建的游戏编程源码申请软件著作权详细流程(免费分享模板)

以为我这篇文章制作的游戏申请软件著作权为例 Ren‘py 视觉小说 交互式故事游戏制作过程学习笔记(Windows下实现)(多结局游戏)-CSDN博客 一、网站注册 申请软著时&#xff0c;所有的著作权人都需要在中国版权保护中心官网注册账号&#xff0c;并进行实名认证后&#xff0c;才…

【LeetCode】链式二叉树OJ题---C语言版

链式二叉树OJ题 一、单值二叉树&#xff08;1&#xff09;题目描述&#xff1a;&#xff08;2&#xff09;思路表述&#xff1a;&#xff08;3&#xff09;代码实现&#xff1a; 二、二叉树最大深度&#xff08;1&#xff09;题目描述&#xff1a;&#xff08;2&#xff09;思路…

java学习part26线程安全

136-多线程-同步代码块解决两种线程创建方式的线程安全问题_哔哩哔哩_bilibili 1.安全问题 关键在于某些数据操作 2.解决 2.1同步代码块 相当于给数据操作加了互斥锁 2.1.1在实现runnable接口的方式下 锁对象要求必须是唯一的&#xff0c;因为可以看成是谁占了这个对象&…

SpringBoot 是如何启动一个内置的Tomcat

为什么说Spring Boot框架内置Tomcat 容器,Spring Boot框架又是怎么样去启动Tomcat的?我简单总结下学习过程。 一:简单了解SpringBoot的启动类 我们都知道Spring Boot框架的启动类上是需要使用 @SpringBootApplication 注解标注的, @SpringBootApplication 是一个复合注解…

Jupyter Markdown 插入图片

首先截图 注意 这一步是关键的&#xff01;&#xff01; 它需要使用电脑自带的截图&#xff0c;用qq啊vx啊美图秀秀那些都不行哦。 截图之后复制&#xff1a; 然后快捷键粘贴到jupyter里面&#xff0c;它会生成一段代码&#xff08;没有代码就是说截图形式不对&#xff09;&a…

深入计算机系统看性能优化

一&#xff0e;引言 “性能优化”&#xff0c;从计算机诞生之初就一直伴随着计算机技术的发展&#xff0c;直到现在。将来也必定不会消失。这是因为每个人都会追求性价比&#xff0c;花最少的钱&#xff0c;办最多的事。生活中也一样&#xff0c;就比如说泡茶&#xff0c;但凡…

2023年12月03日新闻简报(国内国际)

新闻简报 每天三分钟&#xff0c;朝闻天下事。今天是&#xff1a;2023年12月03日&#xff0c;星期日&#xff0c;农历十月廿一&#xff0c;祝工作愉快&#xff0c;身体健康&#xff0c;生活喜乐&#xff1a; &#x1f449;&#x1f449;国内新闻 1、1日凌晨&#xff0c;四川…

docker-速通

1.命令-镜像操作 docker pull nginx #下载最新版 docker pull nginx:1.20.1 #下载指定版本 镜像名:版本名&#xff08;标签&#xff09; docker images #查看所有镜像 # 如果只写镜像名实际就是redis redis:latest 记住这个不是命令 docker rmi 镜像名:版本号/镜像id…

Pandas教程06:DataFrame.merge数据的合并处理

DataFrame.merge() 是 pandas 库中用于合并两个DataFrame数据的方法。该方法主要用于根据一个或多个键&#xff08;键可以是列名或索引&#xff09;将两个 DataFrame 连接在一起&#xff0c;这个过程类似于 SQL 中的 JOIN 操作。 #我的Python教程 #微信公众号&#xff1a;wdPy…

【PTA-C语言】实验四-循环结构II

如果代码存在问题&#xff0c;麻烦大家指正 ~ ~有帮助麻烦点个赞 ~ ~ 实验四-循环结构II 7-1 跟奥巴马一起画方块&#xff08;分数 15&#xff09;7-2 打印九九口诀表&#xff08;分数 10&#xff09;7-3 求符合给定条件的整数集&#xff08;分数 15&#xff09;7-4 求特殊方程…

网络虚拟化场景下网络包的发送过程

网络虚拟化有和存储虚拟化类似的地方&#xff0c;例如&#xff0c;它们都是基于 virtio 的&#xff0c;因而在看网络虚拟化的过程中&#xff0c;会看到和存储虚拟化很像的数据结构和原理。但是&#xff0c;网络虚拟化也有自己的特殊性。例如&#xff0c;存储虚拟化是将宿主机上…

爬虫学习-基础(HTTP原理)

目录 一、URL和URI 二、HTTP和HTTPS &#xff08;1&#xff09;HTTP &#xff08;2&#xff09;HTTPS &#xff08;3&#xff09;HTTP与HTTPS区别 &#xff08;4&#xff09;HTTPS对HTTP的改进&#xff1a;双问的身份认证 三、TCP协议 &#xff08;1&#xff09;TCP三次握手…

2000-2021年上市公司过度负债数据

2000-2021年上市公司过度负债数据 1、时间&#xff1a;2000-2021年 2、指标&#xff1a; 证券代码、证券简称、会计期间、上市日期、行业代码、行业名称、是否剔除ST或*ST股、是否剔除当年新上市、已经退市或被暂停退市的公司、产权性质、盈利能力、杠杆率行业中位数、成长性…

ELK高级搜索,深度详解ElasticStack技术栈-下篇

前言&#xff1a;ELK高级搜索&#xff0c;深度详解ElasticStack技术栈-上篇 14. search搜索入门 14.1. 搜索语法入门 14.1.1 query string search 无条件搜索所有 GET /book/_search结果&#xff1a; {"took" : 969,"timed_out" : false,"_shar…

架构图是什么,怎么做?

架构图是一种用来描述系统或软件的结构和组成的图形表示。它展示了系统中各个组件之间的关系、交互和功能。通过绘制架构图&#xff0c;可以更好地理解和沟通系统的设计和实现。 绘制架构图的软件 目前市场上有许多用于绘制架构图的软件工具&#xff0c;下面简单…

Conmi的正确答案——“xxx.sh: 行 2: $‘\r‘: 未找到命令”

Ubuntu版本&#xff1a;23.10&#xff08;桌面版&#xff09; 问题原因&#xff1a; 这个sh文件被window编辑后会以DOS格式保存&#xff0c;但linux格式中回车只认“\n”&#xff0c;而DOS格式的回车则是“\r\n”。 解决方案&#xff1a; 使用nano打开一次文件&#xff0c;并且…

有两个篮子,分别为A 和 B,篮子A里装有鸡蛋,篮子B里装有苹 果,请用面向对象的思想实现两个篮子里的物品交换

问题&#xff1a; 有两个篮子&#xff0c;分别为A 和 B&#xff0c;篮子A里装有鸡蛋&#xff0c;篮子B里装有苹 果&#xff0c;请用面向对象的思想实现两个篮子里的物品交换 代码 package cn.ljh.algorithmic;/*** author JH*/ public class Demo07 {public static void main…

git rebase冲突说明(base\remote\local概念说明)

主线日志及修改 $ git log master -p commit 31213fad6150b9899c7e6b27b245aaa69d2fdcff (master) Author: Date: Tue Nov 28 10:19:53 2023 08004diff --git a/123.txt b/123.txt index 294d779..a712711 100644 --- a/123.txtb/123.txt-1,3 1,4 123 4^Mcommit a77b518156…

使用SpringBoot和ZXing实现二维码生成与解析

一、ZXing简介 ZXing是一个开源的&#xff0c;用Java实现的多种格式的1D/2D条码图像处理库。它包含了用于解析多种格式的1D/2D条形码的工具类&#xff0c;目标是能够对QR编码&#xff0c;Data Matrix, UPC的1D条形码进行解码。在二维码编制上&#xff0c;ZXing巧妙地利用构成计…