AVL树的模拟实现

AVL树的模拟实现,第1张

AVL树的模拟实现

二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。因此,两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。
我们采用三叉链的方式来实现AVL首先我们定义的AVLTreeNode节点如下所示:

template
struct AVLTreeNode
{
	AVLTreeNode* _left;
	AVLTreeNode* _right;
	AVLTreeNode* _parent;

	int _bf;
	pair _kv;

	AVLTreeNode(const pair& kv)
		:_left(nullptr),
		_right(nullptr),
		_parent(nullptr),
		_bf(0),
		_kv(kv)
	{
	}

};

首先对于AVL树来说,我们这里实现AVLTree的插入实现:当AVL树插入数据时,可以分为以下四种情况 右单旋、左单旋、右左单旋、左右单旋,为了方便记忆我们可以将左、右单旋看成一条直线、右左和左右单旋看成折线。如下所示:

程序实现:

#include
#include
using namespace std;

template
struct AVLTreeNode
{
	AVLTreeNode* _left;
	AVLTreeNode* _right;
	AVLTreeNode* _parent;

	int _bf;
	pair _kv;

	AVLTreeNode(const pair& kv)
		:_left(nullptr),
		_right(nullptr),
		_parent(nullptr),
		_bf(0),
		_kv(kv)
	{
	}

};

template
class AVLTree
{
	typedef AVLTreeNode Node;
public:
	AVLTree():_root(nullptr)
	{
	}

	void _Destory(Node* root)
	{
		if (root == nullptr)
			return;

		_Destory(root->_left);
		_Destory(root->_right);

		delete root;
	}

	~AVLTree()
	{
		_Destory(_root);
		_root = nullptr;
	}

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

		_InOrder(root->_left);
		cout << root->_kv.first << " ";
		_InOrder(root->_right);

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

	bool Insert(const pair& kv)
	{
		if (_root == nullptr)
		{
			_root = new Node(kv);
			return true;
		}

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

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

		cur = new Node(kv);

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

		cur->_parent = parent;

		//开始平衡因子的检测 到这从插入的节点往上对平衡因子进行更新

		while (cur != _root)
		{
			if (parent->_right == cur)
			{
				parent->_bf++;
			}
			else
			{
				parent->_bf--;
			}

			//对更新完后的父亲节点进行检测 分为三种情况
			//1、如果parent节点的_bf为0 则跳出
			//2、如果parent节点的平衡因子为1或者-1则继续向上更新
			//3、如果Parent的节点的平衡因子为-2或者2则不平衡了,应该旋转了
			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)
			{
				//这里开始旋转保持AVLTree的平衡
				//旋转分为四种情况
				//1、 右单旋 
				//2、右左单旋
				//3、左单旋
				//4、左右单旋


				//首先要进行右单选时,那么parent->bf==-2时进行右旋
				if (parent->_bf == -2)
				{
					if (cur->_bf == -1)
					{
						//这里是右单旋
						RotateR(parent);
					}
					else //cur->bf==1 左右双旋转
					{
						RotateLR(parent);
					}
				}
				else //cur->bf==2
				{
					if (cur->_bf == 1)
					{
						RotateL(parent);
					}
					else
					{
						RotateRL(parent);
					}

				}
				break;
			}
			
		}


		return true;
	}

	void RotateR(Node* parent)
	{
		
		Node* SubL = parent->_left;
		Node* SubLR = SubL->_right;

		parent->_left = SubLR;
		if (SubLR)
		{
			SubLR->_parent = parent;
		}

		Node* Parentparent = parent->_parent;
		SubL->_right = parent;
		parent->_parent = SubL;

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

			SubL->_parent = Parentparent;
		}

		SubL->_bf = parent->_bf = 0;

	}
	void RotateL(Node* parent)
	{
		Node* SubR = parent->_right;
	
		Node* SubRL = SubR->_left;
		parent->_right = SubRL;
		if (SubRL)
		{
			SubRL->_parent = parent;
		}

		SubR->_left = parent;
		Node* Parentparent = parent->_parent;

		if (parent == _root)
		{
			_root = SubR;
			SubR->_parent = nullptr;
		}
		else
		{
			if (Parentparent->_left == parent)
			{
				Parentparent->_left = SubR;

			}
			else
			{
				Parentparent->_right = SubR;
			}
			SubR->_parent = Parentparent;
		}

		parent->_bf = SubR->_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 == 1)
		{
			SubL->_bf = -1;
			parent->_bf = 0;
			SubLR->_bf = 0;
		}
		else if (bf == -1)
		{
			SubL->_bf = 0;
			parent->_bf = 1;
			SubLR->_bf = 0;
		}
		else
		{
			SubL->_bf = 0;
			parent->_bf = 0;
			SubLR->_bf = 0;
		}
	}
	void RotateRL(Node* parent)
	{
		Node* SubR = parent->_right;
		Node* SubRL = SubR->_left;
		int bf = SubR->_bf;

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

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

	Node* Find(const K& key)
	{

		Node* cur = _root;
		while (cur)
		{
			if (cur->_kv.first < key)
			{
				cur = cur->_right;
			}
			else if (cur->_kv.first > key)
			{
				cur = cur->_left;
			}
			else
			{
				return cur;
			}
		}

		return nullptr;
	}

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

		int Left=IsHeight(root->_left);
		int Right=IsHeight(root->_right);

		return Left > Right ? Left + 1 : Right + 1;
	}
	bool _IsBalance(Node* root)
	{
		int left = IsHeight(root->_left);
		int right = IsHeight(root->_right);

		return abs(left - right) < 2;

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

private:
	Node* _root;
};
#include"AVLTree.h"
using namespace std;

void Test_AVLTree()
{
	//int a[] = { 1, 3, 5, 7, 6 };
	//int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
	//int a[] = { 6,7,8,9,10};
	int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
	AVLTreet;

	for (auto e : a)
	{
		t.Insert(make_pair(e,e));
	}

	t.InOrder();
}

int main()
{
	Test_AVLTree();
	return 0;
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5699378.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存