C++进阶之AVL树

news2024/11/28 4:43:45

个人主页:点我进入主页

专栏分类:C语言初阶  C语言进阶  数据结构初阶    Linux    C++初阶     C++进阶​    ​​​​算法

欢迎大家点赞,评论,收藏。

一起努力,一起奔赴大厂

目录

一.前言

二.插入

三.旋转 

3.1右旋

3.2左旋

3.3左右双旋

3.4右左双旋

四.测试


一.前言

        在看这篇博客之前需要了解二叉搜索树的相关内容,可以看这篇博客二叉搜索树,AVL树可以看成为了解决二叉搜索树的问题,它保证了左右子树高度差不超过1。本次的内容的重点就是对AVL树的旋转。

二.插入

        AVL树的插入规则和二叉搜索树的插入规则类似,左子树都小于父节点,右子树都大于父节点,在这里我们引入了一个平衡因子,我们先插入后然后进行调节平衡因子,平衡因子的计算=右子树的高度-左子树的高度,插入的新节点的平衡因子为0,当插入的节点在父节点的右边,父节点的平衡因子+1,当插入的节点在父节点的左边,父节点的平衡因子-1,当整后父节点的平衡因子为0时直接结束,不需要继续调整,当调整后父节点的平衡因子为+1或者-1时需要继续向上进行调整,当调整后父节点的平衡因子为+2或-2时需要进行旋转。我们看下面的代码实现:

bool insert(const pair<K, V>& kv)
{
	Node* newnode = new Node(kv);
	if (_root == nullptr) _root = newnode;
	else
	{
		Node* cur = _root, * parent = nullptr;
		while (cur)
		{
			if (kv.first < cur->_kv.first)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (kv.first > cur->_kv.first) 
			{
				parent = cur;
				cur = cur->_right;
			}
			else  return false;
		}
		if (kv.first < parent->_kv.first) parent->_left = newnode;
		else parent->_right = newnode;
		newnode->_parent = parent;

		//调整平衡因子

			while (parent)
		{
			if (newnode == parent->_left) parent->_bf--;
			else parent->_bf++;

			if (parent->_bf == 0) break;
			else if (parent->_bf == 1 || parent->_bf == -1)
			{
				newnode = parent;
				parent = parent->_parent;
			}
			else if (parent->_bf == 2 || parent->_bf == -2)
			{
				if (parent->_bf == 2 && newnode->_bf == 1)
				{
					RatoteL(parent);
				}
				else if (parent->_bf == -2 && newnode->_bf == -1)
				{
					RatoteR(parent);
				}
				else if (parent->_bf == 2 && newnode->_bf == -1)
				{
					RatoteRL(parent);
				}
				else if (parent->_bf == -2 && newnode->_bf == 1)
				{
					RatoteLR(parent);
				}
				else
				{
					assert(false);
				}
				break;
			}
			else
			{
				assert(false);
			}

		}

	}
	return true;
}

三.旋转 

        旋转有4种方式:向右旋转,向左旋转,左右双旋,右左双旋这四种

3.1右旋

        看下面的抽象图

 当n=0时全图为

当n=1时全图为

当n=2时我们有3种,但是在a的位置能放第3种,因为别的会自动进行旋转,b和c这三种都可以

  当n=3时就会更多,所以这是列举不完的,针对右旋我们以下面这张图为例:

我们经过右旋后转化成下面的样子,针对的主要就是这几个节点

 

在旋转的过程中需要注意的是,parent节点是不是根节点,注意调整后subL节点的的父节点的调整,还有一点就是subLR是否为空节点,调整后需要将subL节点和parent节点的bf值改为0,我们看下面的代码:

	void RatoteR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;

		subL->_right = parent;
		parent->_left = subLR;
		Node* ppNode = parent->_parent;
		subL->_parent = parent->_parent;
		parent->_parent = subL;
		if (subLR)
			subLR->_parent = parent;
		if (parent == _root)
		{
			_root = subL;
		}
		else
		{
			if (ppNode->_left == parent)
				ppNode->_left = subL;
			else
				ppNode->_right = subL;
		}
		subL->_bf = parent->_bf = 0;
	}

3.2左旋

        左旋的代码和右旋的类似,不过需要调节的平衡因子为2和1,我们看下面的图片

我们直接上代码:

void RatoteL(Node* parent)
{
	Node* subR = parent->_right;
	Node* subRL = subR->_left;

	parent->_right = subRL;
	if (subRL)
		subRL->_parent = parent;
	Node* ppNode = parent->_parent;
	parent->_parent = subR;
	subR->_left = parent;
	subR->_parent = ppNode;
	

	if (parent == _root)
	{
		_root = subR;
	}
	else
	{
		if (ppNode->_left == parent)
			ppNode->_left = subR;
		else
			ppNode->_right = subR;
	}
	subR->_bf = parent->_bf = 0;
}
void RatoteRL(Node* parent)
{
	Node* subR = parent->_right;
	Node* subRL = subR->_left;
	int bf = subRL->_bf;

	RatoteR(subR);
	RatoteL(parent);

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

3.3左右双旋

        左右双旋的图片可以看为下面的抽象图:

当我们在b位置插入后再旋转,可以得到:

当我们插入到c位置后再经过旋转,可以得到:

 

当只旋转一次就会做一次镜像旋转,我们先让subL节点左旋,然后让parent右旋,然后进行调节平衡因子,我们看代码:

void RatoteLR(Node* parent)
{
	Node* subL = parent->_left;
	Node* subLR = subL->_right;
	int bf = subLR->_bf;

	RatoteL(subL);
	RatoteR(parent);

	if (bf == 1)
	{
		subL->_bf = -1;
	}
	else if (bf == -1)
	{
		parent->_bf = 1;
	}
}

3.4右左双旋

        这个和左右双旋类似,我们直接看代码:

	void RatoteRL(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
		int bf = subRL->_bf;

		RatoteR(subR);
		RatoteL(parent);

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

四.测试

        我们直接上代码:

public:	
    void InOrder()
	{
		_InOrder(_root);
	}

	bool IsBalance()
	{
		return _IsBalance(_root);
	}
private:
	void _InOrder(Node* root)
	{
		if (root == nullptr)
			return;
		_InOrder(root->_left);
		cout << root->_kv.first << "->" << root->_kv.second << endl;

		int left = _height(root->_left);
		int right = _height(root->_right);
		int sub = abs(left - right);
		cout << "bf-> " << sub<<endl;
		if (sub >= 2) 
			cout<<"key-> "<< root->_kv.first << endl;
		_InOrder(root->_right);
	}
	int _height(Node* root)
	{
		if (root == nullptr)
			return 0;
		int x = 1 + _height(root->_left);
		int y = 1 + _height(root->_right);

		return max(x , y);
	}
	bool _IsBalance(Node* root)
	{		
		if (root == nullptr) return true;
		int left = _height(root->_left);
		int right = _height(root->_right);

		if (abs(right - left) >= 2)
		{
			return false;
		}
		return _IsBalance(root->_left) && _IsBalance(root->_right);

	}

测试代码:

int main()
{
	srand(0);
	AVLTree<int, int> a;
	vector<int> v;
	for (int i = 0; i < 1000000; i++)
	{
		int num = rand() + i;
		v.push_back(num);
	}


	cout << a.IsBalance() << endl;
	return 0;
}

运行可以看到:

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

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

相关文章

代码随想录——分发饼干(Leetcode455)

题目链接 贪心 class Solution {public int findContentChildren(int[] g, int[] s) {Arrays.sort(g);Arrays.sort(s);int count 0;for(int i 0, j 0; i < g.length && j < s.length; i, j){if(s[j] > g[i]){count;}else{i--;}}return count;} }

通过InoDriverShop伺服调试软件连接汇川SV660F系列伺服的具体方法(以太网)

通过InoDriverShop伺服调试软件连接汇川SV660F系列伺服的具体方法(以太网) 具体连接伺服驱动器的步骤可参考以下内容: 启动InoDriverShop, 新建或打开工程 如下图所示,选择在线,选中SV660F图标,右侧通信类型选择“TCP—DCP”,点击下一步,同时要选择自己当前使用的网卡…

棉花叶子病害分类数据集3601张6类别

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;3601 分类类别数&#xff1a;6 类别名称:[“aphids”,“army_worm”,“bact…

SpringBoot + Vue 实现 AES 加密和 AES 工具类总结

目录 一、加密知识回顾 AES加密模式 二、Java 自定义 AES 工具类 三、SpringBoot 实现 AES 加密登陆 controller 层 server 层 四、Vue 实现 AES 加密登陆 五、前端AES工具类 六、实现结果 一、加密知识回顾 密钥是AES算法实现加密和解密的根本。对称加密算法之所以…

JDK17特性

JDK17特性 一、JAVA17概述 JDK 16 刚发布半年(2021/03/16),JDK 17 又如期而至(2021/09/14),这个时间点特殊,蹭苹果发布会的热度?记得当年 JDK 15 的发布也是同天。 Oracle 宣布,从 JDK 17 开始,后面的 JDK 带附加条款免费提供!!!Java 17+ 可以免费使用了,包括商…

当Windows台式电脑或笔记本电脑随机关机时,请先从这8个方面检查

序言 你的Windows笔记本电脑或PC是否意外关闭?笔记本电脑电池故障、电源线松动、过热、电源设置错误、驱动程序过时或电脑组件故障等问题都可能是罪魁祸首。如果你对这个问题感到沮丧,试试这些解决方案。 进行一些初步检查 与从电池中获取电力的笔记本电脑不同,台式电脑依…

Vue3 + TS + Antd + Pinia 从零搭建后台系统(四) ant-design-vue Layout布局,导航栏,标签页

书接上回本篇主要介绍&#xff1a; Layout布局&#xff0c;导航栏&#xff0c;标签页继续填充目录 按需引入组件Layout布局&#xff0c;导航栏&#xff0c;标签页css样式 按需引入组件 使用unplugin-vue-components插件完成ant-design-vue组件的按需加载。 前文中已处理过&…

调试器烧录失败的几种常见解决办法

目录 1. 检查接线、Keil配置是否正确 2. 降低下载速度 3. SWD引脚被禁用或被复用为其他功能 4. 使用CubeMX生成的工程&#xff0c;无法调试&#xff1f; 5. 能识别到芯片但是下载时弹出报错对话框&#xff08;Command not supported&#xff09; 6. 内部flash锁死&#x…

媒体邀约中媒体采访应该如何做?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体宣传加速季&#xff0c;100万补贴享不停&#xff0c;一手媒体资源&#xff0c;全国100城线下落地执行。详情请联系胡老师。 在媒体邀约中&#xff0c;媒体采访应该遵循以下几个步骤和…

用户态协议栈05—架构优化

优化部分 添加了in和out两个环形缓冲区&#xff0c;收到数据包后添加到in队列&#xff1b;经过消费者线程处理之后&#xff0c;将需要发送的数据包添加到out队列。添加数据包解析线程&#xff08;消费者线程&#xff09;&#xff0c;架构分层 #include <rte_eal.h> #inc…

ionic7 从安装 到 项目启动最后打包成 apk

报错处理 在打包的时候遇到过几个问题&#xff0c;这里记录下来两个 Visual Studio Code运行ionic build出错显示ionic : 无法加载文件 ionic 项目通过 android studio 打开报错 capacitor.settings.gradle 文件不存在 说明 由于之前使用的是 ionic 3&#xff0c;当时打包的…

模式分解的概念(上)-分解、无损连接性、保持函数依赖特性

一、分解的概念 1、分解的定义 2、判断一个关系模式的集合P是否为关系模式R的一个分解 只要满足以下三个条件&#xff0c;P就是R的一个分解 &#xff08;1&#xff09;P中所有关系模式属性集的并集是R的属性集 &#xff08;2&#xff09;P中所有不同的关系模式的属性集之间…

【计算机网络体系结构】计算机网络体系结构实验-DHCP实验

服务器ip地址 2. 服务器地址池 3. 客户端ip 4. ping Ipconfig

星闪指向遥控,做家电交互的破壁人

“面壁者罗辑&#xff0c;我是你的破壁人。” 科幻小说《三体》中&#xff0c;当人类的基础科学被三体人封锁&#xff0c;变得停步不前&#xff0c;人类启动了自救的面壁计划&#xff0c;通过一次又一次破壁&#xff0c;找到战胜三体人的办法。 现实中&#xff0c;有一点已经成…

教师数字素养标准

老师们有没有想过如何让自己的课堂更加生动、互动&#xff0c;甚至超越传统的教学模式&#xff1f;是否思考过&#xff0c;数字技术如何成为我们教学的得力助手&#xff0c;让我们的课堂焕发出新的活力&#xff1f; 数字素养&#xff0c;这个听起来充满科技感的词汇&#xff0c…

Github上传大于100M的文件(ubuntu教程)

安装Git-lfs Git Large File Storage (LFS) 使用 Git 内部的文本指针替换音频样本、视频、数据集和图形等大文件&#xff0c;同时将文件内容存储在 GitHub.com 或 GitHub Enterprise 等远程服务器上。官网下载&#xff1a;https://git-lfs.github.com/ ./install.sh上传 比如…

软银CEO孙正义:10年内将出现比人类聪明1万倍的人工智能|TodayAI

2024年6月20日&#xff0c;软银集团公司&#xff08;SoftBank&#xff09;董事长兼首席执行官孙正义在日本东京举行的公司年度股东大会上发表讲话&#xff0c;表示比人类聪明1万倍的人工智能将在10年内出现。这是他近年来一次罕见的公开露面&#xff0c;在会上他质疑了自己的人…

57.SAP MII产品介绍(07)功能详解(06)Workbench-SQLQuery

1.SQLQuery概念 您可以使用SAP Manufacturing Integration and Intelligence&#xff08;SAP MII&#xff09;Workbench中的SQLQuery来创建访问面向SQL的连接器&#xff08;如IDBC连接器&#xff09;的模板。此查询的扩展名为tqsq。 简而言之&#xff0c;SQLQuery就是一段…

Github 2024-06-22 开源项目日报 Top10

根据Github Trendings的统计,今日(2024-06-22统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量TypeScript项目3JavaScript项目2Python项目2HTML项目1Rust项目1Dart项目1Dockerfile项目1Shell项目1C++项目1Swift项目1RustDesk: 用Rust编写的…