1.AVL樹的概念:
AVL樹或則是空樹,或是具有下列性質的二叉搜索樹
- 它的左右子樹都是AVL樹;
- 左子樹和右子樹的高度之差簡稱(平衡因子)的絕對值不超過1;
2.AVL樹的實現原理
與二叉搜索樹的節點插入方法相同,具體步驟如下:
當樹不平衡時,我們需要做出旋轉調整,有四種調整方法,分別爲右單旋、左單旋、先左單旋再右單旋、先右單旋在左單旋
左單旋
右單旋
先右旋再左旋
先左旋再右旋
3.代碼實現
#include<stdio.h>
#include<iostream>
using namespace std;
template<class k,class v>
struct AVLTreeNode
{
AVLTreeNode(const k& key,const v& value)
:_key(key)
,_value(value)
,_bf(0)
,_pLeft(NULL)
,_pRight(NULL)
,_pParent(NULL)
{}
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
{
public:
typedef AVLTreeNode<k,v> Node;
AVLTree()
:_pRoot(NULL)
{}
bool Insert(const k& key,const v& value)//插入節點
{
return _Insert(key,value);
}
bool IsBalanceTree()
{
return _IsBalanceTree(_pRoot);
}
private:
bool _IsBalanceTree(Node* pRoot)//判斷該樹是否是平衡二叉樹
{
if(pRoot == NULL)
return true;
size_t leftHeight = _Height(pRoot->_pLeft);
size_t rightHeight = _Height(pRoot->_pRight);
if(rightHeight-leftHeight != pRoot->_bf || abs(pRoot->_bf)>1)
{
cout<<pRoot->_key<<"-->"<<pRoot->_bf<<endl;
return false;
}
return _IsBalanceTree(pRoot->_pLeft)&&_IsBalanceTree(pRoot->_pRight);
}
size_t _Height(Node* pRoot)
{
if(pRoot == NULL)
return 0;
if(pRoot->_pLeft == NULL && pRoot->_pRight == NULL)
return 1;
size_t leftHeight = _Height(pRoot->_pLeft);
size_t rightHeight = _Height(pRoot->_pRight);
return 1+(leftHeight > rightHeight? leftHeight:rightHeight);
}
bool _Insert(const k& key,const v& value)
{
if(_pRoot == NULL)
{
_pRoot = new Node(key,value);
return true;
}
//找到要插入節點的位置
Node* pCur = _pRoot;
Node* pParent = NULL;
while(pCur)
{
if(key < pCur->_key)
{
pParent = pCur;
pCur = pCur->_pLeft;
}
else if(key > pCur->_key)
{
pParent = pCur;
pCur = pCur->_pRight;
}
else
return false;
}
//已經找到插入位置
pCur = new Node(key,value);
if(pParent->_key < key)
{
pParent->_pRight = pCur;
pCur->_pParent = pParent;
}
else
{
pParent->_pLeft = pCur;
pCur->_pParent = pParent;
}
while(pParent)
{
//更新平衡因子
if(pParent->_pLeft == pCur)
(pParent->_bf)--;
else
(pParent->_bf)++;
if(pParent->_bf == 0)//pParent只有左孩子或者只有右孩子,在其空指針域插入一個節點後,平衡因子爲0,
return true; //此時樹的高度沒有發生變化,該樹任然是是AVL樹
else if(pParent->_bf == -1 || pParent->_bf == 1)//pParent是葉子節點,插入節點後其平衡因子可能是1或-1
{ //此時樹的高度可能發生了改變,我們要向上判斷其祖先節點是否平衡
pCur = pParent;
pParent = pCur->_pParent;
}
else
{
//不滿足平衡樹,要做旋轉處理
if(pParent->_bf == 2)//右子樹
{
if(pCur->_bf == 1)//右側
_RotateL(pParent);//左旋調整
else//左側
_RotateRL(pParent);//先右旋再左旋
}
else//左子樹
{
if(pCur->_bf == -1)//左側
_RotateR(pParent);
else//右側
_RotateLR(pParent);
}
break;//調整完後跳出循環
}
}
return true;
}
void InOrder()
{
cout<<"InOrder ";
_InOrder(_pRoot);
cout<<endl;
}
private:
void _InOrder(Node*& pRoot)
{
if(pRoot)
{
_InOrder(pRoot->_pLeft);
cout<<pRoot->_key<<" ";
_InOrder(pRoot->_pRight);
}
}
void _RotateL(Node* pParent)
{
Node* pSubR = pParent->_pRight;
Node* pSubRL =pSubR->_pLeft;
pParent->_pRight = pSubRL;
if(pSubRL)//情況四之一
pSubRL->_pParent = pParent;
pSubR->_pLeft = pParent;
Node* pPParent = pParent->_pParent;
pParent->_pParent = pSubR;
if(pPParent == NULL)
{
_pRoot = pSubR;
pSubR->_pParent = NULL;
}
else if(pPParent->_pLeft == pParent)
{
pPParent->_pLeft = pSubR;
pSubR->_pParent = pPParent;
}
else
{
pPParent->_pRight = pSubR;
pSubR->_pParent = pPParent;
}
//更新平衡因子
pParent->_bf = pSubR->_bf = 0;
}
void _RotateR(Node* pParent)
{
Node* pSubL = pParent->_pLeft;
Node* pSubLR = pParent->_pRight;
pParent->_pLeft = pSubLR;
if(pSubLR)
pSubLR->_pParent = pParent;
pSubL->_pRight = pParent;
Node* pPParent = pParent->_pParent;
pParent->_pParent = pSubL;
if(pPParent == NULL)
{
_pRoot = pSubL;
pSubL->_pParent = NULL;
}
else if(pPParent->_pLeft == pParent)
{
pPParent->_pLeft = pSubL;
pSubL->_pParent = pPParent;
}
else
{
pPParent->_pRight = pSubL;
pSubL->_pParent = pPParent;
}
//更新平衡因子
pParent->_bf = pSubL->_bf = 0;
}
void _RotateRL(Node* pParent)//先右單旋再左單旋
{
Node* pSubR = pParent->_pRight;
Node* pSubRL = pSubR->_pLeft;
int bf = pSubRL->_bf;
_RotateR(pParent->_pRight);
_RotateL(pParent);
//判斷平衡因子應該如何更新
if(bf == 1)
pParent->_bf = -1;
else
pSubR->_bf = 1;
}
void _RotateLR(Node* pParent)//先左單旋再右單旋
{
Node* pSubL = pParent->_pLeft;
Node* pSubLR = pSubL->_pRight;
int bf = pSubLR->_bf;
_RotateL(pParent->_pLeft);
_RotateR(pParent);
//判斷平衡因子應該如何修改
if(bf == 1)
pSubL->_bf = -1;
else
pParent->_bf = 1;
}
private:
Node* _pRoot;
};
測試代碼:
void funtest()
{
int array[] = {2,1,4,3,5,6};//測試左單旋
AVLTree<int,int> bst;
for(size_t idx= 0 ;idx < sizeof(array)/sizeof(array[0]);++idx)
bst.Insert(array[idx],idx);
AVLTree<int,int> bst1;
int array1[] = {5,3,6,2,1,4};//測試右單旋
for(size_t idx1= 0 ;idx1 < sizeof(array1)/sizeof(array1[0]);++idx1)
bst1.Insert(array1[idx1],idx1);
}
void funtest1()
{
int array[] = {3,2,1,4,5,6,7,10,9,8};//測試左單旋
AVLTree<int,int> bst;
for(size_t idx= 0 ;idx < sizeof(array)/sizeof(array[0]);++idx)
bst.Insert(array[idx],idx);
if(bst.IsBalanceTree())
{
cout<<"IS AVLTree"<<endl;
}
else
{
cout<<"NO IS AVLTree"<<endl;
}
}
int main()
{
//funtest();
funtest1();
getchar();
return 0;
}