_08-AVL树的删除

题意:

填写函数

void delete_avl_node( BTreeNode* root, int value );

移除AVL树上值为value的节点。

树和前几个题目一样,挂在根节点-1的右子树下。

给你的树已经处于平衡状态,你不需要判断值是否有效,值一定存在。

思路:

①根据要删除的值,找到要删除的节点。

②分要删除的节点的左右儿子的情况来讨论。

③若左右儿子都有,则用以右儿子为根节点的树中的最小节点p来替代要删除的节点(或者用以左儿子为根节点的树中的最大的点p来替代要删除的节点),代替完了再把p删

④若只有一个儿子或者都没有,先用p记录下要删除的点,再用存在的左或右儿子代替,再将p删除即可。

⑤最后再判断根节点的平衡因子,更新高度即可。

源码:

#include <algorithm>
//
//struct BTreeNode{
//    int value{0};
//    int height{0};
//    BTreeNode* parent{nullptr};
//    BTreeNode* left_child{nullptr};
//    BTreeNode* right_child{nullptr};
//    BTreeNode( int value ){
//        this->value = value;
//    }
//    BTreeNode(){
//        this->value = 0;
//    }
//};
int h(BTreeNode* node) {  //获取高度函数
    if (!node)
        return 0;
    else
        return node->height;
}
void rotate_rr(BTreeNode* node) {
    if (!node) return;
    BTreeNode* t = node->right_child;
    node->right_child = t->left_child;
    if (t->left_child)
        t->left_child->parent = node;
    t->parent = node->parent;
    if (t->parent)
        if (t->parent->left_child == node)
            t->parent->left_child = t;
        else
            t->parent->right_child = t;
    node->parent = t;
    t->left_child = node;
    node->height = max(h(node->left_child), h(node->right_child)) + 1;
    t->height = max(h(t->left_child), h(t->right_child)) + 1;
}
void rotate_ll(BTreeNode* node) {
    if (!node) return;
    BTreeNode* t = node->left_child;
    node->left_child = t->right_child;
    if (t->right_child)
        t->right_child->parent = node;
    t->parent = node->parent;
    if (t->parent)
        if (t->parent->left_child == node)
            t->parent->left_child = t;
        else
            t->parent->right_child = t;
    node->parent = t;
    t->right_child = node;
    node->height = max(h(node->left_child), h(node->right_child)) + 1;
    t->height = max(h(t->left_child), h(t->right_child)) + 1;
}
void rotate_rl(BTreeNode* node) {
    BTreeNode* t = node->right_child;
    rotate_ll(t);
    rotate_rr(node);
}
void rotate_lr(BTreeNode* node) {
    BTreeNode* t = node->left_child;
    rotate_rr(t);
    rotate_ll(node);
}
BTreeNode* findMin(BTreeNode* p) {  //找到最小点函数
    while (p->left_child)
        p = p->left_child;
    return p;
}
BTreeNode* adjust(BTreeNode* node) {
    if (h(node->left_child) - h(node->right_child) >= 2) {  //如果树不平衡且左子树高,在此可判断出是l_型
        if (h(node->left_child->left_child) > h(node->left_child->right_child))  //再通过左子树左右儿子高度差判断
            rotate_ll(node);
        else if (h(node->left_child->left_child) < h(node->left_child->right_child))
            rotate_lr(node);
        else
            rotate_ll(node);
    }
    else if (h(node->right_child) - h(node->left_child) >= 2) {  //如果不平衡且右子树高,在此可判断出是r_型
        if (h(node->right_child->right_child) > h(node->right_child->left_child))  //再通过右子树左右儿子高度差判断
            rotate_rr(node);
        else if (h(node->right_child->right_child) < h(node->right_child->left_child))
            rotate_rl(node);
        else
            rotate_rr(node);
    }
    return node;
}
BTreeNode* delete_avl_node1(BTreeNode* root, int value) {
    if (root->value == -1)  //从根节点传到右儿子
        root = root->right_child;
    if (value < root->value)  //根据大小关系找到要删除的节点
        root->left_child = delete_avl_node1(root->left_child, value);
    else if (value > root->value)
        root->right_child = delete_avl_node1(root->right_child, value);
  //如果能到这步则说明找到了要删除节点的位置
    else if (root->left_child && root->right_child) {  //如果该节点左右都有儿子
        BTreeNode* p = findMin(root->right_child);  //用该点的右儿子的最小点p来代替该点
        root->value = p->value;
        root->right_child = delete_avl_node1(root->right_child, p->value);  //删除节点p
    }
    else {  //该点只有一个儿子或者都没有
        BTreeNode* p = root;
        if (!root->right_child)  //如果该节点有右儿子
            root = root->left_child;
        else if (!root->left_child)  //如果该节点有左儿子
            root = root->right_child;
        delete p;
    }
    if (root) {  //检查当前root的是否平衡,因为是递推,所以会从下往上检查每个点是否平衡
        root = adjust(root);
        root->height = max(h(root->left_child), h(root->right_child)) + 1;
    }
    return root;
}
void delete_avl_node(BTreeNode* root, int value) {
    root = delete_avl_node1(root, value);
}

ps:因为是递推,所以会从下往上每个点检查是否平衡。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

别搜了,自己做

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值