0. 前言
- 1、平衡二叉树又叫AVL树:
- 2、AVL一定是二叉排序树;
- 3、AVL的查找效率要优于二叉搜索树(不过不明显)
- 4、参考视频链接:
平衡二叉树
手绘平衡二叉树的调整 - 5、二叉树基本操作
二叉排序树插入、查找和删除
二叉树递归遍历和非递归遍历
1. 平衡因子
左子树与右子树的高度差称为平衡因子,平衡因子大于1,这棵树就不是平衡二叉树
2. 4种旋转情况
对于新插入的节点,无非就是四种情况,往左子树的左边插、左子树的右边插、右子树的左边插、右子树的右边插,所以对应四种情况:LL型、LR型、RR型和RL型。
注意:每次旋转后都要调整各节点的depth,因为节点会发生调整
2.1 LL型
void LL_Rotation(LPNode* root)
{
//LL型要右旋
LPNode cache = (*root)->left;
(*root)->left = cache->right;
cache->right = (*root);
//更新调整后的高度
renewTreeDepth(*root);
renewTreeDepth(cache);
//更新root的指向
*root = cache;
}
2.2 RR型
void RR_Rotation(LPNode* root)
{
//RR型要左旋
LPNode cache = (*root)->right;
(*root)->right = cache->left;
cache->left = (*root);
//更新调整后的高度
renewTreeDepth(*root);
renewTreeDepth(cache);
//更新root的指向
*root = cache;
}
2.3 LR型
void LR_Rotation(LPNode* root)
{
//LR型先左旋再右旋
RR_Rotation(&(*root)->left);
LL_Rotation(root);
}
2.4 RL型
void RL_Rotation(LPNode* root)
{
//RL型,先右旋再左旋
LL_Rotation(&(*root)->right);
RR_Rotation(root);
}
3. 完整代码
#include<stdio.h>
#include<stdlib.h>
typedef struct node {
int key;
struct node* left;
struct node* right;
int depth;
}*LPNode;
int max(int a, int b)
{
return a > b ? a : b;
}
//获取节点的深度
int getDepth(LPNode node)
{
if (node == NULL)
return 0;
return node->depth;
}
//更新节点深度
void renewTreeDepth(LPNode root)
{
必须写成函数,不然会传进来空指针,
//比如:int leftDepth = root->left->depth;
int leftDepth = getDepth(root->left);
int rightDepth = getDepth(root->right);
root->depth = max(leftDepth, rightDepth) + 1;
}
void LL_Rotation(LPNode* root)
{
//LL型要右旋
LPNode cache = (*root)->left;
(*root)->left = cache->right;
cache->right = (*root);
//更新调整后的高度
renewTreeDepth(*root);
renewTreeDepth(cache);
//更新root的指向
*root = cache;
}
void RR_Rotation(LPNode* root)
{
//RR型要左旋
LPNode cache = (*root)->right;
(*root)->right = cache->left;
cache->left = (*root);
//更新调整后的高度
renewTreeDepth(*root);
renewTreeDepth(cache);
//更新root的指向
*root = cache;
}
void LR_Rotation(LPNode* root)
{
//LR型先左旋再右旋
RR_Rotation(&(*root)->left);
LL_Rotation(root);
}
void RL_Rotation(LPNode* root)
{
//RL型,先右旋再左旋
LL_Rotation(&(*root)->right);
RR_Rotation(root);
}
//平衡调整
void adjustBalance(LPNode* root, int key)
{
if (getDepth((*root)->left) - getDepth((*root)->right) > 1)
{
if (key < (*root)->left->key)
{
//LL型
LL_Rotation(root);
}
else
{
//LR型
LR_Rotation(root);
}
}
else if (getDepth((*root)->left) - getDepth((*root)->right) < -1)
{
if (key > (*root)->right->key)
{
//RR型
RR_Rotation(root);
}
else
{
//RL型
RL_Rotation(root);
}
}
}
void insertAVL(LPNode* root, int key)
{
if (*root == NULL)
{
(*root) = (LPNode)malloc(sizeof(struct node));
if (*root == NULL)
return;
(*root)->key = key;
(*root)->depth = 1;
(*root)->left = NULL;
(*root)->right = NULL;
}
else
{
if (key < (*root)->key)
{
insertAVL(&(*root)->left, key);
}
else if (key > (*root)->key)
{
insertAVL(&(*root)->right, key);
}
}
//更新节点的深度
renewTreeDepth(*root);
//二叉树平衡的调整
adjustBalance(root, key);
}
void midOrder(LPNode root)
{
if (root != NULL)
{
midOrder(root->left);//左
printf("%d ", root->key);
midOrder(root->right);//右
}
}
int main()
{
LPNode root = NULL;
int keyArr[6] = { 9,8,7,0,3,1 };
for (int i = 0; i < 6; i++)
{
insertAVL(&root, keyArr[i]);
}
midOrder(root);
//打印二叉树的形状及depth(验证)
printf("\n%d --- %d", root->key, root->depth);
printf("\n%d --- %d", root->left->key, root->left->depth);
printf("\n%d --- %d", root->left->right->key, root->left->right->depth);
printf("\n%d --- %d", root->right->key, root->right->depth);
printf("\n%d --- %d", root->right->left->key, root->right->left->depth);
printf("\n%d --- %d", root->right->right->key, root->right->right->depth);
return 0;
}
//结果
0 1 3 7 8 9
3 --- 3
0 --- 2
1 --- 1
8 --- 2
7 --- 1
9 --- 1