写在前面
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
后记
还有很多没有实现的功能,但是主要的操作大概就是这些...