C++模拟实现AVL树

AVL树的概念

  • 一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:
    • 它的左右子树都是AVL树
    • 左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)

AVL树的插入

AVL树就是在二叉搜索树的基础上引入了平衡因子,AVL树的插入过程可以分为两步:

  1. 按照二叉搜索树的方式插入新节点
  2. 调整节点的平衡因子

AVL树的旋转

如果在一棵原本是平衡的AVL树中插入一个新节点,可能造成不平衡,此时必须调整树的结构,使之平衡化。根据节点插入位置的不同,AVL树的旋转分为四种:

  • 新节点插入较高左子树的左侧—左左:右单旋
    在这里插入图片描述
  • 新节点插入较高右子树的右侧—右右:左单旋
    在这里插入图片描述
  • 新节点插入较高左子树的右侧—左右:先左单旋再右单旋
    在这里插入图片描述
  • 新节点插入较高右子树的左侧—右左:先右单旋再左单旋
    在这里插入图片描述
  • 旋转完成后,原pParent为根的子树个高度降低到插入之前的高度,已经平衡,因此不需要再向上更新。

AVL树的验证

  1. 验证其为二叉搜索树
    如果中序遍历可得到一个有序的序列,就说明为二叉搜索树
  2. 验证其为平衡树
    • 每个节点子树高度差的绝对值不超过1
    • 节点的平衡因子是否计算正确

AVLTree.hpp

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

template<class T>
struct AVLTreeNode
{
	AVLTreeNode(const T& data)
		: _pLeft(nullptr), _pRight(nullptr), _pParent(nullptr)
		, _data(data), _bf(0)
	{}
	AVLTreeNode<T>* _pLeft; 
	AVLTreeNode<T>* _pRight; 
	AVLTreeNode<T>* _pParent; 
	T _data;
	int _bf; 
};

template<class T>
class AVLTree {
	typedef AVLTreeNode<T>* PNode;
	typedef AVLTreeNode<T> Node;
public:
	AVLTree()
		:_Root(nullptr) 
	{}
	~AVLTree() {
		stack<PNode> arr;
		PNode node = _Root;
		while (!arr.empty() || node) {
			while (node) {
				arr.push(node);
				node = node->_pLeft;
			}
			PNode del = arr.top();
			arr.pop();
			node = del->_pRight;
			delete del;
		}
	}
	bool Insert(const T& data){
		if (!_Root) {
			_Root = new Node(data);
			return true;
		}
		PNode pParent=nullptr;
		PNode pCur = _Root;
		while (pCur) {
			pParent = pCur;
			if (data < pCur->_data)
				pCur = pCur->_pLeft;
			else if (data > pCur->_data)
				pCur = pCur->_pRight;
			else
				return false;
		}
		pCur = new Node(data);
		if (data < pParent->_data) {
			pParent->_pLeft = pCur;
			pCur->_pParent = pParent;
		}
		else {
			pParent->_pRight = pCur;
			pCur->_pParent = pParent;
		}
		while (pParent) {
			if (pParent->_pLeft == pCur) {
				--pParent->_bf;
			}
			else {
				++pParent->_bf;
			}
			if (pParent->_bf == 0)
				break;
			if (pParent->_bf > 1 || pParent->_bf < -1) {
				if (pParent->_bf == 2) {
					if (pParent->_pRight->_bf == 1) {//左旋
						RotateL(pParent);
					}
					else {//右左旋
						RotateRL(pParent);
					}
				}
				else {
					if (pParent->_pLeft->_bf == -1) {//右旋
						RotateR(pParent);
					}
					else {//左右旋
						RotateLR(pParent);
					}
				}
				break;
			}
			pCur = pParent;
			pParent = pParent->_pParent;
		}
		return true;
	}
	PNode Find(const T& data) {
		PNode ptr = _Root;
		while (ptr) {
			if (data < ptr->_data)
				ptr = ptr->_pLeft;
			else if (data > ptr->_data)
				ptr = ptr->_pRight;
			else
				return ptr;
		}
		return nullptr;
	}
	//bool DelNode(const T& data);
	bool IsBalanceTree() {
		return IsAVLTree(_Root);
	}
	void Show() {
		stack<PNode> arr;
		PNode node = _Root;
		while (!arr.empty() || node) {
			while (node) {
				arr.push(node);
				node = node->_pLeft;
			}
			node = arr.top();
			arr.pop();
			cout << node->_data << " ";
			node = node->_pRight;
		}
		cout << endl;
	}
private:
	void RotateL(PNode pParent) {
		pParent->_bf = pParent->_pRight->_bf = 0;
		PNode pPParent = pParent->_pParent;
		PNode pRight = pParent->_pRight;
		pParent->_pRight = pRight->_pLeft;
		if (pRight->_pLeft)
			pRight->_pLeft->_pParent = pParent;
		pRight->_pLeft = pParent;
		pParent->_pParent = pRight;
		if (!pPParent) {
			_Root = pRight;
			pRight->_pParent = nullptr;
		}
		else {
			if (pPParent->_pLeft == pParent) {
				pPParent->_pLeft = pRight;
				pRight->_pParent = pPParent;
			}
			else {
				pPParent->_pRight = pRight;
				pRight->_pParent = pPParent;
			}
		}
	}
	void RotateR(PNode pParent) {
		pParent->_bf = pParent->_pLeft->_bf = 0;
		PNode pPParent = pParent->_pParent;
		PNode pLeft = pParent->_pLeft;
		pParent->_pLeft = pLeft->_pRight;
		if (pLeft->_pRight)
			pLeft->_pRight->_pParent = pParent;
		pLeft->_pRight = pParent;
		pParent->_pParent = pLeft;
		if (!pPParent) {
			_Root = pLeft;
			pLeft->_pParent = nullptr;
		}
		else {
			if (pPParent->_pLeft == pParent) {
				pPParent->_pLeft = pLeft;
				pLeft->_pParent = pPParent;
			}
			else {
				pPParent->_pRight = pLeft;
				pLeft->_pParent = pPParent;
			}
		}
	}
	void RotateLR(PNode pParent) {
		PNode pLeft = pParent->_pLeft;
		PNode pLeftR = pLeft->_pRight;
		int bf = pLeftR->_bf;
		RotateL(pParent->_pLeft);
		RotateR(pParent);
		if (1 == bf)               //最难最难的是这里的判断     花了好久才想到
			pLeft->_bf = -1;
		else if (-1 == bf)
			pParent->_bf = 1;
	}
	void RotateRL(PNode pParent) {
		PNode pRight = pParent->_pRight;
		PNode pRightL = pRight->_pLeft;
		int bf = pRightL->_bf;
		RotateR(pParent->_pRight);
		RotateL(pParent);
		if (1 == bf)
			pParent->_bf = -1;
		else if (-1 == bf)
			pRight->_bf = 1;
	}
	int Height(PNode pRoot) {
		if (!pRoot)
			return 0;
		vector<PNode> v1;
		vector<PNode> v2;
		int count = 1;
		v1.push_back(pRoot);
		while (1) {
			for (size_t i = 0; i < v1.size(); ++i) {
				if (v1[i]->_pLeft)
					v2.push_back(v1[i]->_pLeft);
				else if (v1[i]->_pRight)
					v2.push_back(v1[i]->_pRight);
			}
			v1 = v2;
			v2.clear();
			if (!v1.empty())
				++count;
			else
				break;
		}
		return count;
	}
	bool IsAVLTree(PNode pRoot) {
		if (!pRoot)
			return true;
		int left = Height(pRoot->_pLeft);
		int right = Height(pRoot->_pRight);
		if (right - left < -1 || right - left>1 || pRoot->_bf != right - left)
			return false;
		return IsAVLTree(pRoot->_pLeft) && IsAVLTree(pRoot->_pRight);
	}
	PNode _Root;
};

main.cpp

#include"AVLTree.hpp"
using namespace std;

void testAVLTree() {
	AVLTree<int> tree_a, tree_b;
	vector<int> a{ 16,3,7,11,9,26,18,14,15 };
	vector<int> b{ 4,2,6,1,3,5,15,7,16,14 };
	for (size_t i = 0; i < a.size(); ++i)
	{
		tree_a.Insert(a[i]);
	}
	for (size_t i = 0; i < b.size(); ++i)
	{
		tree_b.Insert(b[i]);
	}
	cout << tree_a.IsBalanceTree() << endl << tree_b.IsBalanceTree() << endl;
	cout << tree_a.Find(7)->_data << endl << tree_b.Find(15)->_data << endl;
	tree_a.Show();
	tree_b.Show();
}
int main() {
	testAVLTree();
	_CrtDumpMemoryLeaks();
	system("pause");
	return 0;
}
发布了161 篇原创文章 · 获赞 52 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_42837885/article/details/103866413