首页 > 其他分享 >笔记——AVL树

笔记——AVL树

时间:2024-08-03 18:28:07浏览次数:11  
标签:Node bf cur parent 笔记 AVL root left

和普通的二叉搜索树的区别:

普通的二叉搜索树 只满足左子树小于个根,右子树大于根,不会进行平衡(降低高度)这就导致可能退化,这样查找插入数据的时间复杂度就是o(n)

而为了防止二叉搜索树退化,AVL树引入了 平衡因子 的概念,使树的每一层都是满的,只有树的一层满后才插入下一层,利用 平衡因子就可以达成这样的效果

平衡因子:

右子树高度减去左子树高度,范围在【-1,1】,

在进行插入的时候,先找到要插入的位置,然后更新被插入节点的祖宗的 平衡因子

平衡因子的更新

插在父节点的左边,父节点的平衡因子自减1,插在左边自增1,接着向上更新

插入后父节点平衡因子的大小

正负1 之前父节点的平衡因子为0,父节点的父节点的平衡因子 加或减 1

为 0 之前父节点的平衡因子为 正负1,停止更新平衡因子

为+-2 需要旋转节点,使平衡因子小于2

旋转方法

左旋

右边节点高,进行左旋

grandpa

          parent

                     cur

parent是grandpa的右孩子,cur是parent的右孩子,这种情况要左旋

                     grandpa

                                  parent

                             cur

parent是grandpa的右孩子,cur是parent的左孩子,先右旋,在左旋

先将 parent 以parent为旋转点 ,进行右·旋

cur

得到 grandpa 以cur为旋转点,进行左旋

cur

parent

右旋

左边节点高,进行右旋

代码部分

#pragma once
#include<iostream>
using namespace std;

template<class K,class V >
class AVLNode
{
public:
	typedef AVLNode<K, V>Node;

	Node* _left;
	Node* _right;
	Node* _parent;
	int _bf;
	pair<K, V>_kv;
public:
	AVLNode(pair<K,V>kv)
		:_left(nullptr)
		,_right(nullptr)
		, _parent(nullptr)
		, _kv(kv)
		, _bf(0)
	{}
};

template<class K,class V>
class AVLTree
{
public:
	typedef AVLNode<K, V> Node;
private:
	Node* _root=nullptr;
public:


	//构造函数
	AVLTree()
		:_root(nullptr)
	{}



	//析构函数
	void _Destory(Node*root)
	{
		if (root == nullptr)
			return;
		_Destory(root->_left);
		_Destory(root->_right);
		delete root;
	}
	~AVLTree()
	{
		_Destory(_root);
	}


	//拷贝构造函数
	Node* _Copy(Node* root)
	{
		if (root == nullptr)
			return nullptr;
		Node* left = _Copy(root->_left);
		Node* right = _Copy(root->_right);
		Node* newnode = new Node;
		newnode->_left = left;
		newnode->_right = right;
		newnode->_bf = root->_bf;
		newnode->_kv = root->_kv;
		return newnode;

	}
	AVLTree(const Node& t)
	{
		_Copy(&t);
	}


	//赋值
	AVLTree<K, V>operator=(AVLTree<K,V>t)
	{
		swap(_root, t._root);
		return *this;
	}



	//左旋
	void RotateL(Node* cur)
	{
		Node* parent = cur->_parent;
		Node* curL = cur->_left;
		cur->_parent = curL;
		cur->_left = cur->_right;
		curL->_right = cur;
		
		if (parent->_left == cur)
			parent->_left = curL;
		else
			parent->_right = curL;
		
		curL->_bf = cur->_bf = 0;

	}

	//右旋
	void RotateR(Node*cur)
	{
		Node* parent = cur->_parent;
		Node* curR = cur->_right;
		if (parent->_left == cur)
		{
			parent->_left = curR;
		}
		else
		{
			parent->_right = curR;
		}
		cur->_right = curR->_left;
		cur->_parent = curR;
		curR->_parent = parent;
		curR->_left = cur;
		cur->_bf = curR->_bf = 0;

	}



	//插入
	bool Insert(pair<K, V>kv)
	{
		if (_root == nullptr)
		{
			_root = new Node(kv);
			return 1;
		}
		Node* cur = _root;
		//找到要插入的位置
		Node* parent = nullptr;
		while (cur)
		{
			if (cur->_kv.first < kv.first)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->_kv.first > kv.first)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return false;
			}
		}

		Node* newnode = new Node(kv);
		if (parent->_kv.first > kv.first)
		
		{
			parent->_left = newnode;
			parent->_bf--;
		}
		else
		{
			parent->_right = newnode;
			parent->_bf++;
		}
		//更新平衡因子

			cur = parent;
			if (parent != nullptr)
			{
				parent = parent->_parent;
			}
			else
				return true;
			while (parent)
			{
				if (cur->_bf == 0)
				{
					return true;
				}
				else if (abs(cur->_bf) == 1)
				{
					if (parent->_left == cur)
					{
						parent->_bf--;
					}
					else
					{
						parent->_bf++;
					}
					cur = parent;
					parent = parent->_parent;
				}
				else if (abs(cur->_bf) == 2)
				{
					if (cur->_bf == -2)
					{
						Node* curL = cur->_left;
						if (curL->_bf == -1)
						{
							RotateR(cur);
						}
						else
						{
							RotateL(cur);
							RotateR(cur);
						}
					}
					else
					{
						Node* curR = cur->_right;
						if (curR->_bf == 1)
						{
							RotateL(cur);
						}
						else
						{
							RotateR(cur);
							RotateL(cur);
						}
					}
				}

			}
		

	}
	//中序遍历
	void _Inorder(Node* root)
	{
		if (root == nullptr)
			return;
		_Inorder(root->_left);
		cout << root->_kv.first << " _bf:"<<root->_bf<<endl;
		_Inorder(root->_right);
	}
	void Inorder()
	{
		_Inorder(_root);
	}

};

标签:Node,bf,cur,parent,笔记,AVL,root,left
From: https://blog.csdn.net/2302_80181022/article/details/140890248

相关文章

  • OpenCV计算机视觉学习(16)——仿射变换学习笔记
    如果需要其他图像处理的文章及代码,请移步小编的GitHub地址传送门:请点击我如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice在计算机视觉和图像处理中,仿射变换是一种重要的几何变换方法。它可以通过线性变换和平移来改变图像的形状和位置,广泛应......
  • Objective-C学习笔记(协议和代理)
    协议协议是多个类共享的一个方法列。协议中列出的方法没有相应的实现,计划由其他人来实现。可以定义这些方法为必须实现的,也可以为可选择实现的@protocal协议名//在此处添加必须实现的协议方法@optional//在此处添加可选择实现的协议方法@end遵循协议也符合继承关系......
  • 【笔记】动态规划选讲:凸优化技术大赏 2024.8.3
    如果您是搜索引擎搜进来的。很抱歉,没有您需要搜索的题目的题解。典题\(n\)个物品的背包,重量在\(1\sim4\)之间,价值在\(1\sim10^9\)之间。\(n\leq10^5\)。Minkowski和会遇到不连续的问题。不妨按照\(i\bmod12\)划分dp数组,每个剩余系都是凸的。枚举拿了\(......
  • FFmpeg开发笔记(四十三)使用SRS开启SRT协议的视频直播服务
    ​《FFmpeg开发实战:从零基础到短视频上线》一书在第10章介绍了轻量级流媒体服务器MediaMTX,通过该工具可以测试RTSP/RTMP等流媒体协议的推拉流。不过MediaMTX的功能实在是太简单了,无法应用于真实直播的生产环境,真正能用于生产环境的流媒体服务器还要看SRS或者ZLMediaKit。SRS是一......
  • Pytorch笔记|小土堆|P14-15|torchvision数据集使用、Dataloader使用
    学会看内置数据集的官方文档:https://pytorch.org/vision/stable/generated/torchvision.datasets.CIFAR10.html#torchvision.datasets.CIFAR10示例代码:importtorchvisionfromtorch.utils.tensorboardimportSummaryWriterfromtorchvisionimporttransforms#ToTensorte......
  • java学习笔记9
    一、线程与进程        线程是指计算机中能够执行独立任务的最小单位。它是进程的一部分,一个进程可以包含多个线程。每个线程都是独立运行的,它们共享进程的资源,如内存空间和文件句柄等。线程之间可以通过共享内存进行通信,因此线程之间的切换开销较小。      ......
  • 硬件开发笔记(二十九):TPS54331电源设计(二):12V转3.3V和12V转4V原理图设计
    若该文为原创文章,转载请注明原文出处本文章博客地址:https://hpzwl.blog.csdn.net/article/details/140868749长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…硬件相关开发......
  • 谷粒商城实战笔记-115-全文检索-ElasticSearch-进阶-bool复合查询
    文章目录1,must2,mustnot3,should1,must{"query":{"bool":{"must":[{"match":{"gender":"M"}},{"matc......
  • 谷粒商城实战笔记-118-全文检索-ElasticSearch-进阶-aggregations聚合分析
    文章目录一,基本概念主要聚合类型二,实战1,搜索address中包含mill的所有人的年龄分布以及平均年龄,但不显示这些人的详情2,按照年龄聚合,并且请求每个年龄的平均薪资Elasticsearch的聚合(Aggregations)功能允许用户对数据集进行聚合分析,从而获得数据的摘要信息。聚......
  • 动态规划学习笔记
    P3195求出玩具的前缀和\(S\)。设\(f_i\)表示区间\([1,i]\)的最大答案。开始应该是\(f_0=0\)。\(f_i=\max_{1\lej<i}f_j+(i+S_i-L-1-(j+S_j))^2\)。\(f_i=\max_{1\lej<i}f_j+(i+S_i-L-1)^2+(j+S_j)^2-2(i+S_i-L-1)(j+S_j)\)。设\(g_i=i+S_i,k=L+1\),那么\(f_......