AVLTree就是平衡因子的绝对值不超过1的二叉搜索树,而平衡因子就是右子树的高度减去左子树的高度多得到的值,由二叉搜索树的性质我们可以知道,它比二叉搜索树的要求更为严格,因为二叉搜索树如果遇到的是一个特殊的有序的序列,那么二叉搜索树就会退化成一个链表,如图:
此时,二叉搜索树的时间复杂度就是o(n),而AVLTree由于平衡因子的绝对值不超过1,所以,它的时间复杂度就是o(log n),这也是AVLTree的优点所在。
重点是TVLTree的平衡因子的保证,这就要在结点插入的时候将这棵树进行一个调平(旋转)操作,使得平衡因子的绝对值不超过1,比如上图的情况调平之后就是:
当然这只是一种情况,具体调平操作有四类:
(1)左单旋
(2)右单旋
(3)左右双旋(分两种)
(4)右左双旋(分两种)
代码实现:
#pragma once
template <class K,class V>
struct AVLTreeNode
{
int _bf; //平衡因子
K _key;
V _value;
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent;
AVLTreeNode(const K& key,const V& value)
:_bf(0)
,_key(key)
,_value(value)
,_left(NULL)
,_right(NULL)
,_parent(NULL)
{}
};
template <class K,class V>
class AVLTree
{
typedef AVLTreeNode<K, V> Node;
public:
AVLTree()
:_root(NULL)
{}
bool Insert(const K& key, const V& value)
{
//将结点插入
//1.为空时直接新创建一个结点
if (NULL == _root)
{
_root = new Node(key, value);
return true;
}
else //寻找插入位置
{
Node* cur = _root;
Node* parent = NULL;
while (cur)
{
// 左小又大
if (key < cur->_key)
{
parent = cur;
cur = cur->_left;
}
else if (key > cur->_key)
{
parent = cur;
cur = cur->_right;
}
else
return false;
}//出循环即为找到相应位置
cur = new Node(key, value);
//按照大小关系进行连接
if (key < parent->_key)
{
parent->_left = cur;
cur->_parent = parent;
}
else
{
parent->_right = cur;
cur->_parent = parent;
}
//更新平衡因子
while (parent)
{
if (cur == parent->_left)
parent->_bf--; //插入节点在左侧,左树高度增加一,平衡因子减一
else
parent->_bf++; //插入节点在右侧,右树高度增加一,平衡因子加一
if (0 == parent->_bf)
{
break; // 插入后,平衡因子为零,不用调平
}
else if (1 == parent->_bf || -1 == parent->_bf)
{
cur = parent;
parent = cur->_parent; //插入后,平衡因子为1或-1,则继续想根结点更新
}
else
{
if (2 == parent->_bf) //插入后,平衡因子为2,需要旋转(具体结合前面的图分析)
{
//1.左单旋
Node* subR = parent->_right;
if (1 == subR->_bf)
{
RotateL(parent);
}
//2.左右双旋
else
{
RotateRL(parent);
}
}
else if (-2 == parent->_bf)
{
//1.右单旋
Node* subL = parent->_left;
if (-1 == subL->_bf)
{
RotateR(parent);
}
//2.右左双旋
else
{
RotateLR(parent);
}
}
break;
}
}
return true;
}
return false;
}
//中序遍历
void InOrder()
{
_InOrder(_root);
cout << endl;
}
bool IsBalance() //检验是否平衡
{
int height = 0;
return _IsBalance(_root, height);
}
protected:
// height 传引用的原因:要将每一层的结点个数加在一起
bool _IsBalance(Node* root, int& height)
{
if (root == NULL)
{
height = 0;
return true;
}
int left, right;
if (_IsBalance(root->_left, left) && _IsBalance(root->_right, right)
&& abs(right - left) < 2)
{
height = left > right ? left + 1 : right + 1;
if (root->_bf != right - left)
{
cout << "该结点平衡因子异常: " << root->_key << endl;
return false;
}
return true;
}
else
{
return false;
}
}
//右单旋
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
subL->_right = parent;
Node* ppNode = parent->_parent;
parent->_parent = subL;
if (NULL == ppNode)
{
_root = subL;
subL->_parent = NULL;
}
else
{
if (ppNode->_left == parent)
ppNode->_left = subL;
else
ppNode->_right = subL;
subL->_parent = ppNode;
}
parent->_bf = subL->_bf = 0;
}
//左单旋
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subR)
subR->_parent = parent;
subR->_left = parent;
Node* ppNode = parent->_parent;
parent->_parent = subR;
if (parent == _root)
{
_root = subR;
subR->_parent = NULL;
}
else
{
if (ppNode->_left == parent)
ppNode->_left = subR;
else
ppNode->_right = subR;
subR->_parent = ppNode;
}
parent->_bf = subR->_bf = 0;
}
void RotateLR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
int bf = subLR->_bf;
RotateL(subL);
RotateR(parent);
if (0 == bf)
{
subLR->_bf = parent->_bf = subL->_bf = 0;
}
else if (-1 == bf)
{
parent->_bf = 1;
subL->_bf = subLR->_bf = 0;
}
else if (1 == bf)
{
parent->_bf = subLR->_bf = 0;
subL->_bf = -1;
}
}
void RotateRL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
int bf = subRL->_bf;
RotateR(subR);
RotateL(parent);
if (0 == bf)
{
parent->_bf = subRL->_bf = subR->_bf = 0;
}
else if (-1 == bf)
{
parent->_bf =subRL->_bf = 0 ;
subR->_bf = 1;
}
else if (1 == bf)
{
parent->_bf = -1;
subR->_bf = subRL->_bf = 0;
}
}
void _InOrder(Node* root)
{
if (NULL == root)
{
return;
}
_InOrder(root->_left);
cout << root->_key << " ";
_InOrder(root->_right);
}
protected:
Node* _root;
};
测试用例1(简单):
void TestAVLTree1()
{
AVLTree<int, int> t1;
int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
{
t1.Insert(a[i], i);
cout << a[i] << "结点IsBalance? " << t1.IsBalance() << endl;
}
cout << "中序遍历:";
t1.InOrder();
cout << "t1 IsBalance? " << t1.IsBalance() << endl;
}
运行结果:
测试用例2(复杂):
void TestAVLTree2()
{
AVLTree<int, int> t2;
int a1[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
for (size_t i = 0; i < sizeof(a1) / sizeof(a1[0]); ++i)
{
t2.Insert(a1[i], i);
cout<<a1[i]<<"结点IsBalance? "<<t2.IsBalance()<<endl;
}
cout << "中序遍历:";
t2.InOrder();
cout << "t2 IsBalance? " << t2.IsBalance() << endl;
}
运行结果: