【C++】AVL树

发布于:2025-05-07 ⋅ 阅读:(15) ⋅ 点赞:(0)

  大家都愿意盲从,好像世界上最安全的事就是让自己消失在多数之中。 

前言

  这是我自己学习C++的第十五篇博客总结。后期我会继续把C++学习笔记开源至博客上。

  上一期笔记是关于C++的set和map知识,没看的同学可以过去看看:

【C++】map与set-CSDN博客https://blog.csdn.net/hsy1603914691/article/details/147123187

AVL树的概念

1. AVL树是一种 自平衡二叉搜索树,具有以下性质:
  • 空树性质一棵AVL树可以是空树
  • 递归性质:如果非空,则AVL树满足以下条件:
    1. 左右子树均为AVL树
    2. 左右子树的高度差(即平衡因子)的绝对值不超过1

2. AVL树需要引入一个平衡因子的概念,每个结点都有一个平衡因子,任何结点的平衡因子等于右子树的高度减去左子树的高度,也就是说任何结点的平衡因子等于01-1

3. AVL树整体结点数量和分布与完全二叉树类似,高度可以控制在log(N),那么增删查改的效率也可以控制在log(N),相比二叉搜索树有了本质的提升。

AVL树的插入 

整体的插入规则 

1. 先按 二叉搜索树规则 进行插入。
2.  新增结点只会影响祖先结点的高度 ,也就是可能会影响部分祖先结点的平衡因子。所以 需要更新从新增结点到根结点路径上的平衡因子 ,实际中最坏情况下要更新到根,有些情况更新到中间就可以停止了。
3.  更新平衡因子过程中没有出现问题,则插入结束。
4.  更新平衡因子过程中出现不平衡 对不平衡子树旋转 。旋转后,本质调平衡的同时,本质降低了子树的高度,不会再影响上一层,所以插入结束。

平衡因子更新原则 

1. 平衡因子 = 右子树高度 - 左子树高度
2. 只有 子树高度变化 才会影响当前结点的平衡因子。
3. 插入结点 会增加高度 。当新增结点在 parent的右子树 parent的平衡因子++ ;当新增结点在 parent的左子树 parent平衡因子--
bool insert(const K& x, const V& y)
{
	Node* cur = _root;
	Node* parent = nullptr;
	if (_root == nullptr)
	{
		_root = new Node(x, y);
		return true;
	}
	else
	{
		while (cur != nullptr)
		{
			if (cur->_key < x)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->_key > x)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return false;//不允许有重复
			}
		}
	}
	cur = new Node(x, y);
	if (parent->_key < cur->_key)
	{
		parent->_right = cur;
	}
	else
	{
		parent->_left = cur;
	}
	cur->_parent = parent;
	//更新平衡因子
	while (parent)
	{
		if (cur == parent->left)
		{
			parent->bf--;
		}
		else if (cur == parent->right)
		{
			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)
		{
			//需要进行旋转调整
            ...
		}
		else
		{
			assert(false);
		}
	}
	return true;
}

旋转原则

1. 保持二叉搜索树性质的前提下让旋转的树从不平衡变平衡

3. 旋转总共分为四种, 左单旋 右单旋 左右双旋 右左双旋

右单旋

void Rotate_Right(Node* parent)
{
	Node* ppNode = parent->_parent;
	Node* sub_left = parent->_left;
	Node* subl_right = sub_left->_right;

	sub_left->_right=parent;
	parent->_parent = sub_left;
	parent->_left = subl_right;
	if (subl_right)
	{
		subl_right->_parent = parent;
	}
	if (ppNode==nullptr)
	{
		_root = sub_left;
		sub_left->_parent = nullptr;
	}
	else
	{
		if (ppNode->_left == parent)
		{
			ppNode->_left = sub_left;
		}
		else
		{
			ppNode->_right = sub_left;
		}
	}
}

左单旋

void Rotate_Left(Node* parent)
{
	Node* ppNode = parent->_parent;
	Node* sub_right = parent->_right;
	Node* subr_left = sub_right->_left;

	sub_right->_left = parent;
	parent->_parent = sub_right;
	parent->_right = subr_left;
	if (subr_left)
	{
		subr_left->_parent = parent;
	}
	if (ppNode == nullptr)
	{
		_root = sub_right;
		sub_right->_parent = nullptr;
	}
	else
	{
		if (ppNode->_left == parent)
		{
			ppNode->_left = sub_right;
		}
		else
		{
			ppNode->_right = sub_right;
		}
	}
}

左右双旋

void Rotate_Left_Right(Node* parent)
{
	Node* sub_left = parent->_left;
	Node* subl_right = sub_left->_right;
	int bf=subl_right->_bf;

	Rotate_Left(sub_left);
	Rotate_Right(parent);

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

右左双旋

void Rotate_Right_Left(Node* parent)
{
	Node* sub_right = parent->_right;
	Node* subr_left = sub_right->_left;
	int bf = subr_left->_bf;

	Rotate_Right(sub_right);
	Rotate_Left(parent);

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

插入的整体代码

bool insert(const K& x, const V& y)
{
	Node* cur = _root;
	Node* parent = nullptr;
	if (_root == nullptr)
	{
		_root = new Node(x, y);
		return true;
	}
	else
	{
		while (cur != nullptr)
		{
			if (cur->_key < x)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->_key > x)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return false;//不允许有重复
			}
		}
	}
	cur = new Node(x, y);
	if (parent->_key < cur->_key)
	{
		parent->_right = cur;
	}
	else
	{
		parent->_left = cur;
	}
	cur->_parent = parent;
	//更新平衡因子
	while (parent)
	{
		if (cur == parent->_left)
		{
			parent->_bf--;
		}
		else if (cur == parent->_right)
		{
			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 && parent->_left->_bf == -1)
			{
				Rotate_Right(parent);
				break;
			}
			else if (parent->_bf == 2 && parent->_right->_bf == 1)
			{
				Rotate_Left(parent);
				break;
			}
			else if (parent->_bf == -2 && parent->_left->_bf == 1)
			{
				Rotate_Left_Right(parent);
				break;
			}
			else if (parent->_bf == 2 && parent->_right->_bf == -1)
			{
				Rotate_Right_Left(parent);
				break;
			}
			else
			{
				assert(false);
			}
		}
		else
		{
			assert(false);
		}
	}
	return true;
}
void Rotate_Right(Node* parent)
{
	Node* ppNode = parent->_parent;
	Node* sub_left = parent->_left;
	Node* subl_right = sub_left->_right;

	sub_left->_right=parent;
	parent->_parent = sub_left;
	parent->_left = subl_right;
	if (subl_right)
	{
		subl_right->_parent = parent;
	}
	if (ppNode==nullptr)
	{
		_root = sub_left;
		sub_left->_parent = nullptr;
	}
	else
	{
		if (ppNode->_left == parent)
		{
			ppNode->_left = sub_left;
		}
		else
		{
			ppNode->_right = sub_left;
		}
	}
}
void Rotate_Left(Node* parent)
{
	Node* ppNode = parent->_parent;
	Node* sub_right = parent->_right;
	Node* subr_left = sub_right->_left;

	sub_right->_left = parent;
	parent->_parent = sub_right;
	parent->_right = subr_left;
	if (subr_left)
	{
		subr_left->_parent = parent;
	}
	if (ppNode == nullptr)
	{
		_root = sub_right;
		sub_right->_parent = nullptr;
	}
	else
	{
		if (ppNode->_left == parent)
		{
			ppNode->_left = sub_right;
		}
		else
		{
			ppNode->_right = sub_right;
		}
	}
}
void Rotate_Left_Right(Node* parent)
{
	Node* sub_left = parent->_left;
	Node* subl_right = sub_left->_right;
	int bf=subl_right->_bf;

	Rotate_Left(sub_left);
	Rotate_Right(parent);

	if (bf == 0)
	{
		parent->_bf = 0;
		sub_left->_bf = 0;
		subl_right->_bf = 0;
	}
	else if (bf == 1)
	{
		parent->_bf = 0;
		sub_left->_bf = -1;
		subl_right->_bf = 0;
	}
	else if (bf == -1)
	{
		parent->_bf = 1;
		sub_left->_bf = 0;
		subl_right->_bf = 0;
	}
	else
	{
		assert(false);
	}
}
void Rotate_Right_Left(Node* parent)
{
	Node* sub_right = parent->_right;
	Node* subr_left = sub_right->_left;
	int bf = subr_left->_bf;

	Rotate_Right(sub_right);
	Rotate_Left(parent);

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

AVL树的遍历

public:
    void InOrder()
    {
	    _InOrder(_root);
    }

private:
    void _InOrder(Node* root)
    {
	    if (root == nullptr)
	    {
		    return;
	    }
	    else
	    {
		    _InOrder(root->_left);
		    cout << root->_key << " " << root->_val << endl;
		    _InOrder(root->_right);
	    }
    }

AVL树的检验

public:
    bool IsAVLTree(Node* root)
    {
	    if (root == nullptr)
	    {
		    return true;
	    }
	    int left_height = _Height(root->_left);
	    int right_height = _Height(root->_right);
	    int diff = right_height - left_height;
	    if (abs(diff) >= 2)
	    {
		    cout << "高度差异常" << " " << root->_key;
		    return false;
	    }
	    if (diff != root->_bf)
	    {
		    cout << "平衡因子异常" << " " << root->_key;
		    return false;
	    }
	    return IsAVLTree(root->_left) && IsAVLTree(root->_right);//从中间节点向左右两边递归
    }
private:
    int _Height(Node* root)
    {
	    if (root == nullptr)
	    {
	    	return 0;
	    }
	    int left_Height = _Height(root->_left);
	    int right_Height = _Height(root->_right);
	    return left_Height > right_Height ? left_Height + 1 : right_Height + 1;
    }

AVL树整体代码

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cassert>
using namespace std;

template <class K,class V>
struct AVLTNode
{
	typedef AVLTNode<K, V> Node;

	K _key;
	V _val;
	Node* _left;
	Node* _right;
	Node* _parent;
	int _bf; 

	AVLTNode(const K& key,const V& val)
		: _key(key)
		, _val(val)
		, _left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		, _bf(0)
	{}
};

template<class K, class V>
class AVLTree
{
	typedef AVLTNode<K, V> Node;
	typedef AVLTree<K, V> Tree;

public:

	AVLTree()
		:_root(nullptr)
	{}

	bool insert(const K& x, const V& y)
	{
		Node* cur = _root;
		Node* parent = nullptr;
		if (_root == nullptr)
		{
			_root = new Node(x,y);
			return true;
		}
		else
		{
			while (cur != nullptr)
			{
				if (cur->_key < x)
				{
					parent = cur;
					cur = cur->_right;
				}
				else if (cur->_key > x)
				{
					parent = cur;
					cur = cur->_left;
				}
				else
				{
					return false;//不允许有重复
				}
			}
		}
		cur = new Node(x, y);
		if (parent->_key < cur->_key)
		{
			parent->_right = cur;
		}
		else
		{
			parent->_left = cur;
		}
		cur->_parent = parent;
		//更新平衡因子
		while (parent)
		{
			if (cur == parent->_left)
			{
				parent->_bf--;
			}
			else if (cur == parent->_right)
			{
				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 && parent->_left->_bf == -1)
				{
					Rotate_Right(parent);
					break;
				}
				else if (parent->_bf == 2 && parent->_right->_bf == 1)
				{
					Rotate_Left(parent);
					break;
				}
				else if (parent->_bf == -2 && parent->_left->_bf == 1)
				{
					Rotate_Left_Right(parent);
					break;
				}
				else if (parent->_bf == 2 && parent->_right->_bf == -1)
				{
					Rotate_Right_Left(parent);
					break;
				}
				else
				{
					assert(false);
				}
			}
			else
			{
				assert(false);
			}
		}
		return true;
	}

	Node* Find(const K& x)
	{
		Node* cur = _root;
		while (cur != nullptr)
		{
			if (cur->_key < x)
			{
				cur = cur->_right;
			}
			else if (cur->_key > x)
			{
				cur = cur->_left;
			}
			else
			{
				return cur;
			}
		}
		return nullptr;
	}

	void InOrder()
	{
		_InOrder(_root);
	}

	bool IsAVLTree(Node* root)
	{
		if (root == nullptr)
		{
			return true;
		}
		int left_height = _Height(root->_left);
		int right_height = _Height(root->_right);
		int diff = right_height - left_height;
		if (abs(diff) >= 2)
		{
			cout << "高度差异常" << " " << root->_key;
			return false;
		}
		if (diff != root->_bf)
		{
			cout << "平衡因子异常" << " " << root->_key;
			return false;
		}
		return IsAVLTree(root->_left) && IsAVLTree(root->_right);//从中间节点向左右两边递归
	}
	
private:

	void _InOrder(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}
		else
		{
			_InOrder(root->_left);
			cout << root->_key << " " << root->_val << endl;
			_InOrder(root->_right);
		}
	}

	void Rotate_Right(Node* parent)
	{
		Node* ppNode = parent->_parent;
		Node* sub_left = parent->_left;
		Node* subl_right = sub_left->_right;

		sub_left->_right = parent;
		parent->_parent = sub_left;
		parent->_left = subl_right;
		if (subl_right)
		{
			subl_right->_parent = parent;
		}
		if (ppNode == nullptr)
		{
			_root = sub_left;
			sub_left->_parent = nullptr;
		}
		else
		{
			if (ppNode->_left == parent)
			{
				ppNode->_left = sub_left;
			}
			else
			{
				ppNode->_right = sub_left;
			}
		}
	}

	void Rotate_Left(Node* parent)
	{
		Node* ppNode = parent->_parent;
		Node* sub_right = parent->_right;
		Node* subr_left = sub_right->_left;

		sub_right->_left = parent;
		parent->_parent = sub_right;
		parent->_right = subr_left;
		if (subr_left)
		{
			subr_left->_parent = parent;
		}
		if (ppNode == nullptr)
		{
			_root = sub_right;
			sub_right->_parent = nullptr;
		}
		else
		{
			if (ppNode->_left == parent)
			{
				ppNode->_left = sub_right;
			}
			else
			{
				ppNode->_right = sub_right;
			}
		}
	}

	void Rotate_Left_Right(Node* parent)
	{
		Node* sub_left = parent->_left;
		Node* subl_right = sub_left->_right;
		int bf = subl_right->_bf;

		Rotate_Left(sub_left);
		Rotate_Right(parent);

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

	void Rotate_Right_Left(Node* parent)
	{
		Node* sub_right = parent->_right;
		Node* subr_left = sub_right->_left;
		int bf = subr_left->_bf;

		Rotate_Right(sub_right);
		Rotate_Left(parent);

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

	int _Height(Node* root)
	{
		if (root == nullptr)
		{
			return 0;
		}
		int left_Height = _Height(root->_left);
		int right_Height = _Height(root->_right);
		return left_Height > right_Height ? left_Height + 1 : right_Height + 1;//子树的高度等于左右子树高度的最大值加1。
	}

	Node* _root;
};
int main()
{
	AVLTree<int, string> a1;
	a1.insert(1, "苹果");
	a1.insert(2, "西瓜");
	a1.insert(3, "菠萝");
	a1.insert(8, "车厘子");
	a1.insert(4, "樱桃");
	a1.insert(5, "梨子");
	a1.insert(6, "香蕉");
	a1.insert(7, "哈密瓜");
	a1.InOrder();
	auto it = a1.Find(5);
	if (a1.Find(5))
	{
		cout << it->_key << "->" << it->_val;
	}
	return 0;
}

致谢

  感谢您花时间阅读这篇文章!如果您对本文有任何疑问、建议或是想要分享您的看法,请不要犹豫,在评论区留下您的宝贵意见。每一次互动都是我前进的动力,您的支持是我最大的鼓励。期待与您的交流,让我们共同成长,探索技术世界的无限可能! 


网站公告

今日签到

点亮在社区的每一天
去签到