C++实现AVL树

时间:2024-04-14 22:03:03

文章目录

    • 一、平衡树的优势
    • 二、二叉平衡搜索树的节点定义
    • 三、二叉搜索树的插入
      • 3.1 寻找插入位置
      • 3.2 开始判定平衡因子,平衡因子有变就开始旋转
        • 3.2.1 左旋的情况
        • 3.2.2 左旋代码(一定要考虑平衡因子为2或者-2的节点是否有父节点)
        • 3.2.2 右旋的情况
        • 3.2.3 左右双旋的情况(细分为3种情况)
          • 3.2.3.1 以下为例3的左子树为h时
          • 3.2.3.2 以下为例3的右子树为h时
          • 3.2.3.3 如果3的右子树为空时
          • 3.2.3.4 代码演示
        • 3.2.4 右左双旋的情况(一样细分三种情况)
    • 四、平衡树的检验(是否平衡)
      • 4.1 先从高度方面检验
      • 4.2 再看树的节点个树
      • 4.3 最后看树的平衡因子
    • 五、全部源码

在这里插入图片描述


先赞后看,养成习惯!!!^ _ ^<3 ❤️ ❤️ ❤️
码字不易,大家的支持就是我坚持下去的动力。点赞后不要忘了关注我哦!
所属专栏:C++进阶

在这里插入图片描述

一、平衡树的优势

经过了解二叉搜索树的性质之后,我们也发现了它极大的缺陷,如果数字基本上都是趋于有序的情况下,那么查找效率非常低下,时间复杂度为O(n),与顺序表的查找一样,因此我们引出了二叉平衡搜索树(AVL树),该树的优势在于能够保证根节点左右子树的高度差的绝对值小于等于1,这就很好保证了查找效率O(logn),如下图就是二叉平衡搜索树的样子。
在这里插入图片描述

二、二叉平衡搜索树的节点定义

由于二叉平衡搜索树需要对节点进行旋转,我们这里引入了父节点的指针,还有平衡因子(保证节点处于平衡状态)
在这里插入图片描述

三、二叉搜索树的插入

3.1 寻找插入位置

首先插入顺序还是和二叉搜索树大差不差,有区别的位置是需要判断平衡因子是否大于1,大于1就要开始旋转了(这里就略过,需要看具体操作可以看二叉搜索树那一章)
在这里插入图片描述

3.2 开始判定平衡因子,平衡因子有变就开始旋转

3.2.1 左旋的情况

在这里插入图片描述

在这里插入图片描述

3.2.2 左旋代码(一定要考虑平衡因子为2或者-2的节点是否有父节点)

在这里插入图片描述

3.2.2 右旋的情况

在这里插入图片描述
在这里插入图片描述

3.2.3 左右双旋的情况(细分为3种情况)
3.2.3.1 以下为例3的左子树为h时

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
一定要注意平衡因子的变化

3.2.3.2 以下为例3的右子树为h时

在这里插入图片描述
在这里插入图片描述

3.2.3.3 如果3的右子树为空时

那么平衡因子都为0,其他变化都是一样的

3.2.3.4 代码演示

在这里插入图片描述

3.2.4 右左双旋的情况(一样细分三种情况)

下面只讲解一种情况其他都是一样的就是平衡因子发生改变

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、平衡树的检验(是否平衡)

4.1 先从高度方面检验

在这里插入图片描述

4.2 再看树的节点个树

在这里插入图片描述

4.3 最后看树的平衡因子

在这里插入图片描述

五、全部源码

#pragma once
#include<iostream>
#include<vector>
#include<assert.h>
//#include <utility> 
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->_right;
			}
			else if (cur->_kv.first > 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 (parent)
		{
			if (cur == parent->_left)
			{
				parent->_bf--;//左为减
			}
			else
			{
				parent->_bf++;
			}

			if (parent->_bf == 1 || parent->_bf == -1)
			{
				cur = cur->_parent;
				parent = parent->_parent;
			}
			else if (parent->_bf == 2 || parent->_bf == -2)
			{
				if (parent->_bf == 2 && cur->_bf == 1)
				{
					RotateL(parent);
				}
				else if (parent->_bf == -2 && cur->_bf == -1)
				{
					RotateR(parent);
				}
				else if (parent->_bf == -2 && cur->_bf == 1)
				{
					RotateLR(parent);
				}
				else
				{
					RotateRL(parent);
				}
				break;
			}
		}
		return true;
	}

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

		if (subRL)
			subRL->_parent = parent;

		parent->_right = subRL;
		Node* pp = parent->_parent;
		subR->_left = parent;

		if (pp == nullptr)
		{
			parent->_parent = subR;
			_root = subR;
			subR->_parent = nullptr;
		}
		else
		{
			if (pp->_left == parent)
			{
				parent->_parent = subR;
				subR->_parent = pp;
				pp->_left = subR;
			}
			else if (pp->_right == parent)
			{
				parent->_parent = subR;
				pp->_right = subR;
				subR->_parent = pp;
			}
			else
			{
				assert(false);
			}
		}
		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* pp = parent->_parent;
		subL->_right = parent;

		if (pp == nullptr)
		{
			_root = subL;
			subL->_parent = nullptr;
		}
		else
		{
			if (pp->_left == parent)
			{
				parent->_parent = subL;
				subL->_parent = pp->_left;
			}
			else if (pp->_right = parent)
			{
				parent->_parent = subL;
				subL->_parent = pp->_right;
			}
			else
			{
				assert(false);
			}
		}
		parent->_bf = subL->_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 = -1;
			subLR->_bf = 0;
			subL->_bf = 0;
		}
		else if (bf == 1)
		{
			parent->_bf = 0;
			subLR->_bf = 0;
			subL->_bf = 1;
		}
		else if (bf == 0)
		{
			parent->_bf = subLR->_bf = subL->_bf = 0;
		}
		else
		{
			assert(false);
		}
	}

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

		int bf = subRL->_bf;

		RotateR(subR);
		RotateL(parent);

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

	void _Inorder()
	{
		Inorder(_root);
	}

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

		Inorder(root->_left);
		cout << root->_kv.first << endl;
		Inorder(root->_right);
	}

	Node* Find(const pair<K,V> kv)
	{
		Node* cur = _root;
		while (cur)
		{
			if (cur->_kv.first > kv.first)
			{
				cur = cur->_left;
			}
			else if (cur->_kv.first < kv.first)
			{
				cur = cur->_right;
			}
			else
			{
				return cur;
			}
		}
		return nullptr;
	}

	size_t _Height()//树的高度
	{
		return Height(_root);
	}

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

		int leftHeight = Height(root->_left);
		int rightHeight = Height(root->_right);
		return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
	}

	//数的节点个树
	size_t _Size()
	{
		return Size(_root);
	}

	size_t Size(Node* root)
	{
		if (root == nullptr)
			return 0;

		return Size(root->left) + Size(root->right) + 1;
	}

	//判断树是否平衡
	bool _Isbalance()
	{
		return Isbalance(_root);
	}



	bool Isbalance(Node* root)
	{
		if (root == nullptr)
			return false;

		int leftHeight = Height(root->_left);
		int rightHeight = Height(root->_right);
		return abs(leftHeight - rightHeight) < 2
			&& Isbalance(root->_left) && Isbalance(root->_right);//检查完当前树的高度
		//然后就检查当前树的左子树和右子树是否符合要求
	}

private:
	Node* _root = nullptr;

};

在这里插入图片描述