- 0. 前言
- 1. 平衡因子
- 2. 4种旋转情况
- 2.1 LL型
- 2.2 RR型
- 2.3 LR型
- 2.4 RL型
- 3. 完整代码
- 附录---节点调整过程
- 1、平衡二叉树又叫AVL树:
- 2、AVL一定是二叉排序树;
- 3、AVL的查找效率要优于二叉搜索树(不过不明显)
- 4、参考视频链接:
平衡二叉树
手绘平衡二叉树的调整 - 5、二叉树基本操作
二叉排序树插入、查找和删除
二叉树递归遍历和非递归遍历
左子树与右子树的高度差称为平衡因子,平衡因子大于1,这棵树就不是平衡二叉树
对于新插入的节点,无非就是四种情况,往左子树的左边插、左子树的右边插、右子树的左边插、右子树的右边插,所以对应四种情况:LL型、LR型、RR型和RL型。
注意:每次旋转后都要调整各节点的depth,因为节点会发生调整
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#include 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附录—节点调整过程



