平衡搜索二叉树~AVL树

作为搜索结构,二叉搜索树有其高效的搜索效率,但是同时也有着其本质的缺陷,就是在数据呈现顺序的时候,效率低下,因此不适合大多数的数据存储,但是如果将其修改,成为一个平衡树,结合两者特点,就可以完成高效的查找,因此我们学习平衡搜索二叉树~AVL树

AVL树的特点是,左子树和右子树的高度差不超过一,也就是说,左右子树的高度最多差一,并且要保证所有的子树都满足这个条件,因此分部均匀,且具有相对优秀的效率。

插入和删除都是二叉搜索树的方式,但是在这之后,需要进行平衡的旋转工作,因此我们一般是随着节点往上走来调节平衡,所以结构一般使用三叉链的结构,来寻找上一个节点,或者可以使用栈保留顺序,来进行反向寻找,两种方式都可以,下面我们使用第一种方式来写代码。

首先我们要明白,AVL树是如何保持平衡的,是利用一个叫平衡因子的数据,平衡因子是右子树高度减去左子树高度,用平衡因子来衡量需不需要旋转,以及一些信息。

插入:我们明白插入一定只能影响一条路径上的高度,首先要明白,左节点插入,balance factor 一定是减一的,而右边是加一的。

那么分为三种情况
如果说更新后,bf为0那么一定是将矮的那边补齐,因此高度不变对上层不影响。
如果更新后,bf为-1或1,那么一定是相等的高度增加了,因此对上层有影响,向上调整。
如果更新后bf为2或-2,那么已经不平衡了,因此进行旋转。

旋转分成四种情况,左单旋,右单旋,左右双旋,右左双旋。

在这里插入图片描述

在这里插入图片描述

删除的话则和插入相反,右边删除,bf–,左边删除,bf++,删除后,如果bf为0,则说明高度变了,因为高度是长的那个,因此,如果变成1或者-1,说明本来是相等的,删了一个高度是不变的。

删除的情况是比较复杂,大方向分为2和-2两种情况,它们是一样的,只是旋转的方向不一样,因为删除的话,一定是兄弟节点变高了,所以我们首先要寻找兄弟节点的bf为多少,进行讨论

bf为2:

假设兄弟节点b 的bf为0,则直接左单旋,就直接平衡。

假设兄弟节点的b 的bf为1,则左单旋,但是向上迁移,因为高度总体低了1
前两种的旋转过后,bf都是0

在这里插入图片描述
如果是兄弟节点的bf为-1,则进行双旋,一定是它的subL,左子树高,那么对左子树的bf进行讨论,双旋后有三种不同的bf调节方式。

第一种subL的bf为0,旋转后,b和p的节点bf都为0

第二种subL的bf为1,旋转后,p的bf为-1,b为0

第三种subL的bf为-1,旋转后,p的bf为0,b为1

在这里插入图片描述
在这里插入图片描述
然后向上迁移,总体高度减一。

bf为-2的情况与之一样,只是旋转方向变化。

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

template<class K,class V>
struct AVLTreeNode
{
	AVLTreeNode<K, V>* _left;
	AVLTreeNode<K, V>* _right;
	AVLTreeNode<K, V>* _parent;

	int _bf;//平衡因子

	pair<K, V> _kv;

	AVLTreeNode(const pair<K,V>& kv)
		:_left(nullptr)
		,_right(nullptr)
		,_parent(nullptr)
		,_bf(0)
		,_kv(kv)
	{}
};


template<class K, class V>
class AVLTree
{
	typedef AVLTreeNode<K, V> Node;
public:
	bool insert(const pair<K, V>& kv)
	{
		if (_root == nullptr)
		{
			_root = new Node(kv);
			return true;
		}

		Node* parent = nullptr;
		Node* cur = _root;

		while (cur)
		{
			if (cur->_kv.first > kv.first)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_kv.first < kv.first)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				return false;
			}
		}

		cur = new Node(kv);
		if (parent->_kv.first > kv.first)
		{
			parent->_left = cur;
			cur->_parent = parent;

		}
		else
		{
			parent->_right = cur;
			cur->_parent = parent;
		}


		while (parent)
		{
			if (cur == parent->_left)
				parent->_bf--;
			else
				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)
				{
					if (cur->_bf == 1)
					{
						RotateL(parent);
					}
					else
					{
						RotateRL(parent);
					}
				}
				else
				{
					if (cur->_bf == -1)
					{
						RotateR(parent);
					}
					else
					{
						RotateLR(parent);
					}
				}

				break;
			}
		}
	}

	bool erase(const pair<K, V>& kv)
	{
		if (_root == nullptr)
			return false;

		Node* cur = _root;
		Node* parent = nullptr;
		int ex = 1;

		while (cur)
		{
			if (cur->_kv.first > kv.first)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_kv.first < kv.first)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				ex = 0;
				if (cur->_left == nullptr)
				{
					if (parent->_left == cur)
					{
						parent->_left = cur->_right;
					}
					else
					{
						parent->_right = cur->_right;
					}

					Node* del = cur;
					cur = cur->_right;

					delete del;
					break;
				}
				else if (cur->_right == nullptr)
				{
					if (parent->_left == cur)
					{
						parent->_left = cur->_left;
		
					}
					else
					{
						parent->_right = cur->_left;
					}

					Node* del = cur;
					cur = cur->_left;

					delete del;
					break;
				}
				else
				{
					Node* rightMinParent = cur;
					Node* rightMin = cur->_right;

					while (rightMin->_left)
					{
						rightMinParent = rightMin;
						rightMin = rightMin->_left;
					}

					cur->_kv = rightMin->_kv;

					if (rightMin == rightMinParent->_left)
					{
					rightMinParent->_left = rightMin->_right;
					}
					else
					{
					rightMinParent->_right = rightMin->_right;
					}

					parent = rightMinParent;
					cur = rightMin->_right;

					delete rightMin;
					break;
				}

			}

		}


		if (ex)
		{
			return false;
		}

		while (parent)
		{
			if (cur = parent->_left)
				parent->_bf++;
			else
				parent->_bf--;

			if (parent->_bf == 0)
			{
				cur = parent;
				parent = parent->_parent;
			}
			else if (parent->_bf == 1 || parent->_bf == -1)
			{
				break;
			}
			else
			{
				if (parent->_bf == 2)
				{
					Node* Brother = parent->_right;

					if (Brother->_bf == 0)
					{
						RotateL(parent);

						parent->_bf = 1;
						Brother->_bf = -1;
						break;
					}
					else if (Brother->_bf == 1)
					{
						RotateL(parent);

						parent->_bf = Brother->_bf = 0;

						cur = Brother;
						parent = cur->_parent;
					}
					else
					{
						Node* subL = Brother->_left;
						int bf = subL->_bf;

						RotateR(Brother);
						RotateL(parent);

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

						subL->_bf = 0;

						cur = subL;
						parent = subL->_parent;
					}
				}
				else
				{
					Node* Brother = parent->_left;

					if (Brother->_bf == 0)
					{
						RotateR(parent);

						Brother->_bf = 1;
						parent->_bf = -1;
					}
					else if (Brother->_bf == -1)
					{
						RotateR(parent);

						Brother->_bf = 0;
						parent->_bf = 0;

						cur = Brother;
						parent = cur->_parent;
					}
					else
					{
						Node* subR = Brother->_right;
						int bf = subR->_bf;

						RotateL(Brother);
						RotateR(parent);

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

						subR->_bf = 0;

						cur = subR;
						parent = cur->_parent;
					}

				}
			}

		}


		return true;
	}



	void RotateL(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;

		if (subRL)
			subRL->_parent = parent;
		parent->_right = subRL;
		Node* ppnode = parent->_parent;
		parent->_parent = subR;

		if (parent == _root)
		{
			_root = subR;
			subR->_left = parent;
			subR->_parent = nullptr;
		}
		else
		{
			subR->_parent = ppnode;
			subR->_left = parent;
			if (parent == ppnode->_left)
				ppnode->_left = subR;
			else
				ppnode->_right = subR;

		}

		parent->_bf = subR->_bf = 0;
	}

	void RotateR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;

		if(subLR)
		subLR->_parent = parent;
		parent->_left = subLR;
		Node* ppnode = parent->_parent;
		parent->_parent = subL;

		subL->_right = parent;

		if (_root = parent)
		{
			_root = subL;
			subL->_parent = nullptr;
		}
		else
		{
			if (ppnode->_left == parent)
				ppnode->_left = subL;
			else
				ppnode->_right = subL;

			subL->_parent = ppnode;
		}
		
		parent->_bf = subL->_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 == 1)
		{
			subR->_bf = 0;
			parent->_bf = -1;
			subRL->_bf = 0;
		}
		else if (bf == -1)
		{
			subR->_bf = 1;
			parent->_bf = 0;
			subRL->_bf = 0;
		}
		else if (bf == 0)
		{
			subR->_bf = 0;
			subR->_bf = 0;
			parent->_bf = 0;
		}
	}

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

		RotateL(subL);
		RotateR(parent);

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

		}

	}

	void _InOrder(Node* root)
	{
		if (root == nullptr)
			return;
		_InOrder(root->_left);

		cout << root->_kv.first << ":" << root->_kv.second << endl;

		_InOrder(root->_right);
	}

	void InOrder()
	{
		_InOrder(_root);
	}

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

		return max(Height(root->_left), Height(root->_right)) + 1;
	}

	bool _IsBalance(Node* root)
	{
		if (root == nullptr)
			return true;

		return abs(Height(root->_left) - Height(root->_right)) < 2
			&& _IsBalance(root->_left) && _IsBalance(root->_right);
	}

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

private:
	Node* _root = nullptr;
};

void test()
{
	int a[] = { 16,3,7,11,9,26,18,14,15 };
	AVLTree<int, int> t;
	for (auto e : a)
	{
		t.insert(make_pair(e, e));

	}

	t.InOrder();
	cout << t.IsBalance() << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值