【C++ 高阶数据结构 Test】AVL ~ 二叉搜索树

news2024/9/21 2:40:48

文章目录

      • 1. AVL 树概念
      • 2. AVL 树节点的定义
      • 3. AVL树的插入
      • 4. AVL树的旋转
        • 4.1 新节点插入较高左子树的左侧---左左:右单旋
        • 4.2 新节点插入较高右子树的右侧---右右:左单旋
        • 4.3 新节点插入较高左子树的右侧---左右:先左单旋再右单旋
        • 4.4 新节点插入较高右子树的左侧---右左:先右单旋再左单旋
      • 5. AVL树的性能
      • 6. AVL树的面试题

1. AVL 树概念

🍎① 二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化单支树,查
找元素相当于在顺序表中搜索元素,效率低下

🍎② 因此,两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis (为什么叫 AVL 树呢 ? ----- 是从这两位科学家的姓名来的) 在1962年发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。

🍎③ 一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:

  • Ⅰ、它的左右子树都是AVL树;
    Ⅱ、左右子树高度之差(简称平衡因子)的绝对值不超过1 (即:-1、0、1);

注意:
🐧a. 平衡因子不是 AVL树必须需要的,它只是 AVL 树的一种实现方式,平衡因子不是必须要维护的,在操作时也可以直接通过高度函数来算,只不过比较麻烦;

🐧b. 平衡因子 = 右子树的高度 - 左子树的高度。

在这里插入图片描述

结论: 如果一棵二叉搜索树是高度平衡的,它就是AVL树。如果它有n个结点,其高度可保持在 O ( l o g 2 n ) O(log_2 n) O(log2n) ,搜索时间复杂度O( l o g 2 n log_2 n log2n)。(注意,当 n = 3亿 的时候,二叉树的高度还不到 30,所以极大的提高了搜索效率)


2. AVL 树节点的定义

template<class K, class V>
struct AVLTreeNode {

	AVLTreeNode<K, V>* _left;
	AVLTreeNode<K, V>* _right;
	AVLTreeNode<K, V>* _parent;		// AVL树要定义节点的父亲,因为更新需要更新祖先的平衡因子

	pair<K, V> _kv;

	int _bf;	// 该节点的平衡因子


	//构造函数,以便初始化
	AVLTreeNode(const pair<K, V>& kv)
		: _left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		, _kv(kv)
		, _bf(0);	
	{}
};

3. AVL树的插入

🍎① AVL 树就是在二叉搜索树的基础上引入了平衡因子,因此AVL树也可以看成是二叉搜索树。那么
AVL树的插入过程可以分为两步:

🐧Ⅰ. 按照二叉搜索树的方式插入新节点
🐧Ⅱ. 调整插入节点以及该节点的祖先节点的平衡因子

a. 插入父节点的左边,父节点的平衡因子 -1

b. 插入父节点的右边,父节点的平衡因子 +1

c. 父亲的平衡因子 == 0的时候,表示父亲所在子树的高度不变,不再需要往上更新,插入结束

d. 父亲平衡因子 == 1 or -1,父亲所在子树高度变了,继续往上更新;

e. 父亲平衡因子== 2 or -2,父亲所在的子树已经不平衡了,需要旋转处理

注意: ❗更新平衡因子的结束条件,要么是当前更新的父亲平衡因子等于0,要么是当前更新节点是根节点,根节点的父亲的平衡因子是不存在的(因为此时父亲节点为空),即为结束条件。

在这里插入图片描述

4. AVL树的旋转

🍎 如果在一棵原本是平衡的AVL树中插入一个新节点,可能造成不平衡,此时必须调整树的结构,使之平衡化。根据节点插入位置的不同,AVL树的旋转分为四种:



4.1 新节点插入较高左子树的左侧—左左:右单旋

🍎 ①右单旋:必须要 单纯的满足都是左子树比右子树高的情况 不能出现右子树比左子树高的情况

🍎 ②什么情况下使用右单旋呢 ?

在这里插入图片描述

在这里插入图片描述

	//右单旋
	void RotateR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;

		// 先稳定老大
		parent->_left = subLR;

		// 认新主人
		if (subLR)
			subLR->_parent = parent;

		// 将老大变成老二
		subL->_right = parent;

		// 因为 parent 可能是还有父节点的情况的
		Node* ppNode = parent->_parent;
		parent->_parent = subL;


		if (parent == _root)
		{
			_root = subL;
			subL->_parent = nullptr;
		}
		else
		{
			//判断 parent 是 ppNode的左孩子还是右孩子
			if (ppNode->_left == parent)
			{
				ppNode->_left = subL;
			}
			else
			{
				ppNode->_right = subL;
			}

			subL->_parent = ppNode;
		}

		// 将其平衡因子改变
		parent->_bf = subL->_bf = 0;
	}

4.2 新节点插入较高右子树的右侧—右右:左单旋

🍎 ① 什么情况下使用左单旋呢 ?

在这里插入图片描述


🍎 ② 注意:❗下面这种情况就不是左单旋,因为它不是单纯的右边高(它有左边高的情况

在这里插入图片描述


  • 以下是左单旋的例子:

在这里插入图片描述

	//左单旋
	void RotateL(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;

		// 先稳定老大,给他派士兵
		parent->_right = subRL;

		if (subRL != nullptr)
			subRL->_parent = parent;

		// 老大变成老二
		subR->_left = parent;
		parent->_parent = subR;

		Node* ppNode = parent->_parent;

		if (parent == _root)
		{
			_root = subR;
			subR->_parent = nullptr;
		}
		else
		{
			// 判断 parent 节点是在 ppNode的右节点还是左节点
			if (ppNode->_right == parent)
			{
				ppNode->_right = subR;
			}
			else
			{
				ppNode->_left = subR;
			}
			subR->_parent = ppNode;
		}

		parent->_bf = subR->_bf = 0;
	}

4.3 新节点插入较高左子树的右侧—左右:先左单旋再右单旋

🍎 ① 大概的思路是将该二叉树变成满足完全右单旋的情况。

🍎 ② 什么情况下使用左右双旋呢 ?

在这里插入图片描述

在这里插入图片描述

// 先进行左单旋,再右单旋
void RotateLR(Node* parent)
{
	Node* subL = parent->_left;
	Node* subLR = subL->_right;

	// 旋转之前,保存subLR的平衡因子,旋转完成之后,需要根据该平衡因子来调整其他节点的平衡因子
	int bf = subLR->_bf;

	// 先对30进行左单旋
	RotateL(parent->_left);

	//  再对90进行右单旋
	RotateR(parent);


	// // 旋转之前,60的平衡因子可能是-1/0/1,旋转完成之后,根据情况对其他节点的平衡因子进行调整
	if (bf == -1)
	{
		subLR->_bf = 0;
		subL->_bf = 0;
		parent->_bf = 1;
	}
	else if (bf == 1)
	{
		subLR->_bf = 0;
		subL->_bf = -1;
		parent->_bf = 0;
	}
	else if (bf == 0)
	{
		subLR->_bf = 0;
		subL->_bf = 0;
		parent->_bf = 0;
	}
	else
	{
		assert(false);
	}
}
4.4 新节点插入较高右子树的左侧—右左:先右单旋再左单旋

🍎 ① 什么情况下使用右左双旋呢 ?

在这里插入图片描述

在这里插入图片描述

// 右左单旋
void RotateRL(Node* parent)
{
	Node* subR = parent->_right;
	Node* subRL = subR->_left;
	int bf = subRL->_bf;

	RotateR(subR);
	RotateL(parent);

	subRL->_bf = 0;
	if (bf == 1)
	{
		subR->_bf = 0;
		parent->_bf = -1;
	}
	else if (bf == -1)
	{
		parent->_bf = 0;
		subR->_bf = 1;
	}
	else
	{
		parent->_bf = 0;
		subR->_bf = 0;
	}
}

5. AVL树的性能

🐧🐧🐧 AVL树是一棵绝对平衡的二叉搜索树,其要求每个节点的左右子树高度差的绝对值都不超过1,这样可以保证查询时高效的时间复杂度,即 l o g 2 ( N ) log_2 (N) log2(N)

🍎🍎🍎 但是如果要对AVL树做一些结构修改的操作,性能非常低下,比如:插入(插入的时候 new 出节点也很消耗时间)时要维护其绝对平衡,旋转的次数比较多,更差的是在删除时,有可能一直要让旋转持续到根的位置。

因此:如果需要一种查询高效且有序的数据结构,而且数据的个数为静态的(即不会改变,意思就是不会插入新数据),可以考虑AVL树,但一个结构经常修改,就不太适合。

6. AVL树的面试题

  • 🍎① AVL树插入或者删除的时候,其旋转情况?

🐧Ⅰ、插入时,AVL树最多只需要旋转两次。

🐧Ⅱ、删除操作时,可能不止旋转两次,可能需要旋转多次,子树旋转后,其高度降低了一层,其上层可能也需要跟着旋转。

在这里插入图片描述

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

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

相关文章

【计算机毕业设计】springboot房地产销售管理系统的设计与实现

相比于以前的传统手工管理方式&#xff0c;智能化的管理方式可以大幅降低房地产公司的运营人员成本&#xff0c;实现了房地产销售的 标准化、制度化、程序化的管理&#xff0c;有效地防止了房地产销售的随意管理&#xff0c;提高了信息的处理速度和精确度&#xff0c;能够及时、…

九游娱乐携手云达不莱梅共谋跨界新发展!

近日&#xff0c;九游娱乐正式宣布&#xff0c;成为德国著名足球俱乐部云达不莱梅俱乐部的亚洲官方合作伙伴。此次跨界合作将携手开创体育与娱乐融合的新篇章&#xff0c;不仅彰显九游娱乐在全球体育和娱乐领域的影响力&#xff0c;也为云达不莱梅俱乐部在亚洲市场带来了新的机…

js之选项卡制作实例

大家好&#xff0c;今天给大家书写选项卡实例&#xff0c;话不多说&#xff0c;直接上干货 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, in…

UVM寄存器模型——手写Ralf问题debug

寄存器模型是UVM中至关重要的一部分&#xff0c;如果没有寄存器模型&#xff0c;那么验证平台对于DUT内寄存器的访问方式将十分有限&#xff0c;对DUT运行状态的把控也会变得更为复杂。 在验证过程中&#xff0c;scoreboard或者其他验证组件经常需要了解当前时间某个寄存器的值…

c++20---std::erase----std::erase_if

问题&#xff1a;如何删除满足条件的所有元素。 erase #include <iostream> #include <algorithm> #include <vector>int main(){std::vector<int> vec{1,2,3,1,1,1,1,1};std::erase(vec,1);for(int v:vec) std::cout<<v<<" "…

详细分析Vue3中的reactive(附Demo)

目录 1. 基本知识2. 用法3. Demo 1. 基本知识 reactive 是一个函数&#xff0c;用于将一个普通的 JavaScript 对象转换为响应式对象 当对象的属性发生变化时&#xff0c;Vue 会自动追踪这些变化&#xff0c;并触发相应的更新 Vue2没有&#xff0c;而Vue3中有&#xff0c;为啥…

[AI智能摄像头]RV1126部署yolov5并加速

导出onnx模型 yolov5官方地址 git clone https://github.com/ultralytics/yolov5 利用官方命令导出python export.py --weights yolov5n.pt --include onnx 利用代码导出 import os import sys os.chdir(sys.path[0]) import onnx import torch sys.path.append(..) from m…

如何使用JMeter测试导入接口/导出接口?

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号&#xff1a;互联网杂货铺&#xff0c;回复1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 今天上班&#xff0c;被开发问了一个问题&#xff1a;JM…

怎样恢复E盘里删了的文件夹,2024让EasyRecovery来帮你轻松恢复

使用EasyRecovery易恢复进行数据恢复非常简单。首先&#xff0c;用户需要选择需要恢复的数据类型&#xff0c;如文档、图片、视频等。然后&#xff0c;软件会对选定的存储设备进行全面扫描&#xff0c;以寻找可恢复的数据。在扫描过程中&#xff0c;用户可以预览部分已找到的文…

一周学习总结:数组与链表

学习内容&#xff1a;数组与链表、计算机网络知识 数组&#xff1a; 从数组的基础知识到相关应用 数组的基础知识&#xff1a;数组在内存中的存储、数组的相关操作&#xff08;获取与更新&#xff09;、数组的相关应用&#xff1a; 二分查找法⭐⭐⭐⭐⭐ ● 掌握左闭右闭的…

matlab使用教程(71)—控制坐标区布局

1.与位置相关的属性和函数 有几个属性和函数可用于获取和设置坐标区的大小与位置。下表摘要显示了这些属性和函数。 函数或属性描述 OuterPosition 属性 使用此属性可以查询或更改坐标区的外边界&#xff0c;包括标题、标签和边距。要更改外边界&#xff0c;请将此属性指定为…

暴利的副业兼职,抖音蓝海赛道,批量复制这个项目,1年200个

在有小孩的家庭中&#xff0c;父母都非常重视孩子的教育&#xff0c;并愿意为此投入大量资金。根据之前的新闻报道&#xff0c;有些父母会毫不犹豫地为孩子花费数千甚至上万元报名参加各种培训课程。尤其是在独生子女家庭中&#xff0c;家长更注重培养孩子的各方面能力。 周周近…

基于springboot实现社区智慧养老监护管理平台系统项目【项目源码+论文说明】计算机毕业设计

基于SpringBoot实现社区智慧养老监护管理平台系统演示 摘要 如今社会上各行各业&#xff0c;都在用属于自己专用的软件来进行工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。互联网的发展&#xff0c;离不开一些新的技术&#xff0c;而新技术的…

Linux交叉编译

目录 一. 下载交叉编译工具 1.使用环境要求 2.获取Linux SDK 方法一&#xff1a;从github上下载orangepi-build 方法二&#xff1a;从百度网盘下载提前编译好的Linux SDK包 通过以下命令进行合并解压 3.修改配置脚本 4.首次编译完整的SDK 1.运行build.sh脚本 2.选择F…

Colab/PyTorch - 004 Torchvision Semantic Segmentation

Colab/PyTorch - 004 Torchvision Semantic Segmentation 1. 源由2. 语义分割 - 应用2.1 自动驾驶2.2 面部分割2.3 室内物体分割2.4 地理遥感 3. 语义分割 - torchvision3.1 FCN 使用 ResNet-101 语义分割3.1.1 加载模型3.1.2 加载图像3.1.3 预处理图像3.1.4 网络的前向传播3.1…

红酒与美食的完善搭配艺术

在美食的世界里&#xff0c;红酒总是扮演着不可或缺的角色。它与美食的搭配&#xff0c;是一门深奥的艺术。云仓酒庄雷盛红酒&#xff0c;作为一款备受欢迎的红酒品牌&#xff0c;以其卓着的品质和丰富的口感&#xff0c;成为了红酒与美食搭配的典范。 雷盛红酒&#xff0c;源…

中国农业大学:学硕11408复试线上涨40分,今年还会持续涨吗?中国农业大学计算机考研考情分析!

中国农业大学&#xff08;China Agricultural University&#xff09;&#xff0c;简称“中国农大”&#xff0c;坐落于中国首都北京&#xff0c;由中华人民共和国教育部直属&#xff0c;中央直管副部级建制&#xff0c;水利部、农业部和北京市共建&#xff0c;位列国家“双一流…

CNN卷积神经网络初学

1.为什么要学CNN 在传统神经网络中&#xff0c;我们要识别下图红色框中的图像时&#xff0c;我们很可能识别不出来&#xff0c;因为这六张图的位置都不通&#xff0c;计算机无法分辨出他们其实是一种形状或物体。 这是传统的神经网络图&#xff0c;通过权重调整神经元和神经元…

云曦实验室期中考核题

Web_SINGIN 解题&#xff1a; 点击打开环境&#xff0c;得 查看源代码&#xff0c;得 点开下面的超链接&#xff0c;得 看到一串base64编码&#xff0c;解码得flag 简简单单的文件上传 解题&#xff1a; 点击打开环境&#xff0c;得 可以看出这是一道文件上传的题目&#x…

智慧变电站守护者:TSINGSEE青犀AI视频智能管理系统引领行业革新

一、方案概述 随着科技的不断进步&#xff0c;人工智能&#xff08;AI&#xff09;技术已经深入到各个领域。在变电站安全监控领域&#xff0c;引入AI视频监控智能分析系统&#xff0c;可以实现对站内环境、设备状态的实时监控与智能分析&#xff0c;从而提高变电站的安全运行…