二叉树——AVL

AVL二叉树的基本概念:

AVL树又称为高度平衡的二叉搜索树,他既能保持二叉树的高度平衡,尽量降低二叉树的高度,又能减少树的平均搜索长度。

AVL树的性质:

1,左子树和右子树的高度之差的绝对值不超过一。2,树中的每个左子树和右子树都是AVL树。3,每个节点都有一个平衡因子,每个平衡因子的值等于右子树的高度减去左子树的高度并且平衡因子的值只能有三个值:1,-1,0。

AVL树的失衡与重平衡:

AVL树和常规的二叉树一样都支持插入,删除等动态修改操作,但是经过这些操作后,原有的平衡会被破坏掉(即有的平衡因子的绝对值大于1),节点的高度也有可能会发生变化,所以不再满足AVL树的平衡条件,如图所示:


如果把上面的AVL树的节点v去掉后节点r的平衡因子-1变成了-2。如果在节点k的下面再创建子节点m,那么节点n的平衡因子也从-1变成了-2,如下图所示:


那如何使AVL树重新平衡呢?有四种方法,分别是左旋转、右旋转、左右旋转和右左旋转。如图分析所示:


实现代码之前我们先来看如何插入一个数:

我们分三种情况,1,没有节点,2,只有一个节点,3,有一个以上的节点

我们来实现插入一个数并且重新建立平衡的代码:

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
template <class K,class V>
struct AVLtreeNode
{
	K _key;
	V _value;
	AVLtreeNode <K,V>*_left;
	AVLtreeNode <K, V>*_right;
	AVLtreeNode<K, V>*_parent;
	int _bf;
	AVLtreeNode(const K& key, const V& value)
		:_key(key)
		, _value(value)
		, _left(NULL)
		, _right(NULL)
		, _parent(NULL)
		, _bf(0)
	{}
};
template <class K,class V>
class AVLtree
{
	typedef AVLtreeNode <K, V>Node;
public:
	AVLtree()
		:_root(NULL)
	{}
	Node* Find(const K& key);
	bool Remove(const K& key);
	bool Insert(const K& key, const V& value)//插入一个数
	{
		if (_root == NULL)//没有节点
		{
			_root = new Node(key, value);
			return true;
		}
			Node* parent = NULL;//只有一个节点
			Node* cur = _root;
			while (cur)
	//判断插入的这个数是放在什么位置,但是注意插入一个数后会破会他的平衡,所以还需要重置平衡
			{
				if (cur->_key < key)
				{
					parent = cur;
					cur = cur->_right;
				}
				else if (cur->_key > key)
				{
					parent = cur;
					cur = cur->_left;
				}
				else
				{
					return false;
				}
			}
			cur = new Node(key, value);//有一个以上的节点
			if (parent->_key < key)
			{
				parent->_right = cur;
				cur->_parent = parent;
			}
			else
			{
				parent->_left = cur;
				cur->_parent = parent;
			}
			while (parent)//重置平衡因子
			{
				if (cur = parent->_right)
				{
					parent->_bf += 1;
				}
				else
				{
					parent->_bf -= 1;
				}
				if (parent->_bf == 0)
				{
					break;
				}
				else if (parent->_bf == 1 || parent->_bf == -1)
				{
					cur = parent;
					parent = cur->_parent;
				}
				else if (parent->_bf == 2 || parent->_bf == -2)
				//else if (abs(parent->_bf)==2)
				{
					//不平衡,需要重置平衡
					if (parent->_bf == 2)
					{
						if (cur->_bf == 1)
						{
							//需要进行左旋转
							RotateL(parent);
						}
						else 
						{
							//需要进行右左旋转
							RotateRL(parent);
						}
					}
					else
					{
						if (cur->_bf == -1)
						{
							RotateR(parent);
						}
						else
						{
							RotateLR(parent);
						}
					}
					break;
				}
				else
				{
					assert(false);
				}
			}
			return true;
	}
	void RotateL(Node* parent)//左移
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
		parent->_right = subRL;
		if (subRL)
		{
			subRL->_parent = parent;
		}
		subR->_left = parent;
		Node* ppNode = parent->_parent;
		parent->_parent = subR;
		if (parent = _root)//也就是说ppNode为空
		{
			_root = subR;
			_root->_parent = NULL;
		}
		else
		{
			if (ppNode->_left == parent)
			{
				ppNode->_left = subR;
			}
			else
			{
				ppNode->_right = subR;
			}
			subR->_parent = ppNode;
		}
		subR->_bf = parent->_bf = 0;
	}
	void RotateR(Node* parent)//右移
	{
		Node* subL = parent->_left;
		Node* subLR = parent->_right;
		parent->_left = subLR;
		if (subLR)
		{
			subLR->_parent = parent;
		}
		subL->_right = parent;
		parent->_parent = subL;
		Node* ppNode = parent->_parent;
		if (ppNode == NULL)
		{
			_root = subL;
			subL->_parent = NULL;
		}
		else
		{
			if (ppNode->_left = parent)
			{
				ppNode->_left = subL;
			}
			else 
			{
				ppNode->_right = subL;
			}
			subL->_parent = ppNode;
		}
		subL->_bf = parent->_bf = 0;
	}
	void RotateRL(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
		int bf = subRL->_bf;

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

		if (bf == 0)
		{
			subRL->_bf = parent->_bf = subR->_bf = 0;
		}
		else if (bf == 1)
		{
			subR->_bf = 0;
			parent->_bf = -1;
			subRL->_bf = 0;
		}
		else
		{
			parent->_bf = 0;
			subR->_bf = 1;
			subRL->_bf = 0;
		}
	}

	void RotateLR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;
		int bf = subLR->_bf;

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

		if (bf == 0)
		{
			parent->_bf = subLR->_bf = subL->_bf = 0;
		}
		else if (bf == -1)
		{
			subL->_bf = 0;
			parent->_bf = 1;
			subLR->_bf = 0;
		}
		else
		{
			parent->_bf = 0;
			subL->_bf = -1;
			subLR->_bf = 0;
		}
	}

	void InOrder()
	{
		_InOrder(_root);
		cout << endl;
	}

	void _InOrder(Node* root)
	{
		if (root == NULL)
		{
			return;
		}

		_InOrder(root->_left);
		cout << root->_key << " ";
		_InOrder(root->_right);
	}

	bool IsBalance()
	{
		return _IsBalance(_root);
	}

	int Height(Node* root)
	{
		if (root == NULL)
		{
			return 0;
		}

		int left = Height(root->_left);
		int right = Height(root->_right);
		return left > right ? left + 1 : right + 1;
	}
	// O(N*N)
	// 优化O(N)
	bool _IsBalance(Node* root)
	{
		if (root == NULL)
			return true;

		int bf = Height(root->_right) - Height(root->_left);

		if (root->_bf != bf)
		{
			cout << root->_key << "平衡因子异常" << endl;
			return false;
		}

		return abs(bf) < 2
			&& _IsBalance(root->_left)
			&& _IsBalance(root->_right);
	}
protected:
	Node *_root;

};
void TestAVLTree()
{
	AVLtree<int, int> t1;
	
	int a[] = {4, 2, 6, 1, 3, 5, 15, 7, 16, 14};
	for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
	{
		
		cout<<a[i]<<"IsBalance?"<<t1.IsBalance()<<endl;
	}
	t1.InOrder();
	cout << "IsBalance?" << t1.IsBalance() << endl;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值