AVL树

AVL树

一、概念

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

1、它的左右子树都是AVL树

2、左子树和右子树高度之差(简称平衡因子)的绝对值不超过1

如果一棵二叉搜索树是高度平衡的,它就是AVL树。如果它有n个结点,其高度可保持在O(lgn),平均搜索时间复杂度O(lg(n))

二、平衡化

如果在一个原本平衡的二叉搜索树中插入一个新节点,可能会导致二叉搜索树不平衡,此时必须调整树的结构使之平衡化。

在插入新的结点时,如果新插入的结点使原本的一些结点的平衡因子的绝对值等于2,这时候就需要用以下四种旋转方法调整不平衡的子树,使得整个树保持平衡:

1、左单旋

插入点位于不平衡节点的右子节点的右子树 -- 右右



2、右单旋

插入点位于不平衡节点的左子节点的左子树 -- 左左


3、左右双旋(先左后右双旋)

插入点位于不平衡节点的左子节点的右子树 -- 左右


4、右左双旋(先右后左双旋)

插入点位于不平衡节点的右子节点的左子树 -- 右左


三、AVL树的插入

在AVL树中插入结点(key,value)的算法:

1. 如果是空树,插入后即为根节点,插入后直接返回true
2. 如果树不空,寻找插入位置,若在寻找的过程中找到key,则插入失败直接返回false
3. 插入结点
4. 更新平衡因子,对树进行调整
新节点pcur平衡因子为0,但其双亲结点parent的平衡因子有三种情况:
1、如果parent的平衡因子为0
即在parent较矮的子树上插入新节点,parent平衡,其高度没有增加,此时从parent到
根路径上各结点为根的子树的高度不变,即各结点的平衡因子不变,结束平衡化处理。
2、如果parent的平衡因子的绝对值为1;
插入前parent的平衡因子为0,插入后以parent为根的子树没有失去平衡,但该子树
的高度增加,需从parent向根节点方向回溯,继续查看parent的双亲的平衡性。
3、在上述2更新后,如果parent平衡因子的绝对值为2,新节点在较高的子树插入,需要
做平衡化处理:
若parent->_bf == 2,说明右子树高,设parent的右子树为subR
当subR的平衡因子为1,执行左单旋转
当subR的平衡因子为-1,执行先右后左双旋转
若parent->_bf == -2,说明左子树高,设parent的左子树为subL
当subL的平衡因子为-1,执行右单旋转
当subL的平衡因子为1,执行先左后右双旋转
旋转后parent为根的子树高度降低,无需继续向上层回溯


四、AVL树的删除

从AVL树中删除一个节点,首先必须检测该结点是否存在,若存在删除该结点之后可能会破坏AVL树的高度平衡,因此需要做平衡化旋转。
被删除的结点pcur存在以下情况:
1、被删除结点只有左孩子
2、被删除结点只有右孩子
3、被删除结点左右孩子都存在-->变为删除中序遍历下的第一个结点q

更新parent的平衡因子,若q是parent的左孩子,则parent的平衡因子增加1,否则减少1,根据修改后的parent的平衡因子调整到根路径上的所有节点:
1、parent平衡因子的平衡因子为1或-1,parent高度不变,则从parent到根所有节点高度均不变,不用调整。
2、parent的平衡因子变成0,虽然以parent为根的子树平衡,其高度减1,但需要检查parent的双亲结点的平衡性。
3、结点parent的平衡因子为2或-2,则较矮子树被缩短,parent发生不平衡,需要进行平
衡化旋转。

令parent较高子树的根为q,根据q的平衡因子,分一下三种情况
a、如果q的平衡因子为0,执行单旋转恢复parent
b、如果q的平衡因子与parent平衡因子(正负)号相同,则执行一个单旋转恢复parent
c、如果q的平衡因子与parent平衡因子(正负)号相反,则执行一个双旋转恢复parent

五、完整代码

对AVL树的删除没有做具体实现。

#include<iostream>
using namespace std;

template<class K, class V>
struct AVLTreeNode
{
	AVLTreeNode()
	: _left(NULL)
	, _right(NULL)
	, _parent(NULL)
	, _bf(0)
	{}
	AVLTreeNode(K key, V value)
		: _left(NULL)
		, _right(NULL)
		, _parent(NULL)
		, _bf(0)
		, _key(key)
		, _value(value)
	{}
	struct AVLTreeNode<K,V>* _left;
	struct AVLTreeNode<K,V>* _right;
	struct AVLTreeNode<K,V>* _parent;
	K _key;
	V _value;
	int _bf;
};
template<class K,class V>
class AVLTree
{
	typedef AVLTreeNode<K,V> Node;
	typedef Node* pNode;
public:
	AVLTree()
		:_pRoot(NULL)
	{}
 	AVLTree(const K* arr, size_t size)
	{
		for (size_t i = 0; i < size; ++i)
		{
 			_Insert(_pRoot, arr[i], i);
		}
	}
	void Inorder()
	{
		_Inorder(_pRoot);
	}
	bool IsBalance()
	{
		return _IsBalance(_pRoot);
	}
	int Height()
	{
		return _Height(_pRoot);
	}
private:
	bool _Insert(pNode &pRoot, const K& key, const V& value)
	{
		if (pRoot == NULL)
		{
			pRoot = new Node(key, value);
			return true;
		}
		//找插入位置
		pNode pCur = pRoot;
		pNode parent = NULL;
		while (pCur)
		{
			parent = pCur;
			if (pCur->_key > key)
				pCur = pCur->_left;
			else if (pCur->_key < key)
				pCur = pCur->_right;
			else
				return false;
		}
		//插入节点
		pCur = new Node(key, value);
		if (parent->_key > key)
		{
			parent->_left = pCur;
			pCur->_parent = parent;
			
			
		}
		else
		{
			parent->_right = pCur;
			pCur->_parent = parent;
			
		}
		while (parent)
		{
			if (parent->_left == pCur)
				parent->_bf--;
			else
				parent->_bf++;
			if (parent->_bf == 0)
				break;
			else if (parent->_bf == 1 || parent->_bf == -1)
			{
				if (parent->_parent)
				{
					pCur = parent;
					parent = parent->_parent;
				}
				else
					break;
			}
			else
			{
				pNode parentR = parent->_right;
				pNode parentL = parent->_left;
				if (parent->_bf == -2)
				{
					if (pCur->_bf == -1)
						//右单旋
						RotateR(parent);
					else if (pCur->_bf == 1)
						//左右双旋
						RotateLR(parent);
				}
				if (parent->_bf == 2)
				{
					if (pCur->_bf == -1)
						RotateRL(parent);
					//右左双旋
					else if (pCur->_bf == 1)
						RotateL(parent);
					//左单旋
				}
				else
					break;
				if (parent->_parent)
				{
					pCur = parent;
					parent = parent->_parent;
				}
			}

		}
		return true;
	}
	bool _IsBalance(pNode pRoot)//判断一个树是否为平衡树
	{
		if (pRoot == NULL)
			return true;
		int RHeight = _Height(pRoot->_right);
		int LHeight = _Height(pRoot->_left);
		if ((RHeight - LHeight) < 2 && (RHeight - LHeight) > -2)
		{
			_IsBalance(pRoot->_left);
			_IsBalance(pRoot->_right);
		}
		else
			return false;
		return true;
	}
	int _Height(pNode &pRoot)//求树的高度
	{
		if (pRoot == NULL)
			return 0;
		return (_Height(pRoot->_left) > _Height(pRoot->_right))?_Height(pRoot->_left):_Height(pRoot->_right) + 1;
	}
	void RotateL(pNode &pRoot)//左单旋
	{
		pNode pRootR = pRoot->_right;
		pNode pRootRL = pRootR->_left;
		pRoot->_right = pRootRL;
		if (pRootRL)
			pRootRL->_parent = pRoot;
		pNode pparent = pRoot->_parent;
		pRootR->_parent = pparent;
		pRoot->_parent = pRootR;
		pRootR->_left = pRoot;

		if (pRoot != _pRoot)
		{
			if (pparent->_left == pRoot)
				pparent->_left = pRootR;
			else
				pparent->_right = pRootR;
		}
		else
			_pRoot = pRootR;
		pRoot->_bf = pRootR->_bf = 0;
	}
	void RotateR(pNode &pRoot)//右单旋
	{
		pNode pRootL = pRoot->_left;
		pNode pRootLR = pRootL->_right;
		pRoot->_left = pRootLR;
		if (pRootLR)
			pRootLR->_parent = pRoot;
		pRootL->_right = pRoot;
		pNode pparent = pRoot->_parent;
		pRootL->_parent = pparent;
		pRoot->_parent = pRootL;

		if (pRoot != _pRoot)
		{
			if (pparent->_left == pRoot)
				pparent->_left = pRootL;
			else
				pparent->_right = pRootL;
		}
		else
			_pRoot = pRootL;
		pRoot->_bf = pRootL->_bf = 0;
	}
	void RotateRL(pNode &pRoot)//右左双旋
	{
		pNode pRootR = pRoot->_right;
		pNode pRootRL = NULL;
		if (pRootR)
			pRootRL = pRootR->_left;

		RotateR(pRootR);
		RotateL(pRoot);

		if (pRootRL->_bf == 1)
			pRoot->_bf = -1;
		else if (pRootRL->_bf == -1)
			pRoot->_bf = 0;
	}
	void RotateLR(pNode &pRoot)//左右双旋
	{
		pNode pRootL = pRoot->_left;
		pNode pRootLR = NULL;
		if (pRootL)
			pRootLR = pRootL->_right;
		RotateL(pRootL);
		RotateR(pRoot);
		if (pRootLR->_bf == 1)
			pRoot->_bf = 0;
		else if (pRootLR->_bf == -1)
			pRoot->_bf = 1;
	}
	void _Inorder(pNode pRoot)
	{
		if (pRoot)
		{
			_Inorder(pRoot->_left);
			cout << pRoot->_key << "   " << pRoot->_value << endl;
			_Inorder(pRoot->_right);
		}
	}
	pNode _pRoot;
};
int  main()
{
	int arr[] = {16, 3, 7, 11, 9, 26, 18, 14, 15};
	AVLTree<int, int> AVL(arr, 9);
	AVL.Inorder();
	if (AVL.IsBalance())
		cout << "IsBanlanceTree" << endl;
	else
		cout << "NotIsBanlanceTree" << endl;
	cout << "树的高度为" << AVL.Height() << endl;
	return 0;
}
以下为运行结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值