C++(map/multimap/set/multiset)底層實現---AVL樹

       二叉搜索樹雖然可以縮短查找的效率,但如果數據有序或接近有序二叉搜索樹將退化爲單支樹,查找元素相當於在順序表中搜索元素,效率低下

      當向二叉搜索樹中插入新結點後,如果能保證每個結點的左右子樹高度之 差的絕對值不超過1(需要對樹中的結點進行調整),即可降低樹的高度,從而減少平均搜索長度。

一棵AVL樹或者是空樹,或者是具有以下性質的二叉搜索樹

  • 它的左右子樹都是AVL樹
  • 左右子樹高度之差(簡稱平衡因子)的絕對值不能超過1(-1/0/1)

                                           

 

AVL樹節點的定義

template <class T>
struct AVLTreeNode
{
	AVLTreeNode(const T& val = T())
	:_left(nullptr)
	, _right(nullptr)
	, _parent(nullptr)
	, _data(val)
	, _bf(0)
	{}

	AVLNode<T>* _left;
	AVLNode<T>* _right;
	AVLNode<T>* _parent;

	T _data;
	int _bf;
};

 

與二叉搜索樹一樣插入元素

if (_root == nullptr)
		{
			_root = new Node(val);
			return true;
		}

		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			if (val > cur->_data)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (val < cur->_data)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
				return false;
		}

		cur = new Node(val);
		if (parent->_data>cur->_data)
			parent->_left = cur;
		else
			parent->_right = cur;
		cur->_parent = parent;

調節平衡因子

while (parent)
		{
			//更新平衡因子
			if (parent->_left == cur)
				--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 || parent->_bf == 2)
			{
				//旋轉
				if (parent->_bf == -2 && cur->_bf == -1)
				{
					//右旋
					RotateR(parent);
				}
				else if (parent->_bf == 2 && cur->_bf == 1)
				{
					//左旋
					RotateL(parent);
				}
				else if (parent->_bf == 2 && cur->_bf == -1)
				{
					Node* subR = parent->_right;
					Node* subRL = subR->_left;
					int bf = subRL->_bf;
					RotateR(subR);
					RotateL(parent);

					if (bf == -1)
					{
						parent->_bf = 0;
						subR->_bf = 1;
					}
					else if (bf == 1)
					{
						parent->_bf = -1;
						subR->_bf = 0;
					}
				}
				else if (parent->_bf == -2 && cur->_bf == 1)
				{
					RotateL(cur);
					RotateR(parent);
				}
				break;
			}

左旋情況

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

		subR->_left = parent;
		parent->_right = subRL;

		if (subRL)
			subRL->_parent = parent;
		if (parent != _root)
		{
			Node* gParent = parent->_parent;
			if (gParent->_left == parent)
				gParent->_left = subR;
			else
				gParent->_right = subR;
			subR->_parent = gParent;
		}
		else
		{
			subR->_parent = nullptr;
			_root = subR;
		}
		parent->_parent = subR;
		subR->_bf = parent->_bf = 0;
	}

右旋情況

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

		//單向鏈接 subL , parent, subLR
		subL->_right = parent;
		parent->_left = subLR;

		//向上鏈接subLR
		if (subLR)
			subLR->_parent = parent;

		//subL,parent->parent 雙向鏈接
		if (parent != _root)
		{
			Node* gParent = parent->_parent;
			if (gParent->_left == parent)
				gParent->_left = subL;
			else
				gParent->_right = subL;
			subL->_parent = gParent;
		}
		else
		{
			_root = subL;
			subL->_parent = nullptr;
		}


		//向上鏈接parent, subL
		parent->_parent = subL;

		//更新平衡因子
		subL->_bf = parent->_bf = 0;
	}

判斷是否平衡

//判斷是否平衡
	bool IsBalance()
	{
		return _IsBalance(_root);
	}
bool _IsBalance(Node* root)
	{
		if (root == nullptr)
			return true;
		int left = Height(root->_left);
		int right = Height(root->_right);

		if (root->_bf != right - left)
		{
			cout << "節點:" << root->_data << "異常" << endl;
			return false;
		}
		return abs(root->_bf) < 2 && _IsBalance(root->_left)
			&& _IsBalance(root->_right);
	}

深度判斷

int Height(Node* root)
	{
		if (root == nullptr)
			return 0;
		int left = Height(root->_left);
		int right = Height(root->_right);
		return left > right ? left + 1 : right + 1;
	}

代碼整合

#include <iostream>
#include <stdlib.h>

using namespace std;

template <class T>
struct AVLNode
{
	AVLNode(const T& val = T())
	:_left(nullptr)
	, _right(nullptr)
	, _parent(nullptr)
	, _data(val)
	, _bf(0)
	{}
	AVLNode<T>* _left;
	AVLNode<T>* _right;
	AVLNode<T>* _parent;

	T _data;
	int _bf;
};

template <class T>
class AVLTree
{
public:
	typedef AVLNode<T> Node;

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

		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			if (val > cur->_data)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (val < cur->_data)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
				return false;
		}

		cur = new Node(val);
		if (parent->_data>cur->_data)
			parent->_left = cur;
		else
			parent->_right = cur;
		cur->_parent = parent;

		//調平衡
		while (parent)
		{
			//更新平衡因子
			if (parent->_left == cur)
				--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 || parent->_bf == 2)
			{
				//旋轉
				if (parent->_bf == -2 && cur->_bf == -1)
				{
					//右旋
					RotateR(parent);
				}
				else if (parent->_bf == 2 && cur->_bf == 1)
				{
					//左旋
					RotateL(parent);
				}
				else if (parent->_bf == 2 && cur->_bf == -1)
				{
					Node* subR = parent->_right;
					Node* subRL = subR->_left;
					int bf = subRL->_bf;
					RotateR(subR);
					RotateL(parent);

					if (bf == -1)
					{
						parent->_bf = 0;
						subR->_bf = 1;
					}
					else if (bf == 1)
					{
						parent->_bf = -1;
						subR->_bf = 0;
					}
				}
				else if (parent->_bf == -2 && cur->_bf == 1)
				{
					RotateL(cur);
					RotateR(parent);
				}
				break;
			}
		}
		return true;
	}

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

		subR->_left = parent;
		parent->_right = subRL;

		if (subRL)
			subRL->_parent = parent;
		if (parent != _root)
		{
			Node* gParent = parent->_parent;
			if (gParent->_left == parent)
				gParent->_left = subR;
			else
				gParent->_right = subR;
			subR->_parent = gParent;
		}
		else
		{
			subR->_parent = nullptr;
			_root = subR;
		}
		parent->_parent = subR;
		subR->_bf = parent->_bf = 0;
	}

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

		//單向鏈接 subL , parent, subLR
		subL->_right = parent;
		parent->_left = subLR;

		//向上鏈接subLR
		if (subLR)
			subLR->_parent = parent;

		//subL,parent->parent 雙向鏈接
		if (parent != _root)
		{
			Node* gParent = parent->_parent;
			if (gParent->_left == parent)
				gParent->_left = subL;
			else
				gParent->_right = subL;
			subL->_parent = gParent;
		}
		else
		{
			_root = subL;
			subL->_parent = nullptr;
		}


		//向上鏈接parent, subL
		parent->_parent = subL;

		//更新平衡因子
		subL->_bf = parent->_bf = 0;
	}

	//判斷是否平衡
	bool IsBalance()
	{
		return _IsBalance(_root);
	}

	void InOrdre()
	{
		_Inorder(_root);
		cout << endl;
	}

	void _Inorder(Node* root)
	{
		if (root)
		{
			_Inorder(root->_left);
			cout << root->_data << " ";
			_Inorder(root->_right);
		}
	}
	
	int Height(Node* root)
	{
		if (root == nullptr)
			return 0;
		int left = Height(root->_left);
		int right = Height(root->_right);
		return left > right ? left + 1 : right + 1; 
	}

	bool _IsBalance(Node* root)
	{
		if (root == nullptr)
			return true;
		int left = Height(root->_left);
		int right = Height(root->_right);

		if (root->_bf != right - left)
		{
			cout << "節點:" << root->_data << "異常" << endl;
			return false;
		}
		return abs(root->_bf) < 2 && _IsBalance(root->_left)
			&& _IsBalance(root->_right);
	}
private:
	Node* _root = nullptr;
};

int main()
{
	AVLTree<int> avlt;
	int arr[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
	for (const auto& e : arr)
	{
		avlt.Insert(e);
		cout << avlt.IsBalance() << endl;
	}
	avlt.InOrdre();
	cout << avlt.IsBalance() << endl;

	system("pause");
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章