一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:
1. 它的左右子树都是AVL树
2. 左子树和右子树高度之差(简称平衡因子)的绝对值不超过1(-1、0、1)
如果一棵二叉搜索树是高度平衡的,它就是AVL树。如果它有n个结点,其高度可保持在O(lgn),平均搜索时间复杂度O(lg(n))
在二叉搜索树中,我们知道要插入一个元素,必须将他插到合适的位置,但是在AVL树中,不仅要插入到合适的位置,还要保证插入该元素之后这棵树是平衡搜索二叉树。
关于如何调整一棵二叉树为平衡二叉树,这里就涉及到四种旋转:
左单旋,右单旋,左右双旋,右左双旋。
下边就每一种旋转都给出图示:
这是需要左单旋的情况
这是需要右单旋的情况
这是需要右左双旋的情况
这是需要左右双旋的情况
代码如下
#include<iostream>
using namespace std;
template<class K,class V>
struct AVLTreeNode
{
AVLTreeNode(const K &key, const V &value)
:_key(key)
, _value(value)
, _pLeft(nullptr)
, _pRight(nullptr)
, _pParent(nullptr)
, _bf(0)
{}
AVLTreeNode<K, V> *_pLeft;
AVLTreeNode<K, V> *_pRight;
AVLTreeNode<K, V> *_pParent;
K _key;
V _value;
int _bf;
};
template<class K,class V>
class AVLTree
{
private:
typedef AVLTreeNode<K, V> Node;
public:
AVLTree() :_pRoot(nullptr)
{}
void InOrder()
{
cout << "InOrder:" << endl;
_InOrder(_pRoot);
cout << endl;
}
void Insert(const K &key, const V &value)
{
_Insert(_pRoot, key, value);
}
bool IsBalanceTree()
{
return _IsBalanceTree(_pRoot);
}
private:
bool _Insert(Node *pRoot, const K &key, const V &value)
{
if (nullptr == pRoot)
{
_pRoot = new Node(key, value);
return true;
}
Node *pCur = pRoot;
Node *parent = nullptr;
while (pCur)
{
if (key < pCur->_key)
{
parent = pCur;
pCur = pCur->_pLeft;
}
else if (key > pCur->_key)
{
parent = pCur;
pCur = pCur->_pRight;
}
else
{
return false;
}
}
pCur = new Node(key, value);
if (key < parent->_key)
parent->_pLeft = pCur;
else
parent->_pRight = pCur;
pCur->_pParent = parent;
if (pCur == parent->_pLeft)
--parent->_bf;
else
++parent->_bf;
while (nullptr != parent)
{
if (0==parent->_bf)
return true;
else if (1 == parent->_bf || -1 == parent->_bf)
{
Node *ppParent = parent->_pParent;
if (nullptr != ppParent)
{
if (ppParent->_pLeft == parent)
ppParent->_bf--;
else
ppParent->_bf++;
}
parent = parent->_pParent;
}
else
{
if (2 == parent->_bf)
{
if (1 == parent->_pRight->_bf)
_RotateL(parent);
else
_RotateRL(parent);
}
else
{
if (-1 == parent->_pLeft->_bf)
_RotateR(parent);
else
_RotateLR(parent);
}
break;
}
}
return true;
}
void _InOrder(Node *pRoot)
{
if (pRoot)
{
_InOrder(pRoot->_pLeft);
cout << pRoot->_key << " ";
_InOrder(pRoot->_pRight);
}
}
void _RotateL(Node *parent)
{
Node *pSubR = parent->_pRight;
Node *ppParent = parent ->_pParent;
Node *pSubRL = pSubR->_pLeft;
parent->_pRight = pSubRL;
if (nullptr != pSubRL)
pSubRL->_pParent = parent;
pSubR->_pLeft = parent;
parent->_pParent = pSubR;
if (nullptr == ppParent)
{
_pRoot = pSubR;
pSubR->_pParent = nullptr;
}
else
{
if (parent == ppParent->_pLeft)
ppParent->_pLeft=pSubR;
else
ppParent->_pRight=pSubR;
pSubR->_pParent = ppParent;
}
parent->_bf = pSubR->_bf = 0;
parent = pSubR;
}
void _RotateR(Node *parent)
{
Node *pSubL = parent->_pLeft;
Node *pSubLR = pSubL->_pRight;
Node *ppParent = parent->_pParent;
parent->_pLeft = pSubLR;
if (pSubLR)
pSubLR->_pParent = parent;
pSubL->_pRight = parent;
parent->_pParent = pSubL;
if (nullptr == ppParent)
{
_pRoot = pSubL;
pSubL->_pParent = nullptr;
}
else
{
if (parent == ppParent->_pLeft)
ppParent->_pLeft = pSubL;
else
ppParent->_pRight = pSubL;
pSubL->_pParent = ppParent;
}
pSubL->_bf = parent->_bf = 0;
parent = pSubL;
}
void _RotateRL(Node *parent)
{
Node *pSubR = parent->_pRight;
Node *pSubRL = pSubR->_pLeft;
int SubRLf = pSubRL->_bf;
_RotateR(parent->_pRight);
_RotateL(parent);
if (1 == SubRLf)
parent->_bf = -1;
else if (-1 == SubRLf)
pSubR->_bf = 1;
}
void _RotateLR(Node *parent)
{
Node *pSubL = parent->_pLeft;
Node *pSubLR = pSubL->_pRight;
int SubLRf = pSubLR->_bf;
_RotateL(parent->_pLeft);
_RotateR(parent);
if (-1 == SubLRf)
parent->_bf = 1;
else if (1 == SubLRf)
pSubL->_bf = -1;
}
size_t _Height(Node *pRoot)
{
if (nullptr == pRoot)
return 0;
if (nullptr == pRoot->_pLeft&&nullptr == pRoot)
return 1;
size_t leftHeight = _Height(pRoot->_pLeft);
size_t rightHeight = _Height(pRoot->_pRight);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
bool _IsBalanceTree(Node *pRoot)
{
if (pRoot == nullptr)
return true;
int leftHeight = _Height(pRoot->_pLeft);
int rightHeight = _Height(pRoot->_pRight);
if (rightHeight - leftHeight != pRoot->_bf)
{
cout << "平衡因子错误" << endl;
return false;
}
return (abs(leftHeight - rightHeight) <2)&&_IsBalanceTree(pRoot->_pLeft)&&_IsBalanceTree(pRoot->_pRight);
}
private:
Node *_pRoot;
};
void test1()
{
int a[10] = { 3, 2, 1, 4, 5, 6, 7, 10, 9, 8 };
AVLTree<int, int> avl;
for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
avl.Insert(a[i], a[i]);
cout << avl.IsBalanceTree() << endl;
avl.InOrder();
}
void test2()
{
int array2[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
AVLTree<int, int> avl;
for (int i = 0; i < sizeof(array2) / sizeof(array2[0]); i++)
avl.Insert(array2[i], array2[i]);
cout << avl.IsBalanceTree() << endl;
avl.InOrder();
}
void test3()
{
int array1[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
AVLTree<int, int> avl;
for (int i = 0; i < sizeof(array1) / sizeof(array1[0]); i++)
avl.Insert(array1[i], array1[i]);
cout << avl.IsBalanceTree() << endl;
avl.InOrder();
}
int main()
{
test1();
test2();
test3();
system("pause");
}