一、概念
平衡二叉树
- 树中任意结点的平衡因子(
左子树高度 - 右子树高度
)绝对值不超过1- 树中的每个左子树和右子树都是AVL树
- AVL树是特殊的
二叉搜索树
- AVL树的旋转操作是指在平衡因子大于1时, 通过旋转来调整树的结构, 使平衡因子不超过1
标记平衡因子(左子树高度 - 右子树高度
)
该树为AVL树
二、实现
节点定义
template <class T>
struct AVLNode{
T value;
AVLNode<T> *leftSon;
AVLNode<T> *rightSon;
int height;
AVLNode(T value,AVLNode<T> *leftSon,AVLNode<T> *rightSon,int height){
this->value = value;
this->leftSon = leftSon;
this->rightSon = rightSon;
this->height = height;
}
};
1. 获取节点信息
//获取某节点的高度
template <class T>
int getHeight(AVLNode<T> *root){
if(root == nullptr){
return 0;
}
return root->height;
}
//获取节点的平衡因子
template <class T>
int getBalanceFactor(AVLNode<T> *root){
if(root == nullptr){
return 0;
}
return getHeight(root->leftSon) - getHeight(root->rightSon);
}
2. 判断
//判断是否平衡
template <class T>
bool isBalance(AVLNode<T> *root){
if(root == nullptr){
return true;
}
if(abs(getBalanceFactor(root)) > 1){
return false;
}
return isBalance(root->leftSon) && isBalance(root->rightSon);
}
3. 旋转
3.1 左旋
- AVL树若在
右子树
插入右孩子
导致失衡时,需进行单左旋调整- 旋转围绕
最小失衡子树
的根节点
进行
图示
原本平衡的AVL树插入节点7后导致不平衡;
最小失衡子树的根节点为节点5
实现代码:
//左旋;root为最小失衡子树的根节点
template <class T>
AVLNode<T> *leftRotation(AVLNode<T> *root){
AVLNode<T> *p = root->rightSon;
root->rightSon = p->leftSon;
p->leftSon = root;
//改变指向后,更新结点对应的高度
root->height = max(getHeight(root->leftSon),getHeight(root->rightSon))+1;
p->height = max(getHeight(p->leftSon),getHeight(p->rightSon))+1;
return p;
}
代码过程图示:
3.2 右旋
- AVL树若在
左子树
插入左孩子
导致失衡时,需进行单右旋调整- 旋转围绕最小失衡子树的根节点进行
图示
实现代码:
template <class T>
AVLNode<T>* rightRotation(AVLNode<T>* root){
AVLNode<T> *p = root->leftSon;
root->leftSon = p->rightSon;
p->rightSon = root;
root->height = max(getHeight(root->leftSon), getHeight(root->rightSon)) + 1;
p->height = max(getHeight(p->leftSon), getHeight(p->rightSon)) + 1;
return p;
}
代码过程图示:
3.3 先右旋后左旋
- AVL树在
右子树
上插入左孩子
导致失衡时,需进行先右旋后左旋调整
template <class T>
AVLNode<T>* rightLeftRotation(AVLNode<T> *root){
root->rightSon = rightRotation(root->rightSon);
return leftRotation(root);
}
图示:
其中,红色为插入节点;绿色为最小失衡子树的根节点
3.4 先左旋后右旋
- AVL树在
左子树
上插入右孩子
导致失衡时,需进行先左旋后右旋调整
template <class T>
AVLNode<T>* leftRightRotation(AVLNode<T> *root){
root->leftSon = leftRotation(root->leftSon);
return rightRotation(root);
}
图示:
其中,红色为插入节点;绿色为最小失衡子树的根节点