深入探索C++中的AVL树

news2025/1/20 1:40:05

引言

在数据结构和算法的世界里,平衡二叉搜索树(Balanced Binary Search Tree, BST)是一种非常重要的数据结构。AVL树(Adelson-Velsky和Landis发明的树)就是平衡二叉搜索树的一种,它通过自平衡来维护其性质:任何节点的两个子树的高度差至多为1。这一特性使得AVL树在插入、删除和查找操作中都能保持相对稳定的性能。

一、AVL树的基本概念

AVL树是一种自平衡的二叉搜索树,它的每个节点都包含四个属性:键值、左子树指针、右子树指针和高度。高度是从该节点到其任一叶子节点的最长路径上边的数量。

二、AVL树的性质

  1. 二叉搜索树性质:对于任意节点N,其左子树上所有节点的键值都小于N的键值,而右子树上所有节点的键值都大于N的键值。
  2. 平衡性质:对于任意节点N,其左子树和右子树的高度差至多为1。

三、AVL树的旋转操作

当在AVL树中插入或删除节点时,可能会破坏其平衡性质。为了恢复平衡,我们需要进行旋转操作。旋转操作包括四种情况:右旋转(RR)、左旋转(LL)、左右旋转(LR)和右左旋转(RL)。

  1. 右旋转(RR):当某个节点的右子树的高度比左子树高2时,需要进行右旋转。
  2. 左旋转(LL):当某个节点的左子树的高度比右子树高2时,需要进行左旋转。
  3. 左右旋转(LR):当某个节点的左子树的右子树高度过高时,需要先进行左旋转,再进行右旋转。
  4. 右左旋转(RL):当某个节点的右子树的左子树高度过高时,需要先进行右旋转,再进行左旋转。

四、C++实现AVL树

在C++中,我们可以使用类和结构体来实现AVL树。以下是一个简化的AVL树节点结构定义和旋转操作的伪代码实现。

template<class T>
struct AVLTreeNode
{
	AVLTreeNode(const T& data = T())
		: _pLeft(nullptr)
		, _pRight(nullptr)
		, _pParent(nullptr)
		, _data(data)
		, _bf(0)
	{}

	AVLTreeNode<T>* _pLeft;
	AVLTreeNode<T>* _pRight;
	AVLTreeNode<T>* _pParent;
	T _data;
	int _bf;   // 节点的平衡因子
};


// AVL: 二叉搜索树 + 平衡因子的限制
template<class T>
class AVLTree
{
	typedef AVLTreeNode<T> Node;
public:
	AVLTree()
		: _pRoot(nullptr)
	{}

	// 在AVL树中插入值为data的节点
	bool Insert(const T& data);
private:
	// 右单旋
	void RotateR(Node* pParent);// /
	// 左单旋
	void RotateL(Node* pParent);// '\'
	// 右左双旋
	void RotateRL(Node* pParent);//  >
	// 左右双旋
	void RotateLR(Node* pParent);//  <

private:
	Node* _pRoot;
};

 1增加

bool Insert(const T& data)
	{
		Node* newnode = new Node(data);
		if (_pRoot == nullptr)
		{
			_pRoot = newnode;
			return true;
		}
		else
		{
			Node* parent = nullptr;
			Node* cur = _pRoot;
			while (cur)
			{
				if (cur->_data < data)
				{
					parent = cur;
					cur = cur->_pRight;
				}
				else if (cur->_data > data)
				{
					parent = cur;
					cur = cur->_pLeft;
				}
				else
				{
					return false;
				}
			}
			if (parent->_data < data)
			{
				parent->_pRight = newnode;
			}
			else
			{
				parent->_pLeft = newnode;
			}
			newnode->_pParent = parent;
			//更新平衡因子
			cur = newnode;
			while (parent)
			{
				if (cur == parent->_pLeft)
				{
					parent->_bf++;
				}
				else
				{
					parent->_bf--;
				}
				if (parent->_bf == 0)
				{
					break;
				}
				else if (parent->_bf == 1 || parent->_bf == -1)
				{
					cur = parent;
					parent = parent->_pParent;
				}
				else if (parent->_bf == 2 || parent->_bf == -2)
				{
					if (parent->_bf == 2 && cur->_bf == 1)
					{
						RotateR(parent);
					}
					else if (parent->_bf == -2 && cur->_bf == -1)
					{
						RotateL(parent);
					}
					else if (parent->_bf == 2 && cur->_bf == -1)
					{
						RotateLR(parent);
					}
					else
					{
						RotateRL(parent);
					}
					break;
				}
				else
				{
					assert(false);
				}
			}
			return true;
		}
	}

2右旋转

// 右单旋
	void RotateR(Node* pParent)//  /
	{
		Node* pchild = pParent->_pLeft;
		Node* pchildr = pchild->_pRight;
		Node* grandfather = pParent->_pParent;
		if (pchildr)
		{
			pchildr->_pParent = pParent;
		}
		pParent->_pLeft = pchildr;
		pParent->_pParent = pchild;
		pchild->_pRight = pParent;
		if (pParent == _pRoot)
		{
			_pRoot = pchild;
			pchild->_pParent = nullptr;
		}
		else
		{
			if (grandfather->_pLeft == pParent)
			{
				grandfather->_pLeft = pchild;
			}
			else
			{
				grandfather->_pRight = pchild;
			}
			pchild->_pParent = grandfather;
		}
		pParent->_bf = pchild->_bf = 0;
	}

3.右左双旋

	// 右左双旋
	void RotateRL(Node* pParent)//  >
	{
		Node* pchild = pParent->_pRight;
		Node* pchildl = pchild->_pLeft;
		int bf = pchildl->_bf;
		RotateR(pchild);
		RotateL(pParent);
		pchildl->_bf = 0;
		if (bf == 1)
		{
			pParent->_bf = 0;
			pchild->_bf = -1;
		}
		else if (bf == -1)
		{
			pchild->_bf = 0;
			pParent->_bf = 1;
		}
		else
		{
			pParent->_bf = pchild->_bf = 0;
		}
	}

五、AVL树的应用

AVL树在需要频繁进行插入、删除和查找操作的场景中非常有用。例如,在数据库索引、文件系统的目录树等地方,AVL树都能提供高效的数据访问能力。

六、总结

AVL树作为一种平衡二叉搜索树,在维护其平衡性质的同时,也保证了高效的查找、插入和删除操作。通过旋转操作,AVL树能够在插入或删除节点后迅速恢复其平衡状态。在C++中,我们可以使用类和结构体来方便地实现AVL树,并将其应用到各种需要高效数据访问的场景中。

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

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

相关文章

噪声-降噪引脚如何提高系统性能

由于LDO是电子器件&#xff0c;因此它们会自行产生一定量的噪声。选择低噪声LDO并采取措施来降低内部噪声对于生成不会影响系统性能的清洁电源轨而言不可或缺。 识别噪声 理想的 LDO 会生成没有交流元件的电压轨。遗憾的是&#xff0c;LDO 会像其他电子器件一样自行产生噪声。…

【C++】关于代码编译自动更新版本的问题

在写代码的时候&#xff0c;总是需要添加一个版本号&#xff0c;用于后续的版本管理 我常遇到的一个问题是&#xff0c;开发过程中&#xff0c;不一定会记得这件事情&#xff0c;导致有时候会出现同样的版本 于是希望有一个方式&#xff0c;能在编译代码的时候自动生成一个版…

价值驱动型PMO如何实现项目战略目标?

近期&#xff0c;看到一个帖子&#xff0c;一位PMO&#xff08;小刘&#xff09;吐槽自己就是一个无情的项目推动机器&#xff0c;但还总被领导diss&#xff0c;他不知道问题出在哪了。评论区也有很多项目管理人吐槽自己也踩过类似的坑&#xff0c;那么本期就围绕这个案例展开相…

后端程序员的Linux命令指南

后端程序员的终极命令指南&#xff1a;考考自己是不是真正掌握Linux的使用 欢迎各位穿着格子衬衫&#xff0c;常年抱着键盘睡觉的后端小伙伴们&#x1f44b;&#x1f44b;&#x1f44b;&#xff01;今天&#xff0c;考考你们是不是掌握以下让你们在日后在服务器上叱咤风云的命令…

【环境变量问题:计算机删除环境变量的恢复方法;此环境变量太大。此对话框允许将值设置为最长2047个字符】

不小心误删了win10系统环境变量可以试试下文方法恢复。 本方法针对修改环境变量未重启的用户可以使用&#xff0c;如果修改环境变量&#xff0c;然后还重启了&#xff0c;只能说重新来。 方法一&#xff1a;使用命令提示符恢复 被修改的系统Path只是同步到了注册表中&#x…

天津这场智博会,成了智能时代的风向标

毫无疑问&#xff0c;这是一场智能产业的盛宴。 2024年6月20日至23日&#xff0c;国家会展中心&#xff08;天津&#xff09;迎来了一场智能科技领域的盛会——世界智能产业博览会&#xff1a;这场以“智行天下、能动未来”为主题的博览会&#xff0c;汇聚了全球49个国家和地区…

海外版coze前端代码助手

定位 解决前端同事的开发问题 参数配置 测试 支持 最屌的大模型及语音播报。 体验地址 海外版前端代码助手 需要魔法才能体验油

智能网联汽车实训教学“好帮手”——渡众机器人自动驾驶履带车

智能网联汽车实训教学“好帮手”——渡众机器人自动驾驶履带车 人工智能技术的兴起&#xff0c;为传统汽车行业注入了强有力的变革基因&#xff0c;以AI技术为驱动的无人驾驶成为汽车产业的未来&#xff0c;同样也面临诸多机遇和挑战。 一方面智能网联汽车的发展&#xff0c;为…

设置浏览器互不干扰

目录 一、查看浏览器文件路径 二、 其他盘新建文件夹Cache 三、以管理员运行CMD 四、执行命令 一、查看浏览器文件路径 chrome://version/ 二、 其他盘新建文件夹Cache D:\chrome\Cache 三、以管理员运行CMD 四、执行命令 Mklink /d "C:\Users\Lenovo\AppData\Loca…

【启明智显产品介绍】Model3C工业级HMI芯片详解专题(一)芯片性能

【启明智显产品介绍】工业级HMI芯片Model3C详解&#xff08;一&#xff09;芯片性能 Model3C 是一款基于 RISC-V 的高性能、国产自主、工业级高清显示与智能控制 MCU&#xff0c;配置平头哥E907&#xff0c;主频400MHz&#xff0c;强大的 2D 图形加速处理器、PNG/JPEG 解码引擎…

[240621] Anthropic 发布了 Claude 3.5 Sonnet AI 助手 | Socket.IO 拒绝服务漏洞

目录 Anthropic 发布 Claude 3.5 Sonnet AI 助手Scoket.IO 拒绝服务漏洞&#xff08;CVE-2024-38355&#xff09; Anthropic 发布 Claude 3.5 Sonnet AI 助手 Claude 3.5 Sonnet: 更智能、更快速、更安全的 AI 助手 一、 引言 Anthropic 发布了 Claude 3.5 Sonnet&#xff0…

excel基本操作

excel 若要取消在数据表中进行的所有筛选 步骤操作&#xff1a; 单击“数据”选项卡。在“排序和筛选”组中&#xff0c;找到“清除”按钮。点击“清除”按钮。 图例&#xff1a; 将文本文件的数据导入到Excel工作表中进行数据处理 步骤&#xff1a; 在Excel中&#xff0c…

详细解读“找不到mfc140u.dll无法继续执行代码”问题

当你打开某个软件或者运行游戏&#xff0c;系统提示mfc140u.dll丢失&#xff0c;此时这个软件或者游戏根本无法运行。其实&#xff0c;mfc140u.dll是动态库文件&#xff0c;它是VS2010编译的软件所产生的&#xff0c;如果电脑运行程序时提示缺少mfc140u.dll文件&#xff0c;程序…

高德行政区查询-综合省市县三级选择跳转

一、需求&#xff1a; 需要使用高德地图进行省市县的一个选择&#xff0c;每选择一次就在地图上对选择的省市县进行定位并画出该区域的范围。 最终效果&#xff1a; 二、准备工作 高德的API的key&#xff1a;两种 三、完整页面代码 综合的是这两篇中的内容&#xff08;不…

python pyautogui实现图片识别点击失败后重试

安装库 pip install Pillow pip install opencv-python confidence作用 confidence 参数是用于指定图像匹配的信度&#xff08;或置信度&#xff09;的&#xff0c;它表示图像匹配的准确程度。这个参数的值在 0 到 1 之间&#xff0c;数值越高表示匹配的要求越严格。 具体来…

Java中将文件转换为Base64编码的字节码

在Java中&#xff0c;将文件转换为Base64编码的字节码通常涉及以下步骤&#xff1a; 读取文件内容到字节数组。使用java.util.Base64类对字节数组进行编码。 下面是一个简单的Java示例代码&#xff0c;演示如何实现这个过程&#xff1a; import java.io.File; import java.io…

实验13 简单拓扑BGP配置

实验13 简单拓扑BGP配置 一、 原理描述二、 实验目的三、 实验内容四、 实验配置五、 实验步骤 一、 原理描述 BGP&#xff08;Border Gateway Protocol&#xff0c;边界网关协议&#xff09;是一种用于自治系统间的动态路由协议&#xff0c;用于在自治系统&#xff08;AS&…

太牛了!AI换脸数字人,限制解除,免费用!

哈喽&#xff0c;各位小伙伴们好&#xff0c;我是给大家带来各类黑科技与前沿资讯的小武。 今天给大家安利一款美图公司出品的神器&#xff0c;功能限制完全解除&#xff0c;可以免费使用AI换脸数字人、AI提词器、AI脚本、AI抠图、AI清除、AI封面等超多超实用功能&#xff0c;…

鸿蒙开发:【进程模型概述】

进程模型概述 系统的进程模型如下图所示&#xff1a; 应用中&#xff08;同一包名&#xff09;的所有PageAbility、ServiceAbility、DataAbility、FormAbility运行在同一个独立进程中&#xff0c;即图中绿色部分的“Main Process”。 WebView拥有独立的渲染进程&#xff0c;即…

python20 函数的定及调用

函数的定及调用 函数是将一段实现功能的完整代码&#xff0c;使用函数名称进行封装&#xff0c;通过函数名称进行调用。以此达到一次编写&#xff0c;多次调用的目的 用 def 关键字来声明 函数 格式&#xff1a; def 函数名(参数列表):函数体[:return 返回值是可选的&#xff0…