AVL树(C++)

文章介绍了二叉搜索树在插入有序或接近有序数据时可能退化为单支树,导致搜索效率降低。为解决这一问题,1962年Adelson-Velskii和Landis提出了AVL树的概念,确保每个节点的左右子树高度差不超过1,保持树的平衡,从而优化搜索时间复杂度为O(log_2n)。文章提供了AVL树的插入操作实现,包括旋转操作以维持平衡。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二叉搜索树有其自身的缺陷,假如往树中
插入的元素有序或者接近有序,二叉搜索树就会退化成单支树,时间复杂度会退化成 O(N)
二叉搜索树虽可以缩短查找的效率,但 如果数据有序或接近有序二叉搜索树将退化为单支树,查
找元素相当于在顺序表中搜索元素,效率低下 。因此,两位俄罗斯的数学家 G.M.Adelson-Velskii
E.M.Landis 1962
发明了一种解决上述问题的方法: 当向二叉搜索树中插入新结点后,如果能保证每个结点的左右
子树高度之差的绝对值不超过 1( 需要对树中的结点进行调整 ) ,即可降低树的高度,从而减少平均
搜索长度。

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

它的左右子树都是 AVL
左右子树高度之差 ( 简称平衡因子 ) 的绝对值不超过 1(-1/0/1)
如果一棵二叉搜索树是高度平衡的,它就是 AVL 树。如果它有 n 个结点,其高度可保持在
$O(log_2 n)$ ,搜索时间复杂度 O($log_2 n$)

平衡因子=右子树高度-左子树高度 

#include<iostream>
#include<assert.h>
using namespace std;
template<class k,class v>
struct AVLtreeNode
{
	pair<k, v> _kv;
	AVLtreeNode<k, v>* left;
	AVLtreeNode<k, v>* right;
	AVLtreeNode<k, v>* parent;
	int _bf;
	AVLtreeNode(const pair<k, v>& a)
		:_kv(a)
		,left(nullptr)
		,right(nullptr)
		,parent(nullptr)
		,_bf(0)
	{}
};
template<class k, class v>
struct AVLtree
{
	typedef AVLtreeNode<k, v> Node;
public:
	bool Insert(const pair<k, v>& a)
	{
		if (_root == nullptr)
		{
			_root = new Node(a);
			return true;
		}
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_kv.first < a.first)
			{
				parent = cur;
				cur = cur->right;
			}
			else if (cur->_kv.first > a.first)
			{
				parent = cur;
				cur = cur->left;
			}
			else
				return false;
		}
		cur = new Node(a);
		if (parent->_kv.first > a.first)
		{
			parent->left = cur;
			cur->parent = parent;
		}
		else if(parent->_kv.first < a.first)
		{
			parent->right = cur;
			cur->parent = parent;
		}
		
		while (parent)
		{
			if (cur == parent->left)
			{
				parent->_bf--;
			}
			else if (cur == parent->right)
			{
				parent->_bf++;
			}
			if (parent->_bf == 0)
				break;
			else if (parent->_bf == 1 || parent->_bf == -1)
			{
				cur = parent;
				parent = parent->parent;
			}
			else if (parent->_bf == 2 || parent->_bf == -2)
			{
				if (parent->_bf == 2 && cur->_bf == 1)
				{
					RotateL(parent);
				}
				else if (parent->_bf == -2 && cur->_bf == -1)
				{
					RotateR(parent);
				}
				else if (parent->_bf == -2 && cur->_bf == 1)
				{
					RotateLR(parent);
				}
				else if (parent->_bf == 2 && cur->_bf == -1)
				{
					RotateRL(parent);
				}
				else
				{
					assert(false);
				}
				break;
			}
			
		}
		
		return true;
	}
	void RotateL(Node* parent)
	{
		Node* sub = parent;
		Node* subp = parent->parent;
		Node* subr = parent->right;
		Node* t = subr->left;
		if (subp == nullptr)
		{
			subr->parent = nullptr;
			_root = subr;
		}
		else if (subp)
		{
			if (subp->right == sub)
			{
				subp->right = subr;
			}
			else if (subp->left == sub)
			{
				subp->left = subr;
			}
			subr->parent = subp;
		}
		if (t)
		{
			sub->right = t;
			t->parent = sub;
		}
		else
		{
			sub->right = nullptr;
		}
		sub->parent = subr;
		subr->left = sub;
		sub->_bf = subr->_bf = 0;
		/*Node* subR = parent->right;
		Node* subRL = subR->left;
		parent->right = subRL;
		if (subRL)
			subRL->parent = parent;
		Node* ppNode = parent->parent;
		subR->left = parent;
		parent->parent = subR;


		if (ppNode == nullptr)
		{
			_root = subR;
			_root->parent = nullptr;
		}
		else
		{
			if (ppNode->left == parent)
			{
				ppNode->left = subR;
			}
			else
			{
				ppNode->right = subR;
			}

			subR->parent = ppNode;
		}

		parent->_bf = subR->_bf = 0;*/
	}
	void RotateR(Node* parent)
	{
		Node* subp = parent->parent;
		Node* subl = parent->left;
		Node* t = subl->right;
		parent->left = t;
		if (t)
			t->parent = parent;
		subl->right = parent;
		parent->parent = subl;
		if (subp == nullptr)
		{
			subl->parent = nullptr;
			_root = subl;
		}
		else if (subp)
		{
			if (subp->right == parent)
			{
				subp->right = subl;
			}
			else if (subp->left == parent)
			{
				subp->left = subl;
			}
			subl->parent = subp;
		}
		
		parent->_bf= subl->_bf = 0;
		//Node* subL = parent->left;
		//Node* subLR = subL->right;

		//parent->left = subLR;
		//if (subLR)
		//{
		//	subLR->parent = parent;
		//}

		//Node* ppNode = parent->parent;
		//subL->right = parent;
		//parent->parent = subL;

		if (_root == parent)
		//if (ppNode == nullptr)
		//{
		//	_root = subL;
		//	_root->parent = nullptr;
		//}
		//else
		//{
		//	if (ppNode->left == parent)
		//	{
		//		ppNode->left = subL;
		//	}
		//	else
		//	{
		//		ppNode->right = subL;
		//	}

		//	subL->parent = ppNode;
		//}

		//subL->_bf = parent->_bf = 0;
	}
	void RotateLR(Node* parent)
	{
		Node* sub = parent->left;
		Node* subr = sub->right;
		int bf = subr->_bf;

		RotateL(parent->left);
		RotateR(parent);

		if (bf == -1)
		{
			sub->_bf = 0;
			parent->_bf = 1;
			subr->_bf = 0;
		}
		else if (bf == 1)
		{
			parent->_bf = 0;
			sub->_bf = -1;
			subr->_bf = 0;
		}
		else if (bf == 0)
		{
			parent->_bf = 0;
			sub->_bf = 0;
			subr->_bf = 0;
		}
		else
		{
			assert(false);
		}
	
	}
	void RotateRL(Node* parent)
	{
		Node* sub = parent->right;
		Node* subl = sub->left;
		int bf = subl->_bf;
		RotateR(parent->right);
		RotateL(parent);
		if (bf == -1)
		{
			sub->_bf = 1;
			parent->_bf = 0;
			subl->_bf = 0;
		}
		else if (bf == 1)
		{
			parent->_bf = -1;
			sub->_bf = 0;
			subl->_bf = 0;
		}
		else if (bf == 0)
		{
			parent->_bf = 0;
			sub->_bf = 0;
			subl->_bf = 0;
		}
		else
		{
			assert(false);
		}
	
	}
	void Inorder()
	{
		_Inorder(_root);
	}
	void _Inorder(Node* root)
	{
		if (root == nullptr)
			return;
		_Inorder(root->left);
		cout << root->_kv.first << ":" << root->_kv.second << endl;
		_Inorder(root->right);
	}
	int Height(Node* node)
	{
		if (node == nullptr)
			return 0;
		return max(Height(node->left), Height(node->right)) + 1;
	}
	bool isblance()
	{
		return _isblance(_root);
	}
	bool _isblance(Node* node)
	{
		if (node == nullptr)
			return true;
		int highr = Height(node->right);
		int highl = Height(node->left);
		if (highr - highl != node->_bf)
		{
			cout <<node->_kv.first<< "平衡因子出错" << endl;
			return false;
		}
		return abs(highr - highl) < 2 && _isblance(node->right) && _isblance(node->left);
	}
	private:
		Node* _root = nullptr;
};
void testtree()
{
	//int a[5] = { 4,2,6,1,3 };
	srand(time(0));
	AVLtree<int, int> t;
	for (int i=0;i<1000;i++)
	{
		int k = rand();
		t.Insert(make_pair(k,k));
	}
	t.Inorder();
	cout << t.isblance() << endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南种北李

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值