二叉平衡树其实是二叉搜索树的进阶,就是在二叉搜索树的基础上添加了平衡因子的概念,平衡因子就是左右子树的高度差,二叉平衡树中所有结点的平衡因子的绝对值都不超过1
如果插入右子树的内侧和左子树的原理一样,但是是先右旋后左旋
#pragma once
#include <iostream>
using namespace std;
template<class T>
struct AVLNode
{
AVLNode(const T& data = T())
:val_(data),
bf_(0),
left_(nullptr),
right_(nullptr),
parent_(nullptr)
{ }
T val_;
int bf_; //平衡因子 //在本代码中平衡因子是用右子树高度减去左子树高度
struct AVLNode* left_;
struct AVLNode* right_;
struct AVLNode* parent_;
};
template<class T>
class AVLTree
{
typedef AVLNode<T> Node;
public:
AVLTree()
:root(nullptr)
{}
~AVLTree()
{
_Destoy(root);
}
void InOrder()
{
_InOrder(root);
}
bool Insert(const T& data)
{
//1.按二叉搜索树的形式进行插入
if (nullptr == root)
{
root = new Node(data);
return true;
}
Node* cur = root;
Node* parent = nullptr;
while (cur)
{
parent = cur;
if (data > cur->val_)
cur = cur->right_;
else if (data < cur->val_)
cur = cur->left_;
else
return false;
}
cur = new Node(data);
if (data < parent->val_)
parent->left_ = cur;
else
parent->right_ = cur;
cur->parent_ = parent;
//2.插入新节点后一定会影响树的平衡因子,调整树的平衡因子
while (parent)
{
//在本代码中平衡因子是用右子树高度减去左子树高度
if (cur == parent->left_)
parent->bf_--; //右子树高度不变
else
parent->bf_++; //左子树高度不变
if (parent->bf_ == 0)
break;
else if (1 == parent->bf_ || -1 == parent->bf_)
{
//之前parent为叶子节点,须向上更新检查平衡因子
cur = parent;
parent = parent->parent_;
}
else
{
//平衡因子为2或-2
//需通过旋转调整平衡因子
if (2 == parent->bf_)
{
if (1 == cur->bf_)
RotateLeft(parent);
else
RotateRL(parent);
}
else
{
if (-1 == cur->bf_)
RotateRight(parent);
else
RotateLR(parent);
}
break;
}
}
return true;
}
private:
void _InOrder(Node* Proot)
{
if (Proot)
{
_InOrder(Proot->left_);
cout << Proot->val_ << " ";
_InOrder(Proot->right_);
}
}
void _Destoy(Node*& Proot)
{
if (root)
{
_Destoy(Proot->left_);
_Destoy(Proot->right_);
delete root;
root = nullptr;
}
}
//右单旋
void RotateRight(Node* parent)
{
Node* stuL = parent->left_;
Node* stuLR = stuL->right_;
parent->left_ = stuLR;
stuL->right_ = parent;
if (stuLR)
stuLR->parent_ = parent; //防止为空(左单支情况)
Node* pparent = parent->parent_;
parent->parent_ = stuL;
stuL->parent_ = pparent;
//parent可能是根节点,需要更新root
//parent也可能是子树,需更新pparent的左右指针域
if (nullptr == pparent)
root = stuL;
else
{
if (parent == pparent->left_)
pparent->left_ = stuL;
else
pparent->right_ = stuL;
}
parent->bf_ = stuL->bf_ = 0;
}
//左单旋
void RotateLeft(Node* parent)
{
Node* stuR = parent->right_;
Node* stuRL = stuR->left_;
parent->right_ = stuRL;
stuR->left_ = parent;
if (stuRL)
stuRL->parent_ = parent;
Node* pparent = parent->parent_;
stuR->parent_ = pparent;
parent->parent_ = stuR;
if (nullptr == pparent)
root = stuR;
else
{
if (parent == pparent->left_)
pparent->left_ = stuR;
else
pparent->right_ = stuR;
}
parent->bf_ = stuR->bf_ = 0;
}
//先左旋后右旋
void RotateLR(Node* parent)
{
Node* stuL = parent->left_;
Node* stuLR = stuL->right_;
int bf = stuLR->bf_; //必须保存stuLR的bf,调整完后要根据它的值更新部分节点的bf
RotateLeft(parent->left_);
RotateRight(parent);
if (1 == bf)
stuL->bf_ = -1;
else if (-1 == bf)
parent->bf_ = 1;
}
//先右旋后左旋
void RotateRL(Node* parent)
{
Node* stuR = parent->right_;
Node* stuRL = stuR->left_;
int bf = stuRL->bf_;
RotateRight(parent->right_);
RotateLeft(parent);
if (1 == bf)
parent->bf_ = -1;
else if (-1 == bf)
stuR->bf_ = 1;
}
private:
Node* root;
};
void TestAVL()
{
int array[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
AVLTree<int> t;
for (auto e : array)
t.Insert(e);
t.InOrder();
cout << endl;
}