AVL树

发现了一个avl树的在线动画https://www.cs.usfca.edu/~galles/visualization/AVLtree.html 

平衡树节点

#pragma once
//平衡树节点
template<typename T>
class AVLTreeNode {
public:
	//关键字
	T value;
	//左子树
	AVLTreeNode* left;
	//右子树
	AVLTreeNode* right;
	//高度
	int height;
	AVLTreeNode() :height(1), left(nullptr), right(nullptr) {}
	AVLTreeNode(const T &value) :value(value), height(1), left(nullptr), right(nullptr) {}
};

旋转

LL型(右旋)

template<typename T>
AVLTreeNode<T>* AVLTree<T>::LeftLeftRotation(AVLTreeNode<T>* rt)
{
	AVLTreeNode<T>* temp = rt->left;
	rt->left = temp->right;
	temp->right = rt;
	updateHeight(rt);
	updateHeight(temp);
	return temp;
}

 

RR型(左旋)

 

template<typename T>
AVLTreeNode<T>* AVLTree<T>::RightRightRotation(AVLTreeNode<T>* rt)
{
	AVLTreeNode<T>* temp = rt->right;
	rt->right = temp->left;
	temp->left = rt;
	updateHeight(rt);
	updateHeight(temp);
	return temp;
}

 

LR型

先对左子树RR旋转(左旋)

后对根LL旋转(右旋)

template<typename T>
AVLTreeNode<T>* AVLTree<T>::LeftRightRotation(AVLTreeNode<T>* rt)
{
	rt->left = RightRightRotation(rt->left);
	return LeftLeftRotation(rt);
}

 

RL型

先对右子树LL旋转(右旋)

后对根RR旋转(左旋)

template<typename T>
AVLTreeNode<T>* AVLTree<T>::RightLeftRotation(AVLTreeNode<T>* rt)
{
	rt->right = LeftLeftRotation(rt->right);
	return RightRightRotation(rt);
}

 

删除

左子树为空则用右子树代替

右子树为空则用左子树代替

否则如果左子树比右子树高或一样

则用左子树上的最大值替换,再删除左子树的最大值

如果右子树比左子树高 

则用右子树的最小值替换,再删除右子树的最小值

template<typename T>
AVLTreeNode<T>* AVLTree<T>::remove(AVLTreeNode<T>* rt, const T & value)
{
	if (rt == nullptr)return nullptr;
	//要删的节点在左子树
	if (value < rt->value) {
		rt->left = remove(rt->left, value);
		//失衡
		if (getHeight(rt->right) - getHeight(rt->left) == 2) {
			AVLTreeNode<T>* right = rt->right;
			//右子树的左子树失衡,进行RL旋转
			if (getHeight(right->left) > getHeight(right->right)) {
				rt = RightLeftRotation(rt);
			}
			//右子树的右子树失衡,进行RR旋转
			else {
				rt = RightRightRotation(rt);
			}
		}
	}
	//要删的节点在右子树
	else if (value > rt->value) {
		rt->right = remove(rt->right, value);
		//失衡
		if (getHeight(rt->left) - getHeight(rt->right) == 2) {
			AVLTreeNode<T>* left = rt->left;
			//左子树的左子树失衡,进行LL旋转
			if (getHeight(left->left) >= getHeight(left->right)) {
				rt = LeftLeftRotation(rt);
			}
			//左子树的右子树失衡,进行LR旋转
			else {
				rt = LeftRightRotation(rt);
			}
		}
	}
	//就删这
	else {
		//左子树或右子树是空的
		if (rt->left == nullptr || rt->right == nullptr) {
			AVLTreeNode<T>* removeNode = rt;
			if (rt->left == nullptr)rt = rt->right;
			else rt = rt->left;
			delete removeNode;
		}
		//左子树比右子树高或者一样高
		else if (getHeight(rt->left) >= getHeight(rt->right)) {
			AVLTreeNode<T>* maxNode = getMax(rt->left);
			rt->value = maxNode->value;
			rt->left = remove(rt->left, maxNode->value);
		}
		//右子树比左子树高
		else {
			AVLTreeNode<T>* minNode = getMin(rt->right);
			rt->value = minNode->value;
			rt->right = remove(rt->right, minNode->value);
		}
	}
	return rt;
}

 完整版

头文件AVLTree.h

#pragma once
#include "AVLTreeNode.h"

//平衡树
template<typename T>
class AVLTree {
private:
	AVLTreeNode<T>* root;
	/*
	更新以rt为根节点的树的高度
	@param rt 根节点
	*/
	void updateHeight(AVLTreeNode<T> * rt);
	/*
	获得以tree为根节点的树的高度
	@param tree 树
	*/
	int getHeight(AVLTreeNode<T>* tree) const;
	/*
	对以rt根节点的树进行右旋(LL旋转)
	@param rt 要旋转的树的根节点
	@return 旋转后的根节点
	*/
	AVLTreeNode<T>* LeftLeftRotation(AVLTreeNode<T>* rt);
	/*
	对以rt根节点的树进行左旋(RR旋转)
	@param rt 要旋转的树的根节点
	@return 旋转后的根节点
	*/
	AVLTreeNode<T>* RightRightRotation(AVLTreeNode<T>* rt);
	/*
	对以rt根节点的树的进行LR旋转
	先对rt的左子树做左旋(RR旋转),然后对rt进行右旋(LL旋转)
	@param rt 要旋转的树的根节点
	@return 旋转后的根节点
	*/
	AVLTreeNode<T>* LeftRightRotation(AVLTreeNode<T>* rt);
	/*
	对以rt根节点的树的进行RL旋转
	先对rt的右子树做右旋(LL旋转),然后对rt进行左旋(RR旋转)
	@param rt 要旋转的树的根节点
	@return 旋转后的根节点
	*/
	AVLTreeNode<T>* RightLeftRotation(AVLTreeNode<T>* rt);
	/*
	插入值为value的节点
	@param value 要插入的值
	@return 插入节点后的树
	*/
	/*
	对以rt为根节点的树插入值为value的节点
	@param rt 要插入的树
	@param value 要插入的值
	@return 插入节点后的树
	*/
	AVLTreeNode<T>* insert(AVLTreeNode<T>* rt, const T &value);
	/*
	对以rt为根节点的树删除值为value的节点
	@param rt 要删除的树
	@param value 要删除的值
	@return 删除节点后的树
	*/
	AVLTreeNode<T>* remove(AVLTreeNode<T>* rt, const T &value);
	/*
	对以rt为根节点的树寻找拥有最大值的节点
	@param rt 要找的树
	@return 包含最大值的节点
	*/
	AVLTreeNode<T>* getMax(AVLTreeNode<T>* rt);
	/*
	对以rt为根节点的树寻找拥有最小值的节点
	@param rt 要找的树
	@return 包含最小值的节点
	*/
	AVLTreeNode<T>* getMin(AVLTreeNode<T>* rt);
	/*
	对以rt为根节点的树进行销毁
	@param rt 要销毁的树
	*/
	void destory(AVLTreeNode<T>* rt);
	/*
	对以rt为根节点的树进行前序遍历
	@param rt 根节点
	*/
	void preOrder(AVLTreeNode<T>* rt) const;
	/*
	对以rt为根节点的树进行中序遍历
	@param rt 根节点
	*/
	void inOrder(AVLTreeNode<T>* rt) const;
	/*
	对以rt为根节点的树进行后序遍历
	@param rt 根节点
	*/
	void postOrder(AVLTreeNode<T>* rt) const;
	/*
	对以rt为根节点的树进行层遍历
	@param rt 根节点
	*/
	void layerOrder(AVLTreeNode<T>* rt) const;
	/*
	对以rt为根节点的树查找值为value的节点
	@param rt 根节点
	@param value 查找的值
	@return 包含value的节点
	*/
	AVLTreeNode<T>* search(AVLTreeNode<T>* rt, const T &value) const;
public:
	AVLTree();
	~AVLTree();
	//获得树的高度
	int getHeight() const;
	/*
	插入值为value的节点
	@param value 要插入的值
	*/
	void insert(const T &value);
	/*
	删除值为value的节点
	@param value 要删除的值
	*/
	void remove(const T &value);
	//前序遍历
	void preOrder() const;
	//中序遍历
	void inOrder() const;
	//后序遍历
	void postOrder() const;
	//层序遍历
	void layerOrder() const;
	/*
	查找值为value的节点
	@param value 查找的值
	@return 包含value的节点
	*/
	AVLTreeNode<T>* search(const T &value) const;
	//销毁树
	void destory();
};

cpp文件AVLTree.cpp

#include "AVLTree.h"
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
/*
对以rt为根节点的树删除值为value的节点
@param rt 要删除的树
@param value 要删除的值
@return 删除节点后的树
*/
template<typename T>
AVLTreeNode<T>* AVLTree<T>::remove(AVLTreeNode<T>* rt, const T & value)
{
	if (rt == nullptr)return nullptr;
	//要删的节点在左子树
	if (value < rt->value) {
		rt->left = remove(rt->left, value);
		//失衡
		if (getHeight(rt->right) - getHeight(rt->left) == 2) {
			AVLTreeNode<T>* right = rt->right;
			//右子树的左子树失衡,进行RL旋转
			if (getHeight(right->left) > getHeight(right->right)) {
				rt = RightLeftRotation(rt);
			}
			//右子树的右子树失衡,进行RR旋转
			else {
				rt = RightRightRotation(rt);
			}
		}
	}
	//要删的节点在右子树
	else if (value > rt->value) {
		rt->right = remove(rt->right, value);
		//失衡
		if (getHeight(rt->left) - getHeight(rt->right) == 2) {
			AVLTreeNode<T>* left = rt->left;
			//左子树的左子树失衡,进行LL旋转
			if (getHeight(left->left) >= getHeight(left->right)) {
				rt = LeftLeftRotation(rt);
			}
			//左子树的右子树失衡,进行LR旋转
			else {
				rt = LeftRightRotation(rt);
			}
		}
	}
	//就删这
	else {
		//左子树或右子树是空的
		if (rt->left == nullptr || rt->right == nullptr) {
			AVLTreeNode<T>* removeNode = rt;
			if (rt->left == nullptr)rt = rt->right;
			else rt = rt->left;
			delete removeNode;
		}
		//左子树比右子树高或者一样高
		else if (getHeight(rt->left) >= getHeight(rt->right)) {
			AVLTreeNode<T>* maxNode = getMax(rt->left);
			rt->value = maxNode->value;
			rt->left = remove(rt->left, maxNode->value);
		}
		//右子树比左子树高
		else {
			AVLTreeNode<T>* minNode = getMin(rt->right);
			rt->value = minNode->value;
			rt->right = remove(rt->right, minNode->value);
		}
	}
	return rt;
}
/*
对以rt为根节点的树寻找拥有最大值的节点
@param rt 要找的树
@return 包含最大值的节点
*/
template<typename T>
AVLTreeNode<T>* AVLTree<T>::getMax(AVLTreeNode<T>* rt)
{
	if (rt == nullptr)return nullptr;
	AVLTreeNode<T>* temp = rt;
	while (temp->right != nullptr)temp = temp->right;
	return temp;
}
/*
对以rt为根节点的树寻找拥有最小值的节点
@param rt 要找的树
@return 包含最小值的节点
*/
template<typename T>
AVLTreeNode<T>* AVLTree<T>::getMin(AVLTreeNode<T>* rt)
{
	if (rt == nullptr)return nullptr;
	AVLTreeNode<T>* temp = rt;
	while (temp->left != nullptr)temp = temp->left;
	return temp;
}
/*
对以rt为根节点的树进行销毁
@param rt 要销毁的树
*/
template<typename T>
void AVLTree<T>::destory(AVLTreeNode<T>* rt)
{
	if (rt == nullptr)return;
	if (rt->left != nullptr)destory(rt->left);
	if (rt->right != nullptr)destory(rt->right);
	delete rt;
}
/*
对以rt为根节点的树进行前序遍历
@param rt 根节点
*/
template<typename T>
void AVLTree<T>::preOrder(AVLTreeNode<T>* rt) const
{
	if (rt == nullptr)return;
	cout << rt->value << ' ';
	if (rt->left != nullptr)preOrder(rt->left);
	if (rt->right != nullptr)preOrder(rt->right);
}
/*
对以rt为根节点的树进行中序遍历
@param rt 根节点
*/
template<typename T>
void AVLTree<T>::inOrder(AVLTreeNode<T>* rt) const
{
	if (rt == nullptr)return;
	if (rt->left != nullptr)inOrder(rt->left);
	cout << rt->value << ' ';
	if (rt->right != nullptr)inOrder(rt->right);
}
/*
	对以rt为根节点的树进行后序遍历
	@param rt 根节点
	*/
template<typename T>
void AVLTree<T>::postOrder(AVLTreeNode<T>* rt) const
{
	if (rt == nullptr)return;
	if (rt->left != nullptr)postOrder(rt->left);
	if (rt->right != nullptr)postOrder(rt->right);
	cout << rt->value << ' ';
}
/*
对以rt为根节点的树进行层遍历
@param rt 根节点
*/
template<typename T>
void AVLTree<T>::layerOrder(AVLTreeNode<T>* rt) const
{
	queue<AVLTreeNode<T>*> q;
	if (rt != nullptr)q.push(rt);
	while (!q.empty()) {
		AVLTreeNode<T>* temp = q.front();
		q.pop();
		cout << temp->value << ' ';
		if (temp->left != nullptr)q.push(temp->left);
		if (temp->right != nullptr)q.push(temp->right);
	}
}
/*
对以rt为根节点的树查找值为value的节点
@param rt 根节点
@param value 查找的值
@return 包含value的节点
*/
template<typename T>
AVLTreeNode<T>* AVLTree<T>::search(AVLTreeNode<T>* rt, const T & value) const
{
	while (rt != nullptr&&rt->value != value) {
		if (value < rt->value)rt = rt->left;
		else if (value > rt->value)rt = rt->right;
		else break;
	}
	return rt;
}

template<typename T>
AVLTree<T>::AVLTree():root(nullptr)
{
}

template<typename T>
AVLTree<T>::~AVLTree()
{
	destory();
}
/*
获得以tree为根节点的树的高度
@param tree 树
*/
template<typename T>
int AVLTree<T>::getHeight(AVLTreeNode<T>* tree) const
{
	if (tree == nullptr)return 0;
	return tree->height;
}
/*
对以rt根节点的树进行右旋(LL旋转)
@param rt 要旋转的树的根节点
@return 旋转后的根节点
*/
template<typename T>
AVLTreeNode<T>* AVLTree<T>::LeftLeftRotation(AVLTreeNode<T>* rt)
{
	AVLTreeNode<T>* temp = rt->left;
	rt->left = temp->right;
	temp->right = rt;
	updateHeight(rt);
	updateHeight(temp);
	return temp;
}
/*
对以rt根节点的树进行左旋(RR旋转)
@param rt 要旋转的树的根节点
@return 旋转后的根节点
*/
template<typename T>
AVLTreeNode<T>* AVLTree<T>::RightRightRotation(AVLTreeNode<T>* rt)
{
	AVLTreeNode<T>* temp = rt->right;
	rt->right = temp->left;
	temp->left = rt;
	updateHeight(rt);
	updateHeight(temp);
	return temp;
}
/*
对以rt根节点的树的进行LR旋转
先对rt的左子树做左旋(RR旋转),然后对rt进行右旋(LL旋转)
@param rt 要旋转的树的根节点
@return 旋转后的根节点
*/
template<typename T>
AVLTreeNode<T>* AVLTree<T>::LeftRightRotation(AVLTreeNode<T>* rt)
{
	rt->left = RightRightRotation(rt->left);
	return LeftLeftRotation(rt);
}
/*
对以rt根节点的树的进行RL旋转
先对rt的右子树做右旋(LL旋转),然后对rt进行左旋(RR旋转)
@param rt 要旋转的树的根节点
@return 旋转后的根节点
*/
template<typename T>
AVLTreeNode<T>* AVLTree<T>::RightLeftRotation(AVLTreeNode<T>* rt)
{
	rt->right = LeftLeftRotation(rt->right);
	return RightRightRotation(rt);
}
/*
插入值为value的节点
@param value 要插入的值
*/
template<typename T>
void AVLTree<T>::insert(const T & value)
{
	//insert(root, value);
	root = insert(root, value);
}
/*
删除值为value的节点
@param value 要删除的值
*/
template<typename T>
void AVLTree<T>::remove(const T & value)
{
	root = remove(root, value);
}
//前序遍历
template<typename T>
void AVLTree<T>::preOrder() const
{
	preOrder(root);
	cout << endl;
}
template<typename T>
void AVLTree<T>::inOrder() const
{
	inOrder(root);
	cout << endl;
}
template<typename T>
void AVLTree<T>::postOrder() const
{
	postOrder(root);
	cout << endl;
}
//层序遍历
template<typename T>
void AVLTree<T>::layerOrder() const
{
	layerOrder(root);
	cout << endl;
}
/*
查找值为value的节点
@param value 查找的值
@return 包含value的节点
*/
template<typename T>
AVLTreeNode<T>* AVLTree<T>::search(const T & value) const
{
	return search(root, value);
}
//销毁树
template<typename T>
void AVLTree<T>::destory()
{
	destory(root);
}
/*
对以rt为根节点的树插入值为value的节点
@param rt 要插入的树
@param value 要插入的值
@return 插入节点后的树
*/
template<typename T>
AVLTreeNode<T>* AVLTree<T>::insert(AVLTreeNode<T>* rt, const T & value)
{
	//就插这
	if (rt == nullptr) {
		rt = new AVLTreeNode<T>(value);
	}
	//插左边
	else if (value < rt->value) {
		rt->left = insert(rt->left, value);
		//左子树比右子树高2,失衡了
		if (getHeight(rt->left) - getHeight(rt->right) == 2) {
			//插入在左子树的左子树上,说明要LL旋转
			if (value < rt->left->value) {
				rt = LeftLeftRotation(rt);
			}
			//插入在左子树的右子树上,说明要LR旋转
			else {
				rt = LeftRightRotation(rt);
			}
		}
	}
	//插右边
	else if (value > rt->value) {
		rt->right = insert(rt->right, value);
		//右子树比左子树高2,失衡了
		if (getHeight(rt->right) - getHeight(rt->left) == 2) {
			//插入在右子树的左子树上,说明要RL旋转
			if (value < rt->right->value) {
				rt = RightLeftRotation(rt);
			}
			//插入在右子树的右子树上,说明要RR旋转
			else {
				rt = RightRightRotation(rt);
			}
		}
	}
	//插入了重复的数据
	else {
		return rt;
	}
	//更新高度
	updateHeight(rt);
	return rt;
}
/*
更新以rt为根节点的树的高度
@param rt 根节点
*/
template<typename T>
void AVLTree<T>::updateHeight(AVLTreeNode<T>* rt)
{
	if (rt == nullptr)return;
	rt->height = max(getHeight(rt->left), getHeight(rt->right)) + 1;
}
//获得树的高度
template<typename T>
int AVLTree<T>::getHeight() const
{
	return getHeight(root);
}

main.cpp

使用模板貌似要引入.cpp文件而不是.h 

#include<iostream>
#include "AVLTree.cpp"
using namespace std;
int main() {
	int arr[] = { 3,2,1,4,5,6,7,16,15,14,13,12,11,10,8,9 };
	AVLTree<int> t;
	for (int a : arr)
		t.insert(a);
	t.preOrder();
	t.inOrder();
	t.remove(13);
	t.preOrder();
	t.inOrder();
	t.remove(4);
	t.preOrder();
	t.inOrder();
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nightmare004

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值