下面是通過左右旋轉達到平衡和通過右旋轉達到平衡的例子:
代碼:
#include<iostream>
#include<windows.h>
using namespace std;
template<typename K, typename V>
struct AVLTreeNode
{
AVLTreeNode()
{}
AVLTreeNode(const K& _key, const V& _value = V())
: key(_key)
, value(_value)
, bf(0)
, pLeft(NULL)
, pRight(NULL)
, pParent(NULL)
{}
K key;
V value;
int bf;
AVLTreeNode *pLeft;
AVLTreeNode *pRight;
AVLTreeNode *pParent;
};
template<typename K, typename V>
class AVLTree
{
typedef AVLTreeNode<K, V> Node;
public:
AVLTree()
:pRoot(NULL)
{}
bool Inserter(const K& _key)
{
//
Node* pCur = pRoot;
Node* parent = NULL;
if (NULL == pRoot)
{
pRoot = new Node(_key);
return true;
}
else
{
//找到插入位置
while (pCur)
{
if (pCur->key < _key)
{
parent = pCur;
pCur = pCur->pRight;
}
else if (pCur->key > _key)
{
parent = pCur;
pCur = pCur->pLeft;
}
else
return false;
}
//插入結點
pCur = new Node(_key);
if (parent->key > _key)
{
parent->pLeft = pCur;
}
else
parent->pRight = pCur;
pCur->pParent = parent;
}
//自下向上更新平衡因子
while (parent)
{
//更新當前結點父節點的平衡因子
if (parent->pLeft == pCur)
{
parent->bf--;
}
else
{
parent->bf++;
}
//如果其父節點的平衡因子爲0,則說明達到平衡
if (0 == parent->bf)
{
break;
}
//如果是1,則繼續向上更新
else if (1 == parent->bf || -1 == parent->bf)
{
pCur = parent;
parent = pCur->pParent;
}
//不是1,就可能是+-2,此時子樹不平衡需要調整
//一旦parent的因子絕對值==2,說明其需要調整,此時較高子樹是相對於它而言的
else
{
//右子樹高
if (parent->bf == 2)
{
//右子樹的右側高
if (pCur->bf == 1)
{
//左旋轉
RotateLeft(parent);
break;
}
//右子樹的左側高
else
{
//右左旋轉
RotateRL(pCur);
break;
}
}
//左子樹高
else
{
//左子樹的左側高
if (pCur->bf == -1)
{
//右旋
RotateRight(parent);
break;
}
//左子樹的右側高
else
{
//左右旋轉
RotateLR(pCur);
break;
}
}
}
}
return true;
}
bool IsBalanceTree()//判斷樹是不是AVL樹
{
return _IsBalanceTree(pRoot);
}
int Hight()//求書的高度
{
return _Hight(pRoot);
}
void InOrder()
{
_InOrder(pRoot);
cout << endl;
}
private:
bool _IsBalanceTree(Node *pRoot)
{
if (NULL == pRoot)
return true;
int left = _Hight(pRoot->pLeft);
int right = _Hight(pRoot->pRight);
if (pRoot->bf != (right - left) || std::abs(pRoot->bf) > 1)
return false;
return _IsBalanceTree(pRoot->pLeft) && _IsBalanceTree(pRoot->pRight);
}
void _InOrder(Node* pRoot)
{
if (NULL == pRoot)
return;
_InOrder(pRoot->pLeft);
cout << pRoot->key << " ";
_InOrder(pRoot->pRight);
}
int _Hight(Node* pRoot)
{
if (NULL == pRoot)
return 0;
if (NULL == pRoot->pLeft && NULL == pRoot->pRight)
return 1;
int left = _Hight(pRoot->pLeft)+1;
int right = _Hight(pRoot->pRight)+1;
return left > right ? left : right;
}
//左旋---->就是用父節點的右孩子去替換父節點,將父節點連接在其右孩子的左側
void RotateLeft(Node *parent)
{
Node* pParent = parent->pParent;
Node* pSubR = parent->pRight;
Node* pSubRL = pSubR->pLeft;
//父節點的右鏈接右孩子的左結點
parent->pRight = pSubRL;
//右孩子成爲父節點的父節點
parent->pParent = pSubR;
//右孩子的左結點存在,更新其父節點
if (pSubRL)
pSubRL->pParent = parent;
//更新右孩子的父節點和左結點
pSubR->pParent = pParent;
pSubR->pLeft = parent;
//如果pParent存在
if (pParent)
{
//說明這是一顆子樹
//將右節點連接在pParent的左或者右
if (pParent->pLeft == parent)
{
pParent->pLeft = pSubR;
}
else
{
pParent->pRight = pSubR;
}
}
//pParent不存在,說明父節點是樹根
else//這是樹根將變爲右節點
pRoot = pSubR;
//將其平衡因子置0
parent->bf = pSubR->bf = 0;
}
//右旋
void RotateRight(Node* parent)
{
Node* pParent = parent->pParent;
Node* pSubL = parent->pLeft;
Node* pSubLR = pSubL->pRight;
parent->pLeft = pSubLR;
parent->pParent = pSubL;
if (pSubLR)
pSubLR->pParent = parent;
pSubL->pParent = pParent;
pSubL->pRight = parent;
if (pParent)
{
if (pParent->pLeft == parent)
pParent->pLeft = pSubL;
else
pParent->pRight = pSubL;
}
else
{
pRoot = pSubL;
}
parent->bf = pSubL->bf = 0;
}
//左右旋轉
void RotateLR(Node* parent)
{
//判斷其右孩子的平衡因子
int bf = parent->pRight->bf;
//parent左旋,parent下降其父節點成爲其父節點的父節點
RotateLeft(parent);
//parent之前的父節點右旋
RotateRight(parent->pParent->pParent);
if (bf == -1)
{//說明parent接受了其右孩子的左孩子,
parent->pParent->pRight->bf = 1;
}
else if (1 == bf)
{
//說明parent的父節點,接受了其右孩子的右孩子
parent->bf = -1;
}
}
//右左旋轉
void RotateRL(Node* parent)
{
int bf = parent->pLeft->bf;
RotateRight(parent);
RotateLeft(parent->pParent->pParent);
if (1 == bf)
{
parent->pParent->pLeft->bf = -1;
}
else if (-1 == bf)
{
parent->bf = 1;
}
}
protected:
Node* pRoot;
};