0. 前言
平衡二叉树的删除可能会破坏平衡性,所以同插入一样,也需要动态的调整。在阅读之前,需要掌握二叉搜索树的节点删除和平衡二叉树的插入,链接如下:
1. 平衡二叉树的删除
强调几点:
- 1、要注意函数每个分支流程是否都有返回值(如代码一);
- 2、如果删除了,那么这个节点就不存在了,所以对该节点的操作程序都会报错;
- 3、如果删除了,那么返回到父节点的值是true,这时才需要进行平衡调整;如果未删除,那么就是false,相应的也不需要调整平衡;
1.1 代码一(有bug)
bool deleteAVL(LPNode* root, int key)
{
if (*root == NULL)
return false;
if (key == (*root)->key)
{
LPNode q, s;
if ((*root)->left == NULL && (*root)->right == NULL)
{
q = (*root);
(*root) = NULL;
delete q;
}
else if ((*root)->left == NULL)
{
q = (*root);
*root = (*root)->right;
delete q;
}
else if ((*root)->right == NULL)
{
q = *root;
*root = (*root)->left;
delete q;
}
else
{
q = *root;
s = (*root)->left;
while (s->right)
{
q = s;
s = s->right;
}
(*root)->key = s->key;
if (q != *root)
{
q->right = s->left;
}
else
{
q->left = s->left;
}
}
return true;
}
else if (key > (*root)->key)
{
deleteAVL(&(*root)->right, key);
}
else
{
deleteAVL(&(*root)->left, key);
}
//更新节点深度
renewTreeDepth(*root);
//二叉树平衡的调整
adjustBalance(root, key);
}
1.2 代码二(正确)
bool deleteAVL(LPNode* root, int key)
{
if (*root == NULL)
return false;
if (key == (*root)->key)
{
LPNode q, s;
if ((*root)->left == NULL && (*root)->right == NULL)
{
q = (*root);
(*root) = NULL;
delete q;
}
else if ((*root)->left == NULL)
{
q = (*root);
*root = (*root)->right;
delete q;
}
else if ((*root)->right == NULL)
{
q = *root;
*root = (*root)->left;
delete q;
}
else
{
q = *root;
s = (*root)->left;
while (s->right)
{
q = s;
s = s->right;
}
(*root)->key = s->key;
if (q != *root)
{
q->right = s->left;
}
else
{
q->left = s->left;
}
}
return true;
}
else if (key > (*root)->key)
{
//如果本次传进去删掉了(*root)->right,那么return回来就是true,则需要调整(*root)
//否则没有删掉,返回回来是false,则不需要调整
int flag = deleteAVL(&(*root)->right, key);
if (flag)
{
//更新节点深度
renewTreeDepth(*root);
//二叉树平衡的调整
adjustBalance(root, key);
}
return flag;
}
else
{
//如果本次传进去删掉了(*root)->left,那么return回来就是true,则需要调整(*root)
//否则没有删掉,返回回来是false,则不需要调整
int flag = deleteAVL(&(*root)->left, key);
if (flag)
{
//更新节点深度
renewTreeDepth(*root);
//二叉树平衡的调整
adjustBalance(root, key);
}
return flag;
}
}
2. 完整代码
#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);
}
}
}
bool deleteAVL(LPNode* root, int key)
{
if (*root == NULL)
return false;
if (key == (*root)->key)
{
LPNode q, s;
if ((*root)->left == NULL && (*root)->right == NULL)
{
q = (*root);
(*root) = NULL;
delete q;
}
else if ((*root)->left == NULL)
{
q = (*root);
*root = (*root)->right;
delete q;
}
else if ((*root)->right == NULL)
{
q = *root;
*root = (*root)->left;
delete q;
}
else
{
q = *root;
s = (*root)->left;
while (s->right)
{
q = s;
s = s->right;
}
(*root)->key = s->key;
if (q != *root)
{
q->right = s->left;
}
else
{
q->left = s->left;
}
}
return true;
}
else if (key > (*root)->key)
{
//如果本次传进去删掉了(*root)->right,那么return回来就是true,则需要调整(*root)
//否则没有删掉,返回回来是false,则不需要调整
int flag = deleteAVL(&(*root)->right, key);
if (flag)
{
//更新节点深度
renewTreeDepth(*root);
//二叉树平衡的调整
adjustBalance(root, key);
}
return flag;
}
else
{
//如果本次传进去删掉了(*root)->left,那么return回来就是true,则需要调整(*root)
//否则没有删掉,返回回来是false,则不需要调整
int flag = deleteAVL(&(*root)->left, key);
if (flag)
{
//更新节点深度
renewTreeDepth(*root);
//二叉树平衡的调整
adjustBalance(root, key);
}
return flag;
}
}
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);
bool flag = deleteAVL(&root, 8);
if (flag)
{
printf("已删除\n");
midOrder(root);
}
return 0;
}