Directorio de artículos
Características del árbol AVL
- El árbol de búsqueda binaria puede aumentar la eficiencia de la búsqueda para registrar 2 n log_2nl o g2n , pero si los datos están básicamente ordenados, el árbol de búsqueda binario degenerará en un árbol de una sola rama La eficiencia de búsqueda es equivalente a buscar datos en la tabla de secuencia, que es baja. Dos árboles de búsqueda binarios balanceados resuelven este problema: árbol AVL y árbol rojo-negro
- Características del árbol AVL:
- El valor absoluto de la diferencia de altura entre los subárboles izquierdo y derecho de cada nodo no supera 1, lo que reduce la altura del árbol, reduciendo así el tiempo medio de búsqueda.
- Un árbol vacío también es un árbol AVL, y cada subárbol del árbol AVL es un árbol AVL
- Por lo tanto, el árbol AVL debe garantizar el equilibrio del árbol cada vez que se realiza una operación de inserción y eliminación.
Cuatro escenarios después de la inserción de AVL
- Rotación única derecha: posición de inserción: el lado izquierdo (exterior) del subárbol superior izquierdo
- método:
- Eleve subL hacia arriba, ajuste los campos de puntero de subL, subLR y nodos principales
- Determinar si existe el nodo padre del padre
- Establezca el factor de equilibrio de padre y subL en 0
- Doble rotación izquierda y derecha: posición de inserción: el lado derecho (interior) del subárbol superior izquierdo
- método:
- Primero realice la rotación izquierda-simple en el padre-> izquierda para convertir el problema en un escenario de rotación simple derecha
- Y luego rotar el padre a la derecha
- Ajuste el factor de equilibrio del árbol juzgando el factor de equilibrio inicial de subLR
- 若 bf == -1 , padre-> bf = 1
- Si bf == 1, subL-> bf = -1
-
Rotación simple izquierda: posición de inserción: el lado derecho (exterior) del subárbol superior derecho
-
método:
- Levante subR, ajuste los campos de puntero de subR, subRL y parent
- Determinar si existe el nodo padre
- Establezca el factor de equilibrio de subR y parent en 0
-
Doble rotación derecha e izquierda: posición de inserción: el lado izquierdo (interior) del subárbol superior derecho
- método:
- Primero, realice una rotación única a la derecha en el padre-> izquierda para convertir el problema en un escenario de rotación única a la izquierda
- Y luego rotar el padre a la izquierda
- Ajuste el factor de equilibrio del árbol juzgando el factor de equilibrio de subLR
- Si bf == -1, entonces subR-> bf = 1
- Si bf == 1, entonces parent-> bf = -1
- método:
Código
#pragma once
#include <iostream>
using namespace std;
template<class T>
class AVLNode
{
public:
AVLNode(const T& data = T())
:left(nullptr)
,right(nullptr)
,parent(nullptr)
,val(data)
,bf_(0)
{
}
AVLNode<T>* left;
AVLNode<T>* right;
AVLNode<T>* parent;
T val;
int bf_;
};
template<class T>
class AVLTree
{
typedef AVLNode<T> Node;
public:
AVLTree()
:root_(nullptr)
{
}
~AVLTree()
{
Destory(root_);
}
bool AVLinsert(const T& data)
{
// 1.找位置进行插入
if (root_ == nullptr)
{
root_ = new Node(data);
return true;
}
Node* cur = root_;
Node* parent = nullptr;
while (cur)
{
parent = cur;
if (data < cur->val)
cur = cur->left;
else if (data > cur->val)
cur = cur->right;
else
return false;
}
cur = new Node(data);
if (data > parent->val)
parent->right = cur;
else
parent->left = cur;
cur->parent = parent;
// 2.调整树的平衡
while (parent)
{
// 1.调整插入父节点的平衡因子
if (cur == parent->left)
parent->bf_--;
else
parent->bf_++;
// 2.判断父节点的平衡因子执行不同行为
if (parent->bf_ == 0)
break;
else if (parent->bf_ == -1 || parent->bf_ == 1)
{
cur = parent;
parent = parent->parent;
}
else //parent->bf_ == 2 huo -2,要通过旋转调整
{
if (parent->bf_ == -2)
{
// 右单旋
if (-1 == cur->bf_)
{
RotateRight(parent);
}
// 左右双旋
else
{
RotateLR(parent);
}
}
else // parent->bf_ = 2
{
// 左单旋
if (cur->bf_ == 1)
{
RotateLeft(parent);
}
// 右左双旋
else
{
RotateRL(parent);
}
}
break;
}
}
return true;
}
void Inorder()
{
Inorder(root_);
cout << endl;
}
bool IsBalanceTree()
{
return _IsBalanceTree(root_);
}
private:
void Inorder(Node* root)
{
if (root)
{
Inorder(root->left);
cout << root->val << " ";
Inorder(root->right);
}
}
void Destory(Node*& root)
{
if (root)
{
Destory(root->left);
Destory(root->right);
delete root;
root = nullptr;
}
}
void RotateRight(Node* parent)
{
Node* subL = parent->left;
Node* subLR = subL->right;
parent->left = subLR;
if (subLR)
subLR->parent = parent;
subL->right = parent;
Node* pp = parent->parent;
parent->parent = subL;
subL->parent = pp;
if (pp == nullptr)
{
root_ = subL;
}
else
{
if (pp->left == parent)
pp->left = subL;
else
pp->right = subL;
}
subL->bf_ = parent->bf_ = 0;
}
void RotateLeft(Node* parent)
{
Node* subR = parent->right;
Node* subRL = subR->left;
parent->right = subRL;
if (subRL)
subRL->parent = parent;
subR->left = parent;
Node* pp = parent->parent;
parent->parent = subR;
subR->parent = pp;
if (pp == nullptr)
{
root_ = subR;
}
else
{
if (pp->left == parent)
pp->left = subR;
else
pp->right = subR;
}
subR->bf_ = parent->bf_ = 0;
}
void RotateLR(Node* parent)
{
Node* subL = parent->left;
Node* subLR = subL->right;
int bf = subLR->bf_;
RotateLeft(parent->left);
RotateRight(parent);
if (bf == -1)
parent->bf_ = 1;
else
subL->bf_ = -1;
}
void RotateRL(Node* parent)
{
Node* subR = parent->right;
Node* subRL = subR->left;
int bf = subRL->bf_;
RotateRight(parent->right);
RotateLeft(parent);
if (bf == -1)
subR->bf_ = 1;
else
parent->bf_ = -1;
}
int High(Node* root)
{
if (root == nullptr)
return 0;
int left = High(root->left);
int right = High(root->right);
return left > right ? left + 1 : right + 1;
}
bool _IsBalanceTree(Node* root)
{
if (root == nullptr)
return true;
int left = High(root->left);
int right = High(root->right);
int bf = right - left;
if (abs(bf) > 1 || bf != root->bf_)
{
cout << "节点" << root->val << "的平衡因子出问题" << endl;
return false;
}
return _IsBalanceTree(root->left) && _IsBalanceTree(root->right);
}
private:
AVLNode<T>* root_;
};
void TestAVLTree()
{
AVLTree<int> an;
//int arr[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
int arr[] = {
4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
for (auto i : arr)
an.AVLinsert(i);
an.Inorder();
an.IsBalanceTree();
}