Avl平衡树的Java代码实现

Avl平衡树的java代码实现

Avl平衡树的结点数据结构

public class AvlTreeNode {

    private int val;

    private int height;

    private AvlTreeNode leftTree;

    private AvlTreeNode rightTree;

    public AvlTreeNode() {
    }

    public AvlTreeNode(int val) {
        this.val = val;
    }

    public int getVal() {
        return val;
    }

    public void setVal(int val) {
        this.val = val;
    }

    public AvlTreeNode getLeftTree() {
        return leftTree;
    }

    public void setLeftTree(AvlTreeNode leftTree) {
        this.leftTree = leftTree;
    }

    public AvlTreeNode getRightTree() {
        return rightTree;
    }

    public void setRightTree(AvlTreeNode rightTree) {
        this.rightTree = rightTree;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    @Override
    public String toString() {
        return "AvlTreeNode{" +
                "val=" + val +
                ", height=" + height +
                '}';
    }

}

Avl树的代码结构

class AvlTree {

    /**
     * 树的根结点
     */
    private AvlTreeNode rootTreeNode;

    public AvlTreeNode search(int val) {
        return search(val, rootTreeNode);
    }

    /**
     * 前序遍历树
     */
    private void preOrder(AvlTreeNode avlTreeNode){
       if(null != avlTreeNode){
           System.out.println(avlTreeNode);
       }
       if(avlTreeNode.getLeftTree() != null ){
           preOrder(avlTreeNode.getLeftTree());
       }

       if(avlTreeNode.getRightTree() != null){
           preOrder(avlTreeNode.getRightTree());
       }
    }

    public void preOrder(){
        preOrder(rootTreeNode);
    }

    private AvlTreeNode search(int val, AvlTreeNode avlTreeNode) {
        if (null == avlTreeNode) {
            return null;
        }
        if (avlTreeNode.getVal() == val) {
            return avlTreeNode;
        } else if (avlTreeNode.getVal() > val) {
            return search(val, avlTreeNode.getLeftTree());
        } else {
            return search(val, avlTreeNode.getRightTree());
        }
    }

    public void insert(int val) {
        if (null == rootTreeNode) {
            rootTreeNode = new AvlTreeNode(val);
            rootTreeNode.setHeight(0);
            return;
        }
         rootTreeNode = insert(val, rootTreeNode);
    }

    private AvlTreeNode insert(int val, AvlTreeNode avlTreeNode) {
        if (null == avlTreeNode) {
            avlTreeNode = new AvlTreeNode(val);
            avlTreeNode.setHeight(0);
            return avlTreeNode;
        } else if (val == avlTreeNode.getVal()) {
            throw new RuntimeException("val is exist, not add again!");
        } else if (val > avlTreeNode.getVal()) {
            avlTreeNode.setRightTree(insert(val, avlTreeNode.getRightTree()));
            avlTreeNode.setHeight(Math.max(height(avlTreeNode.getLeftTree()), height(avlTreeNode.getRightTree())) + 1);
            if(height(avlTreeNode.getRightTree()) - height(avlTreeNode.getLeftTree()) == 2){
                if(val > avlTreeNode.getRightTree().getVal()){
                    //RR旋转
                    avlTreeNode = rightRightRotation(avlTreeNode);
                }else{
                    avlTreeNode = rightLeftRotation(avlTreeNode);
                }
            }
        } else {
            //插入到左边
            avlTreeNode.setLeftTree(insert(val, avlTreeNode.getLeftTree()));
            avlTreeNode.setHeight(Math.max(height(avlTreeNode.getLeftTree()), height(avlTreeNode.getRightTree())) + 1);
            if (height(avlTreeNode.getLeftTree()) - height(avlTreeNode.getRightTree()) == 2) {
                if (val < avlTreeNode.getLeftTree().getVal()) {
                    //LL旋转
                    avlTreeNode = leftLeftRotation(avlTreeNode);
                } else {
                    //LR型旋转
                    avlTreeNode = leftRightRotation(avlTreeNode);
                }
            }
        }
        return avlTreeNode;
    }

    /**
     * 计算结点的高度
     * @param avlTreeNode
     * @return
     */
    private int height(AvlTreeNode avlTreeNode) {
        if (null == avlTreeNode) {
            return 0;
        }
        return avlTreeNode.getHeight();
    }

    /**
     * LL 旋转 【主要针对左树的左子树插入导致平衡被破坏】右旋
     *
     *           4[avlTreeNode]           2[key1]
     *        2      5                 1      4
     *      1   3                    0      3    5
     *   0
     *  avlTreeNode为平衡被破坏的点,将其进行LL旋转重新获得平衡
     *
     * @param avlTreeNode
     * @return
     */
    private AvlTreeNode leftLeftRotation(AvlTreeNode avlTreeNode) {
        AvlTreeNode key1;
        key1 = avlTreeNode.getLeftTree();
        avlTreeNode.setLeftTree(key1.getRightTree());
        key1.setRightTree(avlTreeNode);
        //计算重新移动过后的高度
        avlTreeNode.setHeight(Math.max(height(avlTreeNode.getLeftTree()),height(avlTreeNode.getRightTree())) + 1);
        key1.setHeight(Math.max(height(key1.getLeftTree()),avlTreeNode.getHeight()) + 1);
        return key1;
    }

    /**
     * RR 旋转  【主要针对右树的右子树插入 导致平衡被破坏】  左旋
     *
     *      1  【avlTreeNode】                 3  【key1】
     *   0      3                        1          5
     *       2     5                 0      2            6
     *                 6
     *
     * avlTreeNode 为平衡被破坏的点,将其进行RR旋转重新获取平衡
     *
     * @param avlTreeNode
     * @return
     */
    private AvlTreeNode rightRightRotation(AvlTreeNode avlTreeNode){
        AvlTreeNode key1;
        key1 = avlTreeNode.getRightTree();
        avlTreeNode.setRightTree(key1.getLeftTree());
        key1.setLeftTree(avlTreeNode);

        avlTreeNode.setHeight(Math.max(height(avlTreeNode.getLeftTree()),height(avlTreeNode.getRightTree())) + 1);
        key1.setHeight(Math.max(height(avlTreeNode.getRightTree()),avlTreeNode.getHeight()) + 1);
        return key1;
    }


    /**
     * LR旋转【主要针对在左树的 右子树进行插入 导致平衡被破坏】
     *          A              先对A的左树进行RR旋转==>>        A         再对A进行LL旋转  ====>>       E
     *    [1] B      C                                [1] E       C                              B      A
     *     D    E                                      B                                       D    H       C
     *        H                                      D    H
     *
     * @param avlTreeNode
     * @return
     */
    private AvlTreeNode leftRightRotation(AvlTreeNode avlTreeNode){
        avlTreeNode.setLeftTree(rightRightRotation(avlTreeNode.getLeftTree()));
        return leftLeftRotation(avlTreeNode);
    }

    /**
     * RL旋转
     * 与LR对称 主要针对 右树的左子树插入导致平衡被破坏
     *         A           现对平衡被破坏的点A的右子树进行一次LL旋转 ====>>          A                再对A进行一次RR旋转完成平衡          D
     *    B         C                                                       B        D                                        A        C
     *           D     E                                                          F      C                                 B     F         E
     *        F                                                                              E
     *
     *
     * @param avlTreeNode
     * @return
     */
    private AvlTreeNode rightLeftRotation(AvlTreeNode avlTreeNode){
        avlTreeNode.setRightTree(leftLeftRotation(avlTreeNode.getRightTree()));
        return rightRightRotation(avlTreeNode);
    }

    /**
     * 删除指定结点
     * @param val
     */
    public void deleteAvlTreeNode(int val){
        if(null == rootTreeNode){
            return;
        }
        rootTreeNode = deleteAvlTreeNode(val,rootTreeNode);
    }

    public AvlTreeNode deleteAvlTreeNode(int val,AvlTreeNode avlTreeNode){
       if(null == avlTreeNode) {
           return null;
       }
       if(val == avlTreeNode.getVal()){
           //找到为当前结点  进行删除
           if(avlTreeNode.getLeftTree() != null && null != avlTreeNode.getRightTree()){
               //左子树比右子树高
               if(height(avlTreeNode.getLeftTree()) > height(avlTreeNode.getRightTree())){
                   //找到该子树左子树中最大的结点
                   AvlTreeNode maxAvlTreeNode = maximum(avlTreeNode.getLeftTree());
                   avlTreeNode.setVal(maxAvlTreeNode.getVal());
                   avlTreeNode.setLeftTree(deleteAvlTreeNode(maxAvlTreeNode.getVal(),avlTreeNode.getLeftTree()));
               }else{
                   //右子树比左子树高或者相等
                   AvlTreeNode minTreeNode = minimum(avlTreeNode.getRightTree());
                   avlTreeNode.setVal(minTreeNode.getVal());
                   avlTreeNode.setRightTree(deleteAvlTreeNode(minTreeNode.getVal(),avlTreeNode.getRightTree()));
               }
           }else{
               avlTreeNode = avlTreeNode.getLeftTree() == null ? avlTreeNode.getRightTree() : avlTreeNode.getLeftTree();
           }
       }else if(val < avlTreeNode.getVal()){
           avlTreeNode.setLeftTree(deleteAvlTreeNode(val,avlTreeNode.getLeftTree()));
           //删除之后判断是否树失去平衡   删除的节点在树的左边
           if(height(avlTreeNode.getRightTree()) - height(avlTreeNode.getLeftTree()) == 2){
                //删除导致不平衡则进行旋转   因为被影响的右子树的高度高于左子树
               //则需要判断  右子树的左子树高 还是右子树高
               AvlTreeNode rTreeNode = avlTreeNode.getRightTree();
               if(height(rTreeNode.getLeftTree()) > height(rTreeNode.getRightTree())){
                   //符合RL情况
                   //解释: 如果平衡被影响的结点的 右结点的的右左子树高于 右右子树 则等同于 结点插入到右结点的左子树的情况符合(RL)
                   avlTreeNode = rightLeftRotation(avlTreeNode);
               }else{
                   //符合RR情况
                   //解释: 如果平衡被影响的结点的 右结点的右左子树等于小于右右子树  则符合RR型插入结构
                   //        A
                   //    B        C
                   //  G       D     E
                   //        F     H
                   //
                   //如果G结点被删除 则A结点平衡型被影响  则通过查看A的右结点C的左右子树情况  判断影响平衡的结点满足的类型
                   //   右结点的左子树高度等于右结点的右子树 时:
                   //        A                                              C
                   //    B        C                                    A        E
                   //           D     E     ==》 进型一个RR型左旋      B    D   H
                   //         F     H                                   F

                   //右结点的 左子树高度小于右结点的右子树时
                   //        A                                    A                                         C
                   //    B        C                           B       C                                   A       E
                   //  G       D      E   ===》 删除结点G             D    E    ===》 进行一次RR型左旋转    B    D  H
                   //               H                                   H
                   //   打到平衡  所以 符合LL型与LR型同此推理   通过递归达到局部平衡从而达到一个整体的平衡
                    avlTreeNode = rightRightRotation(avlTreeNode);
               }
           }
       }else{
           avlTreeNode.setRightTree(deleteAvlTreeNode(val,avlTreeNode.getRightTree()));
           //删除之后判断是否树失去平衡  删除的节点在树的右边
           if(height(avlTreeNode.getLeftTree()) - height(avlTreeNode.getRightTree()) == 2){
               //删除导致不平衡则进行旋转
               AvlTreeNode lTreeNode = avlTreeNode.getLeftTree();
               if(height(lTreeNode.getRightTree()) > height(lTreeNode.getLeftTree())){
                   //被删除结点的 左边结点子树的高度   右子树如果高于左子树 则满足LR型
                   avlTreeNode = leftRightRotation(avlTreeNode);
               }else{
                   //否则相等或者小于则舒服 LL型
                   avlTreeNode = leftLeftRotation(avlTreeNode);
               }
           }
       }
       if(null != avlTreeNode){
           //如果没有左右子树则为叶子结点
           if(null == avlTreeNode.getLeftTree() && null == avlTreeNode.getRightTree()){
               avlTreeNode.setHeight(0);
           }else{
               avlTreeNode.setHeight(Math.max(height(avlTreeNode.getLeftTree()),height(avlTreeNode.getRightTree())) + 1);
           }
       }
       return avlTreeNode;
    }

    /**
     * 寻找指定结点子结点的 最大结点
     * @param avlTreeNode
     * @return
     */
    private AvlTreeNode maximum(AvlTreeNode avlTreeNode){
        if(null == avlTreeNode){
            return null;
        }
        AvlTreeNode maxTreeNode = avlTreeNode;
        while(maxTreeNode != null){
            if(maxTreeNode.getRightTree() != null){
                maxTreeNode = maxTreeNode.getRightTree();
            }else{
                return maxTreeNode;
            }
        }
        return maxTreeNode;
    }

    /**
     * 寻找指定结点的最小子结点
     * @param avlTreeNode
     * @return
     */
    private AvlTreeNode minimum(AvlTreeNode avlTreeNode){
        if(null == avlTreeNode){
            return null;
        }

        AvlTreeNode minTreeNode = avlTreeNode;
        while(null != minTreeNode){
            if(null != minTreeNode.getLeftTree()){
                minTreeNode = minTreeNode.getLeftTree();
            }else{
                return minTreeNode;
            }
        }
        return minTreeNode;
    }
}

测试代码

class Main{
    public static void main(String[] args) {
        AvlTree avlTree = new AvlTree();
        //              6
        //        3             10
        //   2        4      7
        //1
        avlTree.insert(6);
        avlTree.insert(3);
        avlTree.insert(10);
        avlTree.insert(7);
        avlTree.insert(2);
        avlTree.insert(4);
        avlTree.insert(1);
        avlTree.preOrder();
        System.out.println("================");
        avlTree.deleteAvlTreeNode(7);
        System.out.println("================");
        avlTree.preOrder();
        System.out.println(avlTree.search(3));
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值