1:定义
AVL树又称平衡二叉搜索树,它的任意一个节点的左右子树的高度差不超过1,这样能减少数的高度,以达到减少搜索次数的目的。
2:AVL节点的结构
//Key Value结构的AVL树
K _key;
AVLTreeNode<K, V>* _Left;
AVLTreeNode<K, V>* _Right;
AVLTreeNode<K, V>* _parent;
V _value;
int _bf; //平衡因子(右子树高度-左子树高度)
3:AVL节点的插入
当我们插入一个节点时,会从当前插入的这个节点向上进行检查,检查到的节点的平衡因子如果等于0;则可以说明这个节点上面的平衡因子在插入新的节点之前已经更新过了,不用再进行调整,如果平衡因子等于-1或者 1,则需要继续向上查找,直到遍历到这颗树的根节点或者遍历到有节点的平衡因子为2或-2为止。
while (parent)
{
//
if (parent->_Left ==cur)
parent->_bf--;
else
parent->_bf++;
if (parent->_bf == 0)
break;
else if (abs(parent->_bf) == 1)
{
cur = parent;
parent = parent->_parent;
}
else
{
/*_UpdataBalanceFactor(parent);*/
if ((parent->_bf == -2) && (parent->_Left->_bf == -1))
{
//进行右单旋
_RotateR(parent);
}
else if ((parent->_bf == 2) && (parent->_Right->_bf) == 1)
{
//进行左单旋
_RotateL(parent);
}
else if ((parent->_bf == 2) && (parent->_Right->_bf == -1))
{
//进行右左双旋
_RotateRL(parent);
}
else
{
//进行左右双旋
_RotateLR(parent);
}
break;
}
1:右单旋
某节点的平衡因子为-2,其左孩子节点平衡因子为-1
2:左单旋
某节点的平衡因子为2,其右孩子节点的平衡因子为1
3:左右双旋
某节点的平衡因子为-2,其左孩子平衡因子为1
4:右左双旋
某节点的平衡因子为2,其右孩子节点的平衡因子为-1
代码
#pragma once
#include <iostream>
using namespace std;
#include <cassert>
#include <string>
template <class K,class V>
struct AVLTreeNode
{
K _key;
AVLTreeNode<K, V>* _Left;
AVLTreeNode<K, V>* _Right;
AVLTreeNode<K, V>* _parent;
V _value;
int _bf; //平衡因子(右子树高度-左子树高度)
AVLTreeNode(const K& key, const V& value)
:_key(key)
, _Left(NULL)
, _Right(NULL)
, _parent(NULL)
, _value(value)
, _bf(0)
{}
};
template<class K,class V>
class AVLTree
{
typedef AVLTreeNode<K, V> Node;
public:
AVLTree()
:_root(NULL)
{}
bool Insert(const K& key, const V& value)
{
if (_root == NULL)
{
_root = new Node(key, value);
return true;
}
Node* cur = _root;
Node* parent = NULL;
//找到所要插入的位置
while (cur)
{
if (cur->_key > key)
{
parent = cur;
cur = cur->_Left;
}
else if (cur->_key < key)
{
parent = cur;
cur = cur->_Right;
}
else
return false;
}
cur = new Node(key, value);
if (parent->_key < key)
{
parent->_Right = cur;
cur->_parent = parent;
}
else
{
parent->_Left = cur;
cur->_parent = parent;
}
while (parent)
{
//
if (parent->_Left ==cur)
parent->_bf--;
else
parent->_bf++;
if (parent->_bf == 0)
break;
else if (abs(parent->_bf) == 1)
{
cur = parent;
parent = parent->_parent;
}
else
{
/*_UpdataBalanceFactor(parent);*/
if ((parent->_bf == -2) && (parent->_Left->_bf == -1))
{
//进行右单旋
_RotateR(parent);
}
else if ((parent->_bf == 2) && (parent->_Right->_bf) == 1)
{
//进行左单旋
_RotateL(parent);
}
else if ((parent->_bf == 2) && (parent->_Right->_bf == -1))
{
//进行右左双旋
_RotateRL(parent);
}
else
{
//进行左右双旋
_RotateLR(parent);
}
break;
}
}
return true;
}
void Inorder()
{
_Inorder(_root);
cout << endl;
}
//判断是否平衡
bool IsBalance()
{
return _IsBalance(_root);
}
size_t GetHeight()
{
return _Height(_root);
}
bool IsBalanceOp()
{
int Height = 0;
bool ret= _IsBalanceOp(_root,Height);
cout << "Tree's height is:" << Height << endl;
return ret;
}
protected:
bool _IsBalanceOp(Node* root,int& Height)
{
if (root == NULL)
{
Height = 0;
return true;
}
int RHeight = 0;
int LHeight = 0;
if (_IsBalanceOp(root->_Left, LHeight) == false)
{
Height = _Height(root);
return false;
}
else if (_IsBalanceOp(root->_Right, RHeight) == false)
{
Height = _Height(root);
return false;
}
Height = LHeight > RHeight ? LHeight + 1 : RHeight + 1;
return abs(RHeight-LHeight) <= 1;
}
bool _IsBalance(Node* root)
{
if (root == NULL)
{
return true;
}
int LHeight = _Height(root->_Left);
int RHeight = _Height(root->_Right);
int bf = RHeight - LHeight;
if (bf != root->_bf)
{
cout << "平衡因子异常:" << root->_key << endl;
return false;
}
return (abs(RHeight-LHeight)<2)&&(_IsBalance(root->_Left))&&(_IsBalance(root->_Right));
}
size_t _Height(Node* root)
{
if (root == NULL)
return 0;
if (root->_Right==NULL&&root->_Left==NULL)
return 1;
return _Height(root->_Left) > _Height(root->_Right) ?
_Height(root->_Left) + 1 : _Height(root->_Right) + 1;
}
//中序遍历
void _Inorder(Node* root)
{
if (root == NULL)
return;
_Inorder(root->_Left);
cout << "Key:"<<root->_key << " Balance Factor:"<<root->_bf<<endl;
_Inorder(root->_Right);
}
//使树平衡
void _UpdataBalanceFactor(Node*& root)
{
if ((root->_bf == -2) && (root->_Left->_bf == -1))
{
//进行右单旋
_RotateR(root);
}
else if ((root->_bf == 2) && (root->_Right->_bf) == 1)
{
//进行左单旋
_RotateL(root);
}
else if ((root->_bf == 2) && (root->_Right->_bf == -1))
{
//进行右左双旋
_RotateRL(root);
}
else
{
//进行左右双旋
_RotateLR(root);
}
}
//右单旋
void _RotateR(Node* root)
{
Node* SubL = root->_Left;
Node* SubLR = root->_Left->_Right;
Node* ppNode = root->_parent;
root->_Left = SubLR;
if (SubLR)
SubLR->_parent = root;
SubL->_Right = root;
if (root->_parent == NULL)
{
SubL->_parent = NULL;
_root = SubL;
}
else
{
SubL->_parent = ppNode;
if (ppNode->_Left == root)
ppNode->_Left = SubL;
else
ppNode->_Right = SubL;
}
root->_parent = SubL;
root->_bf = SubL->_bf = 0;
}
void _RotateL(Node* root)
{
Node* SubR = root->_Right;
Node* SubRL = root->_Right->_Left;
Node* ppNode = root->_parent;
root->_Right = SubRL;
if (SubRL)
SubRL->_parent = root;
SubR->_Left = root;
if (root->_parent == NULL)
{
_root = SubR;
SubR->_parent = NULL;
}
else
{
SubR->_parent = ppNode;
if (ppNode->_Left == root)
ppNode->_Left = SubR;
else
ppNode->_Right = SubR;
}
root->_parent = SubR;
root->_bf = SubR->_bf = 0;
}
void _RotateRL(Node* root)
{
Node* parent = root;
Node* SubR = parent->_Right;
Node* SubRL = SubR->_Left;
int bf = SubRL->_bf;
_RotateR(root->_Right);
_RotateL(root);
}
void _RotateLR(Node* root)
{
Node* parent = root;
Node* SubL = root->_Left;
Node* SubLR = SubL->_Right;
int bf = SubLR->_bf;
_RotateL(root->_Left);
_RotateR(root);
}
protected:
Node* _root;
};