以下图的平衡因子统一为左子树高度减去右子树高度。
附上:单个节点声明的代码
struct AVLTreeNode
{
AVLTreeNode(const K& key, const V& value)
: _pLeft(NULL)
, _pRight(NULL)
, _pParent(NULL)
, _key(key)
, _value(value)
, _bf(0)
{}
AVLTreeNode<K, V> *_pLeft;
AVLTreeNode<K, V> *_pRight;
AVLTreeNode<K, V> *_pParent;
K _key;
V _value;
int _bf; // 平衡因子:right-left
};
左单旋 (右右 - 在较高右子树的右侧插入节点)
具体列子
分析
如图能引发左单旋,那必定是在引起不平衡的节点的较高右字树的右侧插入,至于这个点是在节点C的左边插入还是右边插入都没有关系,都可以通过左旋转达到平衡,这个平衡后的图如上所示,真正发生变化的点,一个SubR一个引发不平衡的节点,而再引发旋转后这俩个点都平衡了,平衡因子为0。
附上 - 左单旋代码:
void _RotateL(Node* pParent)
{
if (pParent)
{
Node *pPParent = pParent->_pParent;
Node * pSubR = pParent->_pRight;
Node * pSubRL = pParent->_pLeft;
if (pSubRL)
{
pSubRL->_pParent = pParent;
}
pParent->_pRight = pSubRL;
pSubR->_pLeft = pParent;
pParent->_pParent = pSubR;
pSubR->_pParent = pPParent;
if (pPParent == NULL)
{
_pRoot = pSubR;
}
else
{
if (pPParent->_pLeft == pParent) pPParent->_pLeft = pSubR;
else
pPParent->_pRight = pSubR;
}
pSubR->_bf = 0;
pParent->_bf = 0;
}
}
右单旋 (左左-在较高左子树中的左侧插入节点)
图示
附上 -右单旋代码:
void _RotateR(Node* pParent)
{
if (pParent)
{
Node*pPParent = pParent->_pParent;
Node*pSubL = pParent->_pLeft;
Node*pSubLR = pSubL->_pRight;
if (pSubLR)
{
pSubLR->_pParent = pParent;
}
pParent->_pLeft = pSubLR;
pParent->_pParent = pSubL;
pSubL->_pRight = pParent;
pSubL->_pParent = pPParent;
if (pPParent==NULL)
{
_pRoot = pSubL;
}
else
{
if (pParent->_pRight == pParent)pParent->_pRight = pSubL;
else
pParent->_pLeft = pSubL;
}
pSubL->_bf = 0;
pParent->_bf = 0;
}
}
右左双旋(右左-在较高右子树的左侧插入)
分析
如下面这个图,这里双旋有三种情况:
1.h为0的时候,那么 10 无左子树,30无右子树,20这个节点必定是新增节点,因为20和它子树高度和为h , h 为0说明20不存在,它这里是新增节点。那这个时候20的平衡因子是0。
2.当新增节点在20这个节点的左子树的情况下,20 节点为-1。这个时候双旋完后 , b的高度新增完后为h , 它给了10之后,10的节点的平衡因子平衡了,但是 c 跟了30,30 此时 平衡因子为1。
3.当新增节点在C,20节点平衡因子为1。这时候双旋完后,C跟了30,C的高度新增后为 h ,那么 30此时是平衡的,相反 高度 为 h-1 的 b跟了10,那么此时10的平衡因子是-1。
图示
void _RotateRL(Node* pParent)
{
Node *PsubR = pParent->_pRight;
Node* pSubRL = PsubR->_pLeft;
int bf = pSubRL->_bf;
_RotateR(pParent->_pRight);
_Rotate(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) pParent->_bf = -1;
else PsubL->_bf = 1;
}
整个AVL树的实现
#include<iostream>
#include<assert.h>
using namespace std;
template<class K , class V>
struct AVLTreeNode
{
public:
using Node = AVLTreeNode<K, V>;
AVLTreeNode(const K & key, const V & value)
:_pLeft(NULL), _pRight(NULL), _pParent(NULL), _Key(key), _value(value), _bf(0)
{}
Node * _pLeft;
Node * _pRight;
Node * _pParent;
K _Key;
V _value;
int _bf;
};
template<class K , class V>
class AVLTree
{
typedef AVLTreeNode<K,V> Node;
public:
AVLTree()
:_root(nullptr)
{}
AVLTree(const K arr[], size_t size)
{
for (size_t idx = 0 l idx < size; ++idx)
{
Insert(idx, arr[idx]);
}
}
bool Insert(const K& key, const V & value)
{
if (nullptr == _root)
{
_root = new Node(key, value);
return false;
}
else
{
Node * pCur = _root;
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;
pCur->_pParent = parent;
}
else
{
parent->_pRight = pCur;
pCur->_pParent = parent;
}
while (parent)
{
if (pCur == parent->_pLeft)
parent->_bf--;
else
parent->_bf++;
if (parent->_bf == 0)
return true;
else if (parent->_bf == -1 || parent->_bf == 1)
{
pCur = parent;
parent = pCur->_pParent;
}
else if (parent->_bf==-2||parent->_bf == 2)
{
/*旋转*/
if (parent->_bf == 2 && parent->_pRight->_bf == 1) // bf==2 说明parent的右子树高 , 那么我们可以查看右子树的bf的值,bf==1在右子树右侧插入,bf==-1 在右子树左侧插入
RotateL(parent);
else if (parent->_bf == 2 && parent->_pRight->_bf == -1)
RotateRL(parent);
else if (parent->_bf == -2 && parent->_pLeft->_bf == -1)
RotateR(parent);
else if (parent->_bf == -2 && parent->_pLeft->_bf == 1)
RotateLR(parent);
break;
}
else
{
cerr << "有bug!!!!在插入的时候" << endl;
assert(false);
}
}
}
}
protected:
void RotateL(Node * parent) // 向左旋转
{
Node*SubR = parent->_pRight;
Node*SubRL = SubR->_pLeft;
Node*grandfather = parent->_pParent;
if (SubRL)
SubRL->_pParent = parent;
parent->_pRight = SubRL;
SubR->_pLeft = parent;
if (grandfather)
{
if (grandfather->_pLeft == parent)
grandfather->_pLeft = SubR;
else
grandfather->_pRight = SubR;
}
else
{
_root = SubR;
SubR->_pParent = NULL;
}
parent->_pParent = SubR;
SubR->_pParent = grandfather;
parent->_bf = 0;
SubR->_bf = 0;
}
void RotateR(Node * parent) //向右旋转
{
Node * SubL = parent->_pLeft;
Node * SubLR = SubL->_pRight;
Node * grandfather = parent->_pParent;
if (SubLR)
SubLR->_pParent = parent;
parent->_pLeft = SubLR;
SubL->_pRight = parent;
if (grandfather)
{
if (grandfather->_pLeft == parent)
grandfather->_pLeft = SubL;
else
grandfather->_pRight = SubL;
}
else
{
_root = SubL;
SubL->_pParent = NULL;
}
parent->_pParent = SubL;
SubL->_pParent = grandfather;
parent->_bf = 0;
SubL->_bf = 0;
}
void RotateLR(Node* parent)
{
Node*SubL = parent->_pLeft;
Node*SubLR = SubL->_pRight;
int bf = SubLR->_bf;
RotateL(SubL);
RotateR(parent);
if (bf == 1)
SubL->_bf = -1;
if (bf == -1)
parent->_bf = 1;
}
void RotateRL(Node* parent)
{
Node*SubR = parent->_pRight;
Node*SubRL = SubR->_pLeft;
int bf = SubRL->_bf;
RotateR(SubR);
RotateL(parent);
if (bf == 1)
parent->_bf = -1;
if (bf == -1)
SubR->_bf = 1;
}
public:
Node * const GetRoot()
{
return _root;
}
void Inorder(Node*Root)
{
if (Root==NULL)
return;
Inorder(Root->_pLeft);
cout << Root->_Key<<" " ;
Inorder(Root->_pRight);
}
bool IsBalance(Node*Root)
{
int Height=0;
return _IsBalance(Root, Height);
}
private:
bool _IsBalance(Node*Root, int & Height)
{
if (Root == NULL)
{
Height = 0;
return true;
}
int left = 0;
if (!_IsBalance(Root->_pLeft, left))
return false;
int right = 0;
if (!_IsBalance(Root->_pRight, right))
return false;
Height = (left > right) ? left + 1 : right + 1;
return abs(left-right) < 2;
}
private:
Node * _root;
};
void TesTAVL()
{
int arr[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
AVLTree<int,int> Tree;
for (int i = 0; i<sizeof(arr) / sizeof(arr[0]);++i)
{
Tree.Insert(arr[i],i);
}
AVLTreeNode<int, int> * Root = Tree.GetRoot();
Tree.Inorder(Root);
if (Tree.IsBalance(Root))
co(left-right) < 2;
}ut << "AVL树平衡的" << endl;
}
int main()
{
TesTAVL();
return 0;
}
判断平衡的方法
方法1 时间复杂度 O(N^2)
bool Height (Node * Root)
{
if(Root == NULL )
return 0;
if(Root->_pleft==NULL&&Root->_pRight==NULL)
{
return 1;
}
int left = Height(Root->_pleft);
int Right = Height(Root->_pRight);
return (left>right)? left+1: right+1;
}
bool IsBalance(Node*Root)
{
if(Root==NULL)
true;
int left = Height(Root->_pLeft);
int Right = Height(Root->_pRight);
return abs(left-Right)<2&&IsBalance(Root->_pLeft)&&IsBalance(Root->_pRight);
}
方法2 时间复杂度O(N)
bool IsBalance(Node*Root)
{
int Height=0;
return _IsBalance(Root, Height);
}
private:
bool _IsBalance(Node*Root, int & Height)
{
if (Root == NULL)
{
Height = 0;
return true;
}
int left = 0;
if (!_IsBalance(Root->_pLeft, left))
return false;
int right = 0;
if (!_IsBalance(Root->_pRight, right))
return false;
Height = (left > right) ? left + 1 : right + 1;
return abs(left-right) < 2;
}