目录
1.文章概括
2.AVL树概念
3.AVL树的性质
4.AVL树的插入
5.旋转控制
1.左单旋
2. 右单旋
3.左右双旋
4.右左双旋
6.全部代码
1.文章概括
本文适合理解平衡二叉树的读者阅读,因为AVL树是平衡二叉树的一种优化,其大部分实现逻辑与平衡二叉树是相同的,相同的部分不做过多阐述。
2.AVL树概念
平衡二叉树主要用于查找数据,可提高查找效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。在这样的缺点下,AVL树被发明了出来。AVL树的优化点在于:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。
3.AVL树的性质
一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:
1.它的左右子树都是AVL树;
2.左右子树高度之差(简称平衡因子)的绝对值不超过1(-1,0,1)。
AVL树 == 高度平衡二叉搜索树,说是平衡,为什么不是相等?
因为高度差不超过1,不是高度相等。
AVL树图片示例:
如此控制后,增删改查的时间复杂度即为高度次 == O(logN)。
4.AVL树的插入
对于一个结点的插入,分析如下:
1.新增在该结点的左,parent平衡因子减减;
2.新增在该结点的右,parent平衡因子加加;
3.更新后parent平衡因子 == 0,说明parent所在的子树的高度不变,不会再影响祖先,不用再沿着到root的路径往上更新;
4.更新后parent平衡因子 == 1 or -1,说明parent所在的子树的高度变化,会再影响祖先,需要沿着到root的路径往上更新;
5.更新后parent平衡因子 == 2 or -2,说明parent所在的子树的高度变化且不平衡,对parent所在子树进行旋转,让它平衡;
6.更到根结点。
补充说明:执行到4时会从1,2,开始继续循环,执行到3,5,6时插入结束。
旋转时需要注意的问题:
1.保持它是搜索树;
2.变成平衡树且降低这个子树的高度。
代码:
bool Insert(const T& data)
{
Node* parent = nullptr;
Node* cur = _pRoot;
if (cur == nullptr)
{
cur = new Node(data);
_pRoot = cur;
}
while (cur)
{
if (cur->_data > data)
{
parent = cur;
cur = cur->_pLeft;
}
else if (cur->_data < data)
{
parent = cur;
cur = cur->_pRight;
}
else
return false;
}
cur = new Node(data);
if (parent->_data > data)
{
parent->_pLeft = cur;
cur->_pParent = parent;
}
else
{
parent->_pRight = cur;
cur->_pParent = parent;
}
while (parent)
{
if (parent->_pLeft == cur)
parent->_bf--;
else
parent->_bf++;
if (parent->_bf == 0)
return true;
else if (parent->_bf == 1 || parent->_bf == -1)
{
cur = parent;
parent = parent->_pParent;
}
else
{
if (cur->_bf == 1 && parent->_bf == 2)
{
RotateL(parent);
}
else if (cur->_bf == -1 && parent->_bf == -2)
{
RotateR(parent);
}
else if (cur->_bf == -1 && parent->_bf == 2)
{
RotateRL(parent);
}
else if (cur->_bf == 1 && parent->_bf == -2)
{
RotateLR(parent);
}
break;
}
}
}
代码中,我使用了平衡因子来控制这棵树的高度。
5.旋转控制
1.左单旋
2. 右单旋

3.左右双旋
新节点插入较高左子树的右侧---左右:
4.右左双旋

6.全部代码
#pragma once
#include <iostream>
#include <assert.h>
#include <vector>
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)
{
Node* parent = nullptr;
Node* cur = _pRoot;
if (cur == nullptr)
{
cur = new Node(data);
_pRoot = cur;
}
while (cur)
{
if (cur->_data > data)
{
parent = cur;
cur = cur->_pLeft;
}
else if (cur->_data < data)
{
parent = cur;
cur = cur->_pRight;
}
else
return false;
}
cur = new Node(data);
if (parent->_data > data)
{
parent->_pLeft = cur;
cur->_pParent = parent;
}
else
{
parent->_pRight = cur;
cur->_pParent = parent;
}
while (parent)
{
if (parent->_pLeft == cur)
parent->_bf--;
else
parent->_bf++;
if (parent->_bf == 0)
return true;
else if (parent->_bf == 1 || parent->_bf == -1)
{
cur = parent;
parent = parent->_pParent;
}
else
{
if (cur->_bf == 1 && parent->_bf == 2)
{
RotateL(parent);
}
else if (cur->_bf == -1 && parent->_bf == -2)
{
RotateR(parent);
}
else if (cur->_bf == -1 && parent->_bf == 2)
{
RotateRL(parent);
}
else if (cur->_bf == 1 && parent->_bf == -2)
{
RotateLR(parent);
}
break;
}
}
}
// AVL树的验证
bool IsAVLTree()
{
return _IsAVLTree(_pRoot);
}
private:
// 根据AVL树的概念验证pRoot是否为有效的AVL树
bool _IsAVLTree(Node* root)
{
if (root == nullptr)
return true;
int leftHight = Height(root->_pLeft);
int rightHight = Height(root->_pRight);
if (rightHight - leftHight != root->_bf)
{
cout << "平衡因子异常:" << root->_data << "->" << root->_bf << endl;
return false;
}
return abs(rightHight - leftHight) < 2
&& _IsAVLTree(root->_pLeft)
&& _IsAVLTree(root->_pRight);
}
size_t Height(Node* root)
{
if (root == nullptr)
return 0;
int leftHeight = Height(root->_pLeft);
int rightHeight = Height(root->_pRight);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
// 右单旋
void RotateR(Node* pParent)
{
Node* cur = pParent->_pLeft;
Node* curRight = cur->_pRight;
Node* parentP = pParent->_pParent;
pParent->_pLeft = curRight;
if(curRight)
curRight->_pParent = pParent;
cur->_pRight = pParent;
pParent->_pParent = cur;
if (parentP == nullptr)
{
_pRoot = cur;
cur->_pParent = nullptr;
}
else
{
cur->_pParent = parentP;
if (parentP->_pLeft == pParent)
parentP->_pLeft = cur;
else
parentP->_pRight = cur;
}
if(curRight)
curRight->_bf = 0;
pParent->_bf = cur->_bf = 0;
}
// 左单旋
void RotateL(Node* pParent)
{
Node* cur = pParent->_pRight;
Node* curLeft = cur->_pLeft;
Node* parentP = pParent->_pParent;
pParent->_pRight = curLeft;
if(curLeft)
curLeft->_pParent = pParent;
cur->_pLeft = pParent;
pParent->_pParent = cur;
if (parentP == nullptr)
{
_pRoot = cur;
cur->_pParent = nullptr;
}
else
{
cur->_pParent = parentP;
if (parentP->_pLeft == pParent)
parentP->_pLeft = cur;
else
parentP->_pRight = cur;
}
if(curLeft)
curLeft->_bf = 0;
pParent->_bf = cur->_bf = 0;
}
// 右左双旋
void RotateRL(Node* pParent)
{
Node* cur = pParent->_pRight;
Node* curLeft = cur->_pLeft;
int temp = curLeft->_bf;
RotateR(cur);
RotateL(pParent);
if (temp == 0)
return;
else if (temp == 1)
{
pParent->_bf = -1;
cur->_bf = 0;
curLeft->_bf = 0;
}
else if (temp == -1)
{
pParent->_bf = 0;
cur->_bf = 1;
curLeft->_bf = 0;
}
else
assert(false);
}
// 左右双旋
void RotateLR(Node* pParent)
{
Node* cur = pParent->_pLeft;
Node* curRight = cur->_pRight;
int temp = curRight->_bf;
RotateL(cur);
RotateR(pParent);
if (temp == 0)
return;
else if (temp == 1)
{
pParent->_bf = 0;
cur->_bf = -1;
curRight->_bf = 0;
}
else if (temp == -1)
{
pParent->_bf = 1;
cur->_bf = 0;
curRight->_bf = 0;
}
else
assert(false);
}
private:
Node* _pRoot;
};