AVL树基本操作

一、AVL树的节点平衡旋转

AVL是绝对的平衡树,增删查都可以达到log(n)
在这里插入图片描述

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

二、AVL树插入删除代码实现

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;

template<typename T>
class AVLTree
{
public:
	AVLTree()
		:_root(nullptr){}
	~AVLTree(){}
	//AVL插入操作接口
	void insert(const T &val)
	{
		_root = insert(_root, val);
	}
	//AVL删除操作接口
	void remove(const T& val)
	{
		_root = remove(_root, val);
	}
private:
	//定义AVL树节点类型
	struct Node
	{
		Node(T data = T())
			:_data(data),
			_left(nullptr),
			_right(nullptr),
			_height(1)
		{}
		int _data;
		Node* _left;
		Node* _right;
		int _height;
	};
	Node* _root;

	//返回节点高度值
	int height(Node* node)
	{
		return node == nullptr ? 0 : node->_height;
	}

	//右旋操作,以参数node为轴做右旋转操作,并把新的根节点返回
	Node* rightRotate(Node* node)
	{
		//节点旋转
		Node* child = node->_left;
		node->_left = child->_right;
		child->_right = node;
		//高度更新
		node->_height = max(height(node->_left), height(node->_right)) + 1;
		child->_height = max(height(child->_left), height(child->_right)) + 1;
		return child;
	}
	//左旋操作,以参数node为轴做左旋转操作,并把新的根节点返回
	Node* leftRotate(Node* node)
	{
		Node* child = node->_right;
		node->_right = child->_left;
		child->_left = node;

		node->_height = max(height(node->_left), height(node->_right)) + 1;
		child->_height = max(height(child->_left), height(child->_right)) + 1;
		return child;
	}

	//左平衡操作,以参数node为轴做左-右旋转操作,并把新的根节点返回
	Node* leftBalance(Node* node)
	{
		node->_left = leftRotate(node->_left);
		return rightRotate(node);
	}
	//右平衡操作,以参数node为轴做右-左旋转操作,并把新的根节点返回
	Node* rightBalance(Node* node)
	{
		node->_right = leftRotate(node->_right);
		return leftRotate(node);
	}
	//AVL插入操作实现
	Node* insert(Node* node, const T& val)
	{
		//递归结束,找到插入位置
		if (node == nullptr)
		{
			return new Node(val);
		}
		if (node->_data > val)
		{
			node->_left = insert(node->_left, val);
			//添加1 在递归回溯是判断节点是否失衡,node的左子树太高,node失衡了
			if (height(node->_left) - height(node->_right) > 1)
			{
				if (height(node->_left->_left) >= height(node->_left->_right))
				{
					//节点失衡,由于左孩子的左子树太高
					node = rightRotate(node);
				}
				else
				{
					//节点失衡,由于左孩子的右子树太高
					node = leftBalance(node);
				}
			}
		}
		else if (node->_data < val)
		{
			node->_right = insert(node->_right, val);
			//添加2 在递归回溯是判断节点是否失衡,node的右子树太高,
			if (height(node->_right) - height(node->_left) > 1)
			{
				if (height(node->_right->_right) >= height(node->_right->_left))
				{
					//节点失衡,由于右孩子的右子树太高
					node = leftRotate(node);
				}
				else
				{
					//节点失衡,由于右孩子的左子树太高
					node = rightBalance(node);
				}
			}
		}
		else
		{
			//找到相同节点了,不用再往下递归了,直接向上回溯
			return node;
		}
		//添加3 因为子树中增加了新的节点,在递归回溯时检测更新节点高度
		node->_height = max(height(node->_left), height(node->_right)) + 1;
		return node;
	}
	Node* remove(Node* node, const T& val)
	{
		if (node == nullptr)
		{
			return nullptr;
		}
		if (node->_data > val)
		{
			node->_left = remove(node->_left, val);
			//左子树删除节点,会造成右子树偏高
			if (height(node->_right) - height(node->_left) > 1)
			{
				//右孩子的右子树太高
				if (height(node->_right->_right) >= height(node->_right->_left))
				{
					node = leftRotate(node);
				}
				//右孩子的左子树太高
				else
				{
					node = rightBalance(node);
				}
			}
		}
		else if (node->_data < val)
		{
			node->_right = remove(node->_right, val);
			//右子树删除节点,会造成左子树偏高
			if (height(node->_left) - height(node->_right) > 1)
			{
				//左孩子的左子树太高
				if (height(node->_left->_left) >= height(node->_left->_right))
				{
					node = rightRotate(node);
				}
				//左孩子的右子树太高
				else
				{
					node = leftBalance(node);
				}
			}
		}
		else
		{
			//找到了,先处理有两个孩子的节点删除情况
			if (node->_left != nullptr && node->_right != nullptr)
			{
				//为了避免删除前驱或者后继节点造成节点失衡,谁高删谁
				if (height(node->_left) >= height(node->_right))
				{
					//删前驱
					Node* pre = node->_left;
					while (pre->_right != nullptr)
					{
						pre = pre->_right;
					}
					node->_data = pre->_data;
					node->_left = remove(node->_left, pre->_data);
				}
				else
				{
					//删后继
					Node* post = node->_right;
					while (post->_left != nullptr)
					{
						post = post->_left;
					}
					node->_data = post->_data;
					node->_right = remove(node->_right, post->_data);
				}
			}
			else
			{
				Node* child = node->_left;
				if (node->_right != nullptr)
				{
					child = node->_right;
				}
				delete node;
				return child;
			}
		}
		node->_height = max(height(node->_left), height(node->_right)) + 1;
		return node;
	}
};
int main()
{
	AVLTree<int> avl;
	for (int i = 1; i <= 10; i++)
	{
		avl.insert(i);
	}
	avl.remove(10);
	avl.remove(9);
	avl.remove(6);
	avl.remove(1);
	avl.remove(2);
	avl.remove(3);
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值