AVL树
一.什么是AVL树?
AVL树本质上也是一棵二叉搜索树,不过它是一棵高度平衡的二叉搜索树
平衡二叉树:左右子树的高度差不超过1;
二.如何实现?
在二叉搜索树的前提上为每一个结点加入一个平衡因子成员变量,再加入一个指向父节点的指针变量;
平衡因子:右子树高度 - 左子树高度
三.旋转
1.右边的右边高--左单旋
2.左边的左边高--右单旋
3.左右双旋:
4.右左双旋:
四.实现
#include <iostream>
using namespace std;
//AVL树:二叉搜索平衡树
template <class T>
struct AVLNode {
T _data;
AVLNode<T>* _left;
AVLNode<T>* _right;
AVLNode<T>* _parent;
int _bf;
AVLNode(const T& data = T())
:_data(data),
_left(nullptr),
_right(nullptr),
_parent(nullptr),
_bf(0)
{}
};
template <class T>
class AVLTree {
public:
typedef AVLNode<T> Node;
typedef Node* pNode;
AVLTree()
:_root(nullptr)
{}
//查找
pNode Find(const T& data) {
//先判断树是否为空
if (_root == nullptr) {
return _root;
}
//树不为空,按照性质来查找
pNode cur = _root;
while (cur) {
if (cur->_data == data) {
break;
}
if (cur->_data > data) {
cur = cur->_left;
}
else {
cur = cur->_right;
}
}
return cur;
}
//左边的左边高——右单旋
void RotateRight(pNode node) {
pNode subL = node->_left;
pNode subLR = subL->_right;
subL->_right = node;
node->_left = subLR;
//判断subLR是否存在
if (subLR) {
subLR->_parent = node;
}
//判断是否是根节点
if (node != _root) {
pNode parent = node->_parent;
if (parent->_left == node) {
parent->_left = subL;
}
else {
parent->_right = subL;
}
subL->_parent = parent;
}
//不是根节点
else {
_root = subL;
subL->_parent = nullptr;
}
node->_parent = subL;
//更改平衡因子
node->_bf = subL->_bf = 0;
}
//右边的右边高——左单旋
void RotateLeft(pNode node) {
pNode subR = node->_right;
pNode subRL = subR->_left;
node->_right = subRL;
subR->_left = node;
if (subRL) {
subRL->_parent = node;
}
//判断是否是根节点
if (node != _root) {
pNode parent = node->_parent;
if (parent->_left == node) {
parent->_left = subR;
}
else {
parent->_right = subR;
}
subR->_parent = parent;
}
//是根节点
else {
_root = subR;
subR->_parent = nullptr;
}
node->_parent = subR;
//更改平衡因子
node->_bf = subR->_bf = 0;
}
//结点的插入
bool Insert(const T& data) {
//先判断树是否为空
if (_root == nullptr) {
_root = new Node(data);
return true;
}
//树非空,根据二叉搜索树的性质找到合适的叶子位置
pNode cur = _root;
pNode parent = nullptr;
while (cur) {
//判断是否有相同的结点
if (cur->_data == data) {
cout << "存在相同节点!!!" << endl;
return false;
}
parent = cur;
if (cur->_data > data) {
cur = cur->_left;
}
else {
cur = cur->_right;
}
}
//找到了合适的叶子结点的位置
cur = new Node(data);
if (parent->_data > cur->_data) {
parent->_left = cur;
}
else {
parent->_right = cur;
}
cur->_parent = parent;
//结点插入完毕,开始进行调整
//从叶子结点开始进行调整
while (parent) {
//在这里先更改平衡因子
if (parent->_left == cur) {
--parent->_bf;
}
else {
++parent->_bf;
}
//开始判断是否需要旋转调整
//如果父节点的平衡因子是0,表示对其父路径上的结点没有干扰,直接退出循环,调整完毕
if (parent->_bf == 0) {
break;
}
//如果父节点的平衡因子是1 / -1 ,则表明父节点的平衡因子的改变对其父路径上的结点已经有所影响,
//需要向上检查其他节点是否平衡
else if (parent->_bf == 1 || parent->_bf == -1) {
cur = parent;
parent = parent->_parent;
}
//左边的左边高——右单旋
else if (parent->_bf == -2 && cur->_bf == -1) {
RotateRight(parent);
break;
}
//右边的右边高——左单旋
else if (parent->_bf == 2 && cur->_bf == 1) {
RotateLeft(parent);
break;
}
//双旋的场景:
//左边的右边高——先左旋,再右旋
else if (parent->_bf == -2 && cur->_bf == 1) {
pNode subLR = cur->_right;
pNode subL = cur;
RotateLeft(cur);
RotateRight(parent);
if (subLR->_bf == -1) {
parent->_bf = 1;
subL->_bf = 0;
}
else if (subLR->_bf == 1) {
parent->_bf = 0;
subL->_bf = -1;
}
break;
}
//右边的左边高——先右旋,再左旋
else if(parent->_bf == 2 && cur->_bf == -1){
pNode subR = cur;
pNode subRL = cur->_left;
RotateRight(cur);
RotateLeft(parent);
if (subRL->_bf == 1) {
parent->_bf = -1;
subR->_bf = 0;
}
else if (subRL->_bf == -1) {
parent->_bf = 0;
subR->_bf = 1;
}
break;
}
}
return true;
}
//结点的删除
void _inOrder(pNode root) {
if (root == nullptr) {
return;
}
_inOrder(root->_left);
cout << root->_data << " ";
_inOrder(root->_right);
}
void InOrder() {
_inOrder(_root);
cout << endl;
}
int height(pNode root) {
if (root == nullptr) {
return 0;
}
int left = height(root->_left);
int right = height(root->_right);
return left > right ? left + 1 : right + 1;
}
bool _isAVLTree(pNode root) {
//判断每个结点的平衡因子与高度差是否相同
if (root == nullptr) {
return true;
}
int leftHeight = height(root->_left);
int rightHeight = height(root->_right);
int heightgap = rightHeight - leftHeight;
if (root->_bf != heightgap || root->_bf > 1 || root->_bf < -1) {
cout << root->_data << ":平衡因子-->" << root->_bf << endl;
cout << "高度差:" << heightgap << endl;
return false;
}
return _isAVLTree(root->_left) && _isAVLTree(root->_right);
}
bool IsAVLTree() {
return _isAVLTree(_root);
}
private:
pNode _root;
};
void test() {
AVLTree<int> avl;
avl.Insert(5);
avl.Insert(6);
avl.Insert(7);
avl.Insert(8);
avl.Insert(9);
avl.InOrder();
cout << avl.IsAVLTree() << endl;
avl.InOrder();
cout << avl.IsAVLTree() << endl;
}
int main() {
test();
system("pause");
return 0;
}