AVL树 是 高度平衡二叉搜索树 ,通过平衡因子来严格控制二叉搜索树的高度差不大于1 ,以达到提高增删查改为O(logn)的复杂度
bf 因子为正则说明右子树大,为负则相反
AVL树 的旋转
主要分为4种情况
1. 左单旋(bf因子为正,右边过高,提高左边高度,减少右边高度)(六个指针的改变)
旋转后 节点的 bf 均为 0
3. 右左双旋
初始父亲结点bf=2,儿子bf=-1 ,
先考虑儿子,左树大右旋,在考虑父亲,右树大左旋
4.双旋过后 父子 bf 取值 的3种情况
a. 上图为第一种 3rd 的左边树大 parent(1st) bf =-1 其他 =0
b. 3rd 的右树小 接到了1st上左边 2nd bf =1, 其他 =0
c. 3rd 结点bf 为0 最后bf全是 0
代码实现如下,注意画图包含所有情况即可
#include <iostream>
#include <cmath>
#include <assert.h>
using namespace std;
template <class T>
struct AVLTreeNode
{
AVLTreeNode(const T &data = T())
: _pLeft(nullptr), _pRight(nullptr), _pParent(nullptr), _data(data), _bf(0)
{
}
AVLTreeNode<T> *_pLeft;
AVLTreeNode<T> *_pRight;
AVLTreeNode<T> *_pParent;
T _data;
int _bf; // 节点的平衡因子
};
// AVL: 二叉搜索树 + 平衡因子的限制
template <class T>
class AVLTree
{
typedef AVLTreeNode<T> Node;
public:
AVLTree()
: _pRoot(nullptr)
{
}
// 在AVL树中插入值为data的节点
bool Insert(const T &data)
{
if (_pRoot == nullptr)
{
_pRoot = new Node(data);
return true;
}
Node *parent = nullptr;
Node *cur = _pRoot;
while (cur)
{
if (data < cur->_data)
{
parent = cur;
cur = cur->_pLeft;
}
else if (data > cur->_data)
{
parent = cur;
cur = cur->_pRight;
}
else
{
return false;
}
}
cur = new Node(data);
if (data < parent->_data)
{
parent->_pLeft = cur;
}
else
{
parent->_pRight = cur;
}
cur->_pParent = parent;
while (parent)
{
if (cur == parent->_pLeft)
{
parent->_bf--;
}
else
{
parent->_bf++;
}
if (parent->_bf == 0)
{
break;
}
else if (abs(parent->_bf) == 1)
{
cur = cur->_pParent;
parent = parent->_pParent;
}
else if (abs(parent->_bf) == 2)
{
if (parent->_bf == 2 && cur->_bf == 1)
{
RotateL(parent);
}
else if (parent->_bf == 2 && cur->_bf == -1)
{
RotateRL(parent);
}
else if (parent->_bf == -2 && cur->_bf == 1)
{
RotateLR(parent);
}
else if (parent->_bf == -2 && cur->_bf == -1)
{
RotateR(parent);
}
else
{
cout << parent->_bf << ' ' << cur->_bf <<'\n';
assert(false);
}
break;
}
else
{
assert(false);
}
}
return true;
}
// AVL树的验证
bool IsAVLTree()
{
return _IsAVLTree(_pRoot);
}
void InOrder()
{
_Inordered(_pRoot);
}
private:
// 根据AVL树的概念验证pRoot是否为有效的AVL树
bool _IsAVLTree(Node *pRoot)
{
if (pRoot)
{
return true;
}
int Hleft = _Height(pRoot->_pLeft);
int Hright = _Height(pRoot->_pRight);
int diff = Hright - Hleft;
if (diff != pRoot->_bf)
{
cout << pRoot->_data << "异常" <<'\n';
}
return abs(diff) <= 2
&& _IsAVLTree(pRoot->_pLeft)
&& _IsAVLTree(pRoot->_pRight);
}
size_t _Height(Node *pRoot)
{
if (pRoot == nullptr)
{
return 0;
}
return max(_Height(pRoot->_pLeft), _Height(pRoot->_pRight)) + 1;
}
// 右单旋
void RotateR(Node *pParent)
{
Node *ppNode = pParent->_pParent;
Node *subL = pParent->_pLeft;
Node *subLR = subL->_pRight;
pParent->_pLeft = subLR;
if (subLR)
{
subLR->_pParent = pParent;
}
pParent->_pParent = subL;
subL->_pRight = pParent;
if (pParent == _pRoot)
{
_pRoot = subL;
subL->_pParent = nullptr;
}
else
{
if (ppNode->_pLeft == pParent)
{
ppNode->_pLeft = subL;
subL->_pParent = ppNode;
}
else
{
ppNode->_pRight = subL;
subL->_pParent = ppNode;
}
}
pParent->_bf = subL->_bf = 0;
}
// 左单旋
void RotateL(Node *pParent)
{
Node *ppNode = pParent->_pParent;
Node *subR = pParent->_pRight;
Node *subRL = subR->_pLeft;
pParent->_pRight = subRL;
if (subRL)
{
subRL->_pParent = pParent;
}
pParent->_pParent = subR;
subR->_pLeft = pParent;
if (pParent == _pRoot)
{
_pRoot = subR;
subR->_pParent = nullptr;
}
else
{
if (ppNode->_pLeft == pParent)
{
ppNode->_pLeft = subR;
subR->_pParent = ppNode;
}
else
{
ppNode->_pRight = subR;
subR->_pParent = ppNode;
}
}
pParent->_bf = subR->_bf = 0;
}
// 右左双旋
void RotateRL(Node *pParent)
{
Node *subR = pParent->_pRight;
Node *subRL = subR->_pLeft;
RotateR(subR);
RotateL(pParent);
int bf = subRL->_bf;
subRL->_bf = 0;
if (bf == 0)
{
pParent->_bf = 0;
subR->_bf = 0;
}
else if (bf == 1)
{
subR->_bf = 0;
pParent->_bf = -1;
}
else if (bf == -1)
{
subR->_bf = 1;
pParent->_bf = 0;
}
else
{
assert(false);
}
}
// 左右双旋
void RotateLR(Node *pParent)
{
Node *subL = pParent->_pLeft;
Node *subLR = subL->_pRight;
RotateL(pParent->_pLeft);
RotateR(pParent);
int bf = subLR->_bf;
subLR->_bf = 0;
if (bf == 0)
{
pParent->_bf = 0;
subL->_bf = 0;
}
else if (bf == 1)
{
pParent->_bf = 0;
subL->_bf = -1;
}
else if (bf == -1)
{
pParent->_bf = 1;
subL->_bf = 0;
}
else
{
assert(false);
}
}
void _Inordered(Node *root)
{
if (root == nullptr)
{
return;
}
_Inordered(root->_pLeft);
cout << root->_data << ' ';
_Inordered(root->_pRight);
}
private:
Node *_pRoot;
};
int main()
{
size_t N = 10000;
srand(time(0));
AVLTree<int> t1;
for (size_t i = 0; i < N; ++i)
{
int x = rand();
cout << x << ' ';
t1.Insert(x);
}
cout << 666 <<'\n';
cout << "IsBalance:" << t1.IsAVLTree() << endl;
return 0;
}