c++实现AVL_tree

写在前面

AVL_Tree是一棵自平衡的二叉树,在树中任意节点的左右子树之间的高度差小于等于1,很好的弥补了二叉搜索树有可能出现不平衡的情况,只是在二叉搜索树的基础上添加了四种旋转操作,使二叉搜索树变成自平衡的二叉搜索树

AVLTree的数据结构

首先它是一个二叉树,那么他一定包含左右子节点的信息,并且为了方便进行高度的判断调整等,还要包含高度信息,最后还要有当前节点的数值信息,所以他的数据结构是这样的:

template<class T>
class AVLTree_Node {
public:
	T key;
	AVLTree_Node<T> *left;
	AVLTree_Node<T> *right;
	int height;
};

四种操作

首先先看一下四种操作,我们称这四种情况为LL,RR,LR,RL

LL情况

在第一个图中:节点a的左子树高度为3,右子树高度为1,他们之间相差大于1,那么这里就要对树进行相应的调整,我们看到多出来的节点在b节点的外侧,那么我们称这种不平衡出现在右子树中外侧的情况成有LL情况,那么只需要向右旋转一次,便可得到正确的自平衡二叉树,即第二个图

template<class T>
AVLTree_Node<T>* AVLTree<T>::_leftLeftRotate(AVLTree_Node<T> *node) {       //node对应图中的a点
	AVLTree_Node<T> *temp = node->left;

	node->left = temp->right;
	temp->right = node;

	node->height = max(_height(node->left), _height(node->right)) + 1;
	temp->height = max(_height(temp->left), node->height) + 1;

	return temp;
}

RR情况

当前情况与LL情况类似,同样在节点a出第一次出现不平衡的情况,并且这不平衡的节点在节点a的右子树的外侧,所以我们只要执行一次向左旋转的操作,就可以将图像转换为第二张图的情况

template<class T>
AVLTree_Node<T>* AVLTree<T>::_rightRightRotate(AVLTree_Node<T> *node) {
	AVLTree_Node<T> *temp = node->right;

	node->right = temp->left;
	temp->left = node;

	node->height = max(_height(node->left), _height(node->right)) + 1;
	temp->height = max(_height(temp->right), node->height) + 1;

	return temp;
}

LR情况

 这种情况上述两种情况不同的是:这里出现的产生不平衡的节点在a节点的右子树的内侧,没有再同一侧,我们就先根据节点b做一次左旋(RR情况),转换成在右子树中的外侧,那么就换成了LL情况,所以再以a为根节点做一次右旋,这样就可以得到平衡的二叉搜索树

template<class T>
AVLTree_Node<T>* AVLTree<T>::_leftRightRotate(AVLTree_Node<T>* node) {   //node代表图中的a节点
	node->left = _rightRightRotate(node->left);

	return _leftLeftRotate(node);
}

RL情况 

 与LR情况不同,这种情况产生不平衡的节点在a节点的右子树中的内侧,所以这样类似于RL操作,先以c节点作为根节点做一次右旋,形成RR的情况,再以a为根节点做一次左旋,得到正确的自平衡二叉树

template<class T>
AVLTree_Node<T>* AVLTree<T>::_rightLeftRotate(AVLTree_Node<T>* node) {
	node->right = _leftLeftRotate(node->right);

	return _rightRightRotate(node);
}

上述四张情况就是在AVLTree中所有可能的旋转操作,那么剩下的只是插入操作以及删除操作,他与二叉搜索树的插入操作相类似,但是要根据当前树的情况,进行相应的调整

节点插入

节点的插入操作,我们插入的节点一定在叶子节点,当我们向上回溯的时候,需要调整节点的深度,以及是否还是符合自平衡二叉树的条件,如果不满足的话,要进行相应的操作

template<class T>
AVLTree_Node<T>* AVLTree<T>::_insert(AVLTree_Node<T>* &node, T key){
	if (node == NULL) {
		node = new AVLTree_Node<T>(key);                                       //根据新节点插入的条件得知:插入的位置一定是叶子节点的位置
		if (node == NULL) {                    
			cout << "REEOR:create node faile!" << endl;
		}
	}
	else if (node->key > key) {                                               //向左子节点插入对象
		node->left = _insert(node->left, key);
		if (_height(node->left) - _height(node->right) == 2) {                //如果出现不满足AVLTree的情况
			if (key > node->left->key)                                        //插入到了左子树内侧,所以是LR情况
				node = _leftRightRotate(node);
			else                                                              //插入到了左子树外侧,LL情况
				node = _leftLeftRotate(node);
		}
	} 
	else if (node->key < key) {                                              //向右子节点插入对象                        
		node->right = _insert(node->right, key);
		if (_height(node->right) - _height(node->left) == 2) {
			if (key > node->right->key)                                      //插入到了右子树的外侧 RR情况
				node = _rightRightRotate(node); 
			else                                                             //右子树的内侧     RL情况
				node = _rightLeftRotate(node);
		}
	}
	else {                                                                  //否则一定是数据出现相同的情况
		cout << "ERROR:Digital repetition!" << endl;
	}
	node->height = max(_height(node->left), _height(node->right)) + 1;
	return node;
}

节点删除 

节点删除的时候,总共包含三种情况

template<class T>
AVLTree_Node<T>* AVLTree<T>::_remove(AVLTree_Node<T>* &root, AVLTree_Node<T> *node) {
	if (root == NULL || node == NULL)
		return NULL;

	if (node->key < root->key) {                                        //在节点的左子树中删除的
		root->left = _remove(root->left, node);
		if (_height(root->right) - _height(root->left) == 2) {          //如果右子树的高度与左子树高度相差大于2,删除节点之后进行相应的调整
			AVLTree_Node<T> *r = root->right;
			if (_height(r->left) > _height(r->right))                   //这里不能直接判断插入的节点在左子树还是右子树中,只能借助树的高度间接判断
				root = _rightLeftRotate(root);
			else
				root = _rightRightRotate(root);
		}
	}
	else if (node->key > root->key) {
		root->right = _remove(root->right, node);                      //相应的节点在右子树中删除的情况
		if (_height(root->left) - _height(root->right) == 2) {
			AVLTree_Node<T>* l = root->left;
			if (_height(l->right) > _height(l->left))
				root = _leftRightRotate(root);
			else
				root = _leftLeftRotate(root);
		}
	}
	else {                                                            //root对应要删除的节点
		if (root->left != NULL && root->right != NULL) {              //要删除的节点左右都有子节点
			if (_height(root->left) > _height(root->right)) {         //情况一、如果当前节点的左子树要比右子树高
				AVLTree_Node<T>* max = _maximum(root->left);          //找到左子树中最大的节点,将最大的节点赋值到当期那节点,然后删除最大指针指向的节点
				root->key = max->key;                                 
				root->left = _remove(root->left, max);                //那么相应的就去删除最大的那个节点
			}
			else {                                                     //情况二、找到右子树中最小的节点,将数值进行替换,然后再去删除右子树中最小的节点
				AVLTree_Node<T>* min = _minimum(root->right);
				root->key = min->key;
				root->right = _remove(root->right, min);
			}
		}
		else {                                                         //情况三、如果当前要删除的节点左边或者右边没有叶子节点
			AVLTree_Node<T> *tmp = root;
			root = (root->left != NULL) ? root->left : root->right;    //直接将当前节点接上后续(左子树或者右子树)的节点即可
			delete tmp;                                                //删除当前节点
		}
	}
	return root;
}

总程序

#pragma once                   //AVL_Tree_.h文件
#ifndef __AVL_TREE_H_
#define __AVL_TREE_H_
#include <iostream>
using namespace std;

template<class T>
class AVLTree_Node {
public:
	T key;
	AVLTree_Node<T> *left;
	AVLTree_Node<T> *right;
	int height;

	AVLTree_Node() {}
	AVLTree_Node(T _key, AVLTree_Node<T> *l = NULL, AVLTree_Node<T> *r = NULL,int _height = 0 ) :key(_key), left(l), right(r), height(height){}
};

template<class T>
class AVLTree {
public:
	AVLTree();
	~AVLTree();

	int height();
	int max(int a,int b);

	void insert(T key);

private:
	AVLTree_Node<T> *root;                                        //根节点

private:
	int _height(AVLTree_Node<T> *tree);
	AVLTree_Node<T>* _insert(AVLTree_Node<T> * &tree, T key);

	AVLTree_Node<T>* _leftLeftRotate(AVLTree_Node<T>* node);
	AVLTree_Node<T>* _rightRightRotate(AVLTree_Node<T>* node);
	AVLTree_Node<T>* _leftRightRotate(AVLTree_Node<T>* node);
	AVLTree_Node<T>* _rightLeftRotate(AVLTree_Node<T>* node);
};

template<class T>
AVLTree<T>::AVLTree():root(){}

template<class T>
AVLTree<T>::~AVLTree() {
	destory(root);
}
template<class T>
int AVLTree<T>::max(int a, int b) {
	return a > b ? a : b;
}

template<class T>
int AVLTree<T>::_height(AVLTree_Node<T> *node) {
	if (node != NULL)
		return node->height;
	return 0;
}

template<class T>
int AVLTree<T>::height() {
	return _height(root);
}

template<class T>
AVLTree_Node<T>* AVLTree<T>::_leftLeftRotate(AVLTree_Node<T> *node) {
	AVLTree_Node<T> *temp = node->left;

	node->left = temp->right;
	temp->right = node;

	node->height = max(_height(node->left), _height(node->right)) + 1;
	temp->height = max(_height(temp->left), node->height) + 1;

	return temp;
}

template<class T>
AVLTree_Node<T>* AVLTree<T>::_rightRightRotate(AVLTree_Node<T> *node) {
	AVLTree_Node<T> *temp = node->right;

	node->right = temp->left;
	temp->left = node;

	node->height = max(_height(node->left), _height(node->right)) + 1;
	temp->height = max(_height(temp->right), node->height) + 1;

	return temp;
}

template<class T>
AVLTree_Node<T>* AVLTree<T>::_leftRightRotate(AVLTree_Node<T>* node) {
	node->left = _rightRightRotate(node->left);

	return _leftLeftRotate(node);
}

template<class T>
AVLTree_Node<T>* AVLTree<T>::_rightLeftRotate(AVLTree_Node<T>* node) {
	node->right = _leftLeftRotate(node->right);

	return _rightRightRotate(node);
}

template<class T>
void AVLTree<T>::insert(T key) {
	_insert(root, key);
}

template<class T>
AVLTree_Node<T>* AVLTree<T>::_insert(AVLTree_Node<T>* &node, T key){
	if (node == NULL) {
		node = new AVLTree_Node<T>(key);                                       //根据新节点插入的条件得知:插入的位置一定是叶子节点的位置
		if (node == NULL) {                    
			cout << "REEOR:create node faile!" << endl;
		}
	}
	else if (node->key > key) {
		node->left = _insert(node->left, key);
		if (_height(node->left) - _height(node->right) == 2) {
			if (key > node->left->key)
				node = _leftRightRotate(node);
			else
				node = _leftLeftRotate(node);
		}
	}
	else if (node->key < key) {
		node->right = _insert(node->right, key);
		if (_height(node->right) - _height(node->left) == 2) {
			if (key > node->right->key)
				node = _rightRightRotate(node);
			else
				node = _rightLeftRotate(node);
		}
	}
	else {
		cout << "ERROR:Digital repetition!" << endl;
	}
	node->height = max(_height(node->left), _height(node->right)) + 1;
	cout << node -> height << endl;
	return node;
}

#endif

 测试程序:

#include <iostream>
#include "AVL_Tree_.h"

using namespace std;

int main()
{
	int arr[13] = { 3,2,1,4,5,6,7,12,34,56,78,13,35 };

	AVLTree<int> * tree = new AVLTree<int>();
	for (int i = 0; i < 13; i++)
		tree->insert(arr[i]);
	

	cout << tree->minimum() << endl;
	tree->remove(1);
	cout << tree->minimum() << endl;

	cout << tree->height() << endl;

	system("pause");
}

参考博客

程序来源:https://www.cnblogs.com/skywang12345/p/3577360.html

后记

还有很多没有实现的功能,但是主要的操作大概就是这些...

猜你喜欢

转载自blog.csdn.net/li1615882553/article/details/83313161