AVL树建立

news2024/11/13 22:03:08

AVL树是在二叉搜索树基础上实现的,与二叉搜索树不同的是,AVL树的左右子树高度相差不超过1.

AVL树的旋转

大致分为四类:

单旋:

左左——右旋:使平衡因子为-2的父节点与左子树相连,该节点的左节点与左孩子的右节点相连

右右——左旋:使平衡因子为2的父节点与右子树相连,该节点的右节点与右孩子的左子树相连

双旋:以下是最简单的情况,具体还要考虑插入位置来改平衡因子

左右——先左旋后右旋

右左——先右旋再左旋

代码

#include<iostream>
#include<time.h>
#include<assert.h>
#include<stdlib.h>
using namespace std;
template<class T>
struct AVLtreeNode
{
	AVLtreeNode<T>* left;
	AVLtreeNode<T>* right;
	AVLtreeNode<T>* parent;
	T data;
	int bf;//平衡因子
	AVLtreeNode(const T& d)
		:left(nullptr),right(nullptr),parent(nullptr),data(d),bf(0)
	{}
};
template <class T>
class AVLtree
{
	AVLtreeNode<T>* root;
public:
	AVLtree()
		:root(nullptr)
	{}
	void insert(const T& d)
	{
		//二叉搜索树方式插入
		AVLtreeNode<T>* newt = new AVLtreeNode<T>(d);
		if (root == nullptr)
			root = newt;
		else
		{
			AVLtreeNode<T>* n = root;
			AVLtreeNode<T>* p = root;
			while (n)
			{
				p = n;
				if (n->data >= newt->data)
					n = n->left;
				else
					n = n->right;
			}
			if (p->data >= newt->data)
			{
				p->left = newt;
				newt->parent = p;
			}
			else
			{
				p->right = newt;
				newt->parent = p;
			}
		}
		//向上调整平衡因子
		
		AVLtreeNode<T>* p = newt->parent;
		AVLtreeNode<T>* n =newt;
		while (p)
		{
			assert(p);
			assert(root);
			if (p->left == n)
				p->bf--;
			else if(p->right==n)
				p->bf++;
			if (p->bf == 0)
				break;
				if (abs(p->bf) == 2)
				{
					if (p->bf == -2 && p->left->bf == -1)
					{
						if (p == root)
							root = p->left;
						p->bf = 0;
						p->left->bf = 0;
						RotateR(p);
						
					}
					else if (p->bf == 2 && p->right->bf == 1)
					{
						if (p == root)
							root = p->right;
						p->bf = 0;
						p->right->bf = 0;
						RotateL(p);
					}
					else if (p->bf == -2 )
					{
						if (p == root)
							root = p->left->right;
						int bf = p->left->right->bf;
						if (bf == -1)
						{
							p->left->right->bf = 0;
							p->left->bf = 0;
							p->bf = 1;
						}
						else if (bf == 1)
						{
							p->left->right->bf = 0;
							p->left->bf = -1;
							p->bf = 0;
						}
						else if (bf == 0)
						{
							p->left->right->bf = 0;
							p->left->bf = 0;
							p->bf = 0;
						}
						
						RotateL(p->left);
						RotateR(p);
					}
					else
					{
						if (p == root)
							root = p->right->left;
						int bf = p->right->left->bf;
						if (bf == 1)
						{
							p->right->left->bf = 0;
							p->bf = -1;
							p->right->bf = 0;
						}
						else if (bf == -1)
						{
							p->bf = 0;
							p->right->bf = 1;
							p->right->left->bf = 0;
						}
						else
						{
							p->bf = 0;
							p->right->bf = 0;
							p->right->left->bf = 0;
						}
						RotateR(p->right);
						RotateL(p);
					}
					root->parent = nullptr;
					p = p->parent;
					break;
				}
				n = p;
			p = p->parent;
		}
	}
	void show()
	{
		inor(root);
	}
	
	AVLtreeNode<T>* Find(const T& key)
	{
		AVLtreeNode<T>* cur = root;
		while (cur)
		{
			if (cur->data < key)
			{
				cur = cur->right;
			}
			else if (cur->data > key)
			{
				cur = cur->left;
			}
			else
			{
				return cur;
			}
		}

		return nullptr;
	}
	bool IsBalance()
	{
		return _IsBalance(root);
	}
};
template<typename T>
void inor(AVLtreeNode<T>* root)
{
	if (root == nullptr)
		return;
	pre(root->left);
	cout << root->data << ' ';
	pre(root->right);
}
template<typename T>
void RotateR(AVLtreeNode<T>* root)
{
	AVLtreeNode<T>* n = root->left;
	root->left = n->right;
	if(n->right)
	n->right->parent = root;
	n->right = root;
	n->parent = root->parent;
	if (root->parent != nullptr)
	{
		if (root->parent->left == root)
			root->parent->left = n;
		else
			root->parent->right = n;
	}
	root->parent = n;
}
template<typename T>
void RotateL(AVLtreeNode<T>* root)
{
	AVLtreeNode<T>* n = root->right;
	root->right = n->left;
	if(n->left)
	n->left->parent = root;
	n->left = root;
	n->parent = root->parent;
	if (root->parent != nullptr)
	{
		if (root->parent->left == root)
			root->parent->left = n;
		else
			root->parent->right = n;
	}
	root->parent = n;
}
template<typename T>
int _Height(AVLtreeNode<T>* root)
{
	if (root == nullptr)
		return 0;

	return max(_Height(root->left), _Height(root->right)) + 1;
}
template<typename T>
bool _IsBalance(AVLtreeNode<T>* root)
{
	if (root == nullptr)
		return true;

	int leftHeight = _Height(root->left);
	int rightHeight = _Height(root->right);
	// 不平衡
	if (abs(leftHeight - rightHeight) >= 2)
	{
		cout << root->data << endl;
		return false;
	}

	// 顺便检查一下平衡因子是否正确
	if (rightHeight - leftHeight != root->bf)
	{
		cout << root->data << endl;
		return false;
	}

	return _IsBalance(root->left)
		&& _IsBalance(root->right);
}
void test()
{
	int num = 100000;
	AVLtree<int> t;
	int a[] = { 37,18,52,58,72,51,42,98,34,87  };
	for (int i = 0; i < num; i++)
	{
	
		int k = rand()+1;
	/*	while (t.Find(k) != nullptr)
			k = rand()%1000000 + 1;*/

		t.insert(k);
	//cout <<i<<' '<< k << ':';

	}
	cout << t.IsBalance() << endl;


}
int main()
{
	srand(time(NULL));
	test();
}

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

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

相关文章

spring boot 项目 prometheus 自定义指标收集和 grafana 查询--方法耗时分位数指标

auth author JellyfishMIX - github / blog.jellyfishmix.comLICENSE LICENSE-2.0 说明 网上有很多 promehteus 和 grafana 配置&#xff0c;本文不再重复&#xff0c;只介绍自定义部分。目前只介绍了分位数指标的收集和查询&#xff0c;常用于方法耗时的指标监控。 自定义…

Python函数(进程和线程)

Python基础语法文章导航&#xff1a; Python基础&#xff08;01初识数据类型&变量&#xff09;Python基础&#xff08;02条件&循环语句&#xff09;Python基础&#xff08;03字符串格式化&运算符&进制&编码&#xff09;Python基础&#xff08;04 基础练习…

【媒体人必备】免费的 AI 配音神器,还有黑神话悟空的配音

【媒体人必备】免费的 AI 配音神器&#xff0c;还有黑神话悟空的配音 在短视频风靡全球的时代&#xff0c;TikTokVoice 提供了一个功能强大、操作简单的在线文字转语音工具&#xff0c;支持多种语言和热门AI配音角色。本文将带你了解这个工具的独特之处&#xff0c;以及如何利用…

【计算机组成原理】计算机系统的层次结构——计算机软件

计算机系统的层次结构 导读一、计算机软件的分类二、计算机语言三、计算机系统的层次结构3.1 从计算机语言的角度来理解多级层次结构3.2 计算机层次之间的关系3.3 指令集体系结构&#xff08;ISA&#xff09; 结语 导读 大家好&#xff0c;很高兴又和大家见面啦&#xff01;&a…

Redis(13)| 主从复制

关键词&#xff1a;主从复制&#xff0c;主从数据一致性&#xff0c;同步 带着问题阅读 主从复制解决了什么问题&#xff1f;主从复制的原理&#xff08;过程&#xff09;是什么&#xff1f;主从切换时是如何减少数据丢失的 前言 我在前已经给大家图解了 AOF 和 RDB&#x…

创新之光闪耀,点赋科技在第十三届创新创业大赛中绽放光彩

近日&#xff0c;第十三届创新创业大赛决赛落下帷幕&#xff0c;这场充满激情与挑战的赛事吸引了众多优秀企业参与角逐。在激烈的竞争中&#xff0c;点赋科技脱颖而出&#xff0c;荣获第三名的佳绩。 创新创业大赛一直是企业展示实力、交流创新理念的重要平台。本次大赛中&…

p2p、分布式,区块链笔记: Merkle-DAG和Merkle-Tree的区别与联系

Merkle-DAG和Merkle-Tree的区别与联系 结构: Merkle-Tree 是一种二叉树结构&#xff0c;每个非叶子节点是其子节点哈希的哈希。它具有层次结构&#xff0c;通常用于验证数据的完整性。Merkle-DAG&#xff08;有向无环图&#xff09;是一种更通用的图结构&#xff0c;其一个节点…

142. Go操作Kafka(confluent-kafka-go库)

文章目录 Apache kafka简介开始使用Apache Kafka构建生产者构建消费者 总结 之前已经有两篇文章介绍过 Go如何操作 kafka 28.windows安装kafka&#xff0c;Go操作kafka示例&#xff08;sarama库&#xff09; 51.Go操作kafka示例&#xff08;kafka-go库&#xff09; Apache ka…

django外键表查询

Django外键&#xff08;ForeignKey&#xff09;操作以及related_name的作用-CSDN博客 django模型中外键操作_django的model的contain外键-CSDN博客 通过基本表可以查外键表 删基本表可以删外键表

【Redis】Redis 持久化 AOF、RDB—(七)

目录 一、AOF 日志二、RDB 内存快照 Redis 一旦服务器宕机&#xff0c;内存中的数据将全部丢失&#xff0c;从后端数据库恢复这些数据&#xff0c;对数据库压力很大&#xff0c;且性能肯定比不上从 Redis 中读取&#xff0c;会拖慢应用程序。所以&#xff0c;对 Redis 来说&…

临时性解决斐讯K3 路由器端口转发限制

几年前&#xff0c;原来买的斐讯路由器被我折腾坏掉了。然后那时候刚好K3出来。差不多2000块&#xff0c;因为之前的一个路由器顺利下车&#xff0c;然后就傻傻的上了K3的车。结局&#xff0c;你懂的。 最近因为需要&#xff0c;在折腾远程办公&#xff0c;大概目的就是方便连…

Python | Leetcode Python题解之第386题字典序排数

题目&#xff1a; 题解&#xff1a; class Solution:def lexicalOrder(self, n: int) -> List[int]:ans [0] * nnum 1for i in range(n):ans[i] numif num * 10 < n:num * 10else:while num % 10 9 or num 1 > n:num // 10num 1return ans

pycharm破解教程

下载pycharm https://www.jetbrains.com/pycharm/download/other.html 破解网站 https://hardbin.com/ipfs/bafybeih65no5dklpqfe346wyeiak6wzemv5d7z2ya7nssdgwdz4xrmdu6i/ 点击下载破解程序 安装pycharm 自己选择安装路径 安装完成后运行破解程序 等到Done图标出现 选择Ac…

数据安全法实施三周年 | 天空卫士引领关键技术突破

2024.09.01星期日 三年前的今天数据安全法正式实施&#xff0c;标志着我国数据安全防护体系迈入了一个崭新的发展阶段。 《数据安全法》提出&#xff1a;国家建立数据分类分级保护制度&#xff0c;对数据实行分类分级保护。建立健全全流程数据安全管理制度&#xff0c;组织开展…

NumPy实现线性回归

1 单变量线性回归 1.1 sklearn实现(最小二乘法) import osimport pandas as pd import matplotlib.pyplot as plt import syscurrent_diros.getcwd() pathcurrent_dir\\"Salary Data.csv"def plot_data(path):tablepd.read_csv(path)experience table["Exper…

六、Selenium操作指南(三)

文章目录 七、模拟鼠标操作&#xff08;一&#xff09;左键 click()&#xff08;二&#xff09;右键 context_click()&#xff08;三&#xff09;双击 double_click()&#xff08;四&#xff09;拖拽 drag_and_drop(source,target)&#xff08;五&#xff09;悬停 move_to_elem…

python-禁止抽烟

题目描述 小理的朋友有 n 根烟&#xff0c;他每吸完一根烟就把烟蒂保存起来&#xff0c;k&#xff08; k>1&#xff09;个烟蒂可以换一个新的烟&#xff0c;那么小理的朋友最终能吸到多少根烟呢&#xff1f; 与某些脑筋急转弯不同的是&#xff0c;小理的朋友并不能从异次元借…

AI 通过python脚本自动化导出交易软件某一天的分笔成交明细

一.背景需求 打开交易软件,我们想要导出非今日的日线股票成交分笔明细,其实,很麻烦的。你得在日线图上点击某一天的柱状图,然后双击,就会出现当日的成交明细,然后导出。如果你想到导出30天或者1年的数据呢?你难道盯着电脑一步一步的操作?不,我不允许你还不知道用pytho…

应急响应-爆破漏洞应急响应流程(以SSH爆破为例)

目录 概述研判分析登录成功登录失败历史命令authorized_keys 定损止损攻击链路还原清理恢复总结复盘参考 概述 爆破漏洞是比较常见漏洞&#xff0c;端口开放&#xff0c;管理后台没有做登录频率限制等情况都可能遭受到爆破攻击&#xff0c;本文以SSH爆破为例&#xff0c;介绍下…

【SpringCloud Alibaba】(十二)学习 Sleuth + ZipKin

目录 1、ZipKin 核心架构1.1、ZipKin 概述1.2、ZipKin 核心架构 2、集成 ZipKin2.1、下载安装 ZipKin 服务端2.2、集成 ZipKin 客户端 3、ZipKin 数据持久化3.1、ZipKin 数据持久化到 MySQL 在前面整合 Sleuth 实现链路追踪时&#xff0c;我们是通过查看日志的情况来了解系统调…