java AVL树增删模拟

一、AVL树概念

  1. AVL树就是平衡二叉查询树,每个节点的左子树和右子树高度最多相差1,这个差值就是平衡因子
  2. 树的左右子树都是AVL树。

在这里插入图片描述

二、AVL树初始化

2.1 AVLNode属性

public class AVLNode {
   public AVLNode parent;
    public AVLNode left;
    public AVLNode right;
    public int height;
    public int value;

    public AVLNode(AVLNode parent, AVLNode left, AVLNode right, int value) {
        this.parent = parent;
        this.left = left;
        this.right = right;
        this.height = 1;
        this.value = value;
    }
}

2.2 AVLTree属性

public class AVLTree {
	public AVLNode root;
}

三、影响AVL平衡的因素

  • 主要以下四种情况

  • 在这里插入图片描述

  • LL 是操作节点的左子树的高度-右子树的高度>1,且操作节点的左节点左子树高度>=右子树高度,根据此种情况,需要对操作节点右旋

    • 在这里插入图片描述
  • LR 是操作节点的左子树的高度-右子树的高度>1,且操作节点的左节点左子树高度<右子树高度,根据此种情况,需要对操作节点左节点左旋后,在对操作节点右旋

    • 在这里插入图片描述
  • RR是操作节点的左子树的高度-右子树的高度<-1,且操作节点的左节点左子树高度<=右子树高度,根据此种情况,需要对操作节点左旋

    • 在这里插入图片描述
  • RL是操作节点的左子树的高度-右子树的高度<-1,且操作节点的左节点左子树高度>右子树高度,根据此种情况,需要对操作节点右节点右旋后,在对操作节点左旋

    • 在这里插入图片描述

四、AVL增加节点

4.1 增加节点

  1. 判断插入值得大小,插入后,查询当前左右节点的平衡因子,如果平衡因子不为1,0,-1,则需要调平,平衡因子 = 左子树高度-右子树高度
  2. 如果平衡因子>1,体现为L,继续判断操作节点的左节点的高度大小,如果左节点的左高度>=右高度,则体现为L,最终体现为LL
  3. 如果平衡因子>1,体现为L,继续判断操作节点的左节点的高度大小,如果左节点的左高度<右高度,则体现为R,最终体现为LR
  4. 如果平衡因子<-1,体现为R,继续判断操作节点的右节点的高度大小,如果右节点的左高度<=右高度,则体现为R,最终体现为RR
  5. 如果平衡因子<-1,体现为R,继续判断操作节点的右节点的高度大小,如果右节点的左高度>右高度,则体现为L,最终体现为RL

4.2 增加节点代码

public void add(int value) {
    if (root == null) {
        root = new AVLNode(null, null, null, value);
        return;
    }
    addNode(value, root);
}

private AVLNode addNode(int value, AVLNode node) {
    if (node == null) {
        return new AVLNode(null, null, null, value);
    } else {
        if (value > node.value) {
            node.right = addNode(value, node.right);
            node.right.parent = node;
        } else if (value < node.value) {
            node.left = addNode(value, node.left);
            node.left.parent = node;
        } else {
            return node;
        }
        // 开始设置高度
        resetHeight(node);
        // 开始调整结构
        return rebalance(node);
    }
}

private AVLNode rebalance(AVLNode node) {
    // 判断平衡因子
    if (height(node.left) - height(node.right) > 1) {
        if (height(node.left.left) < height(node.left.right)) {
            // 先左旋
            rolateLeft(node.left);
        }
        return rolateRight(node);
    } else if (height(node.left) - height(node.right) < -1) {
        if (height(node.right.left) > height(node.right.right)) {
            // node右旋
            rolateRight(node.right);
        }
        return rolateLeft(node);
    }
    return node;
}

private void resetHeight(AVLNode node) {
    node.height = Math.max(height(node.left), height(node.right)) + 1;
}

private AVLNode rolateLeft(AVLNode node) {
    AVLNode right = node.right;
    AVLNode left = right.left;
    AVLNode parent = node.parent;
    node.right = left;
    if (left != null) {
        left.parent = node;
    }
    node.parent = right;
    right.parent = parent;
    right.left = node;
    if (parent == null) {
        root = right;
    } else if (parent.left == node) {
        parent.left = right;
    } else if (parent.right == node) {
        parent.right = right;
    }
    resetHeight(node);
    resetHeight(right);
    return right;
}

private AVLNode rolateRight(AVLNode node) {
    AVLNode left = node.left;
    AVLNode parent = node.parent;
    AVLNode right = left.right;
    left.right = node;
    node.left = right;
    if (right != null) {
        right.parent = node;
    }
    node.parent = left;
    left.parent = parent;
    if (parent == null) {
        root = left;
    } else if (parent.left == node) {
        parent.left = left;
    } else if (parent.right == node) {
        parent.right = left;
    }
    resetHeight(node);
    resetHeight(left);
    return left;
}

private int height(AVLNode node) {
   return node == null ? 0 : node.height;
}

五、AVL删除节点

5.1 删除节点

  1. 首先找到删除节点
  2. 判断删除节点有几个子节点,一个或者没有,则直接删除
  3. 如果有两个子节点,删除该节点的后继节点,然后用后继节点内容代替当前节点内容
  4. 调整高度后,判断平衡因子并调平

5.2 删除节点代码

public void delete(int value) {
    if (root == null) {
        return;
    }
    delete(value, root);
}

private AVLNode delete(int value, AVLNode node) {
    if (node == null) {
        return null;
    }
    if (value > node.value) {
        node.right = delete(value, node.right);
    } else if (value < node.value) {
        node.left = delete(value, node.left);
    } else {
        // 判断当前node有几个节点
        if (node.left == null && node.right == null) {
            // 直接删除当前节点
            return null;
        } else if (node.left == null) {
            node.right.parent = node.parent;
            return node.right;
        } else if (node.right == null) {
            node.left.parent = node.parent;
            return node.left;
        } else {
            // 找到后继节点
            AVLNode avlNode = findSussorNode(node);
            // 删除后继节点
            AVLNode newNode = delete(avlNode.value, node);
            node.value = avlNode.value;
            return newNode;
        }
    }
    resetHeight(node);
    return rebalance(node);
}

private AVLNode findSussorNode(AVLNode node) {
    AVLNode right = node.right;
    while (right.left != null) {
        right = right.left;
    }
    return right;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值