平衡二叉树Java

参考:
https://baijiahao.baidu.com/s?id=1651427207567199156&wfr=spider&for=pc
https://blog.csdn.net/bjweimengshu/article/details/106774187
https://blog.csdn.net/QuedYin/article/details/103619681

public class AVLNode {
    public int data;
    public int depth;
    public int balance;
    public AVLNode parent;
    public AVLNode left;
    public AVLNode right;
    public AVLNode(int data){
        this.data=data;
        this.balance=0;
        left=null;
        right=null;
    }
    //插入
    public void insert(AVLNode root,int data){
        //递归向左子树插入
        if(data<root.data){
            if(root.left!=null){
                insert(root.left,data);
            }
            else{
                root.left=new AVLNode(data);
                root.left.parent=root;
            }
        }
        //递归向右子树插入
        else{
            if(root.right!=null){
                insert(root.right,data);
            }
            else{
                root.right=new AVLNode(data);
                root.right.parent=root;
            }
        }
        //插入之后计算平衡因子
        root.balance=calcBalance(root);
        //左子树高,右旋
        if(root.balance>=2){
            //左孙低,右孙高,先左旋
            if(root.left.balance==-1){
                left_rotate(root.left);
            }
            right_rotate(root);
        }
        //右子树高,左旋
        if(root.balance<=-2){
            //左孙高,先右旋
            if(root.right.balance==1){
                right_rotate(root.right);
            }
            left_rotate(root);
        }
        //调整后,重新计算平衡因子和长度
        root.balance=calcBalance(root);
        root.depth=calcDepth(root);
    }
    //右旋
    public void right_rotate(AVLNode p){
        AVLNode pParent=p.parent;
        AVLNode pLeftSon=p.left;
        AVLNode pRightGrandSon=pLeftSon.right;//这个节点的左孩子的右节点
        //左子变父 使这个节点的左孩子替代它在父亲那里的位置
        pLeftSon.parent=pParent;
        //使这个节点的左孩子替代它在父亲那里的位置
        if(pParent!=null){
            if(p==pParent.left){
                pParent.left=pLeftSon;
            }
            else if(p==pParent.right){
                pParent.right=pLeftSon;
            }
        }
        pLeftSon.right=p;//使这个节点成为原来的左孩子的右节点
        p.parent=pLeftSon;//使这个节点成为原来的左孩子的右节点
        //右孙变左孙
        //因为这个节点占了原来的左孩子的右节点pRightGrandSon的位置,所以pRightGrandSon需要 新位置
        //而pRightGrandSon原来在这个节点的左子树中, 必定小于这个节点,所以让她成为这个节点的左孩子
        p.left=pRightGrandSon;//左孩子设置为pRightGrandSon
        if(pRightGrandSon!=null){//pRightGrandSon的父亲设为p
            pRightGrandSon.parent=p;
        }
        //重新计算p和pLeftSon的depth和balance
        p.depth=calcDepth(p);
        p.balance=calcBalance(p);
        pLeftSon.depth=calcDepth(pLeftSon);
        pLeftSon.balance=calcBalance(pLeftSon);
    }
    //左旋 (右子树高的情况)
    public void left_rotate(AVLNode p){
        AVLNode pParent=p.parent;
        AVLNode pRightSon=p.right;//这个节点的右孩子
        AVLNode pLeftGrandSon=pRightSon.left;//这个节点的右孩子的左节点,因为这个节点将要替代他,所以要处理他
        pRightSon.parent=pParent;//这个节点的右孩子替代了这个节点在父亲那的位置
        //这个节点的右孩子替代了这个节点在父亲那的位置
        if(pParent!=null){
            if(p==pParent.right){
                pParent.right=pRightSon;
            }else if(p==pParent.left){
                pParent.left=pRightSon;
            }
        }
        pRightSon.left=p;//这个节点替代了它的右孩子的左节点
        p.parent=pRightSon;
        p.right=pLeftGrandSon;//它的右孩子的左节点无处可去,因为原来在他右子树,所以必定比这个节点大,让他成为这个节点的右孩子
        if(pLeftGrandSon!=null){
            pLeftGrandSon.parent=p;
        }
        p.depth=calcDepth(p);
        p.balance=calcBalance(p);
        pRightSon.depth=calcDepth(pRightSon);
        pRightSon.balance=calcBalance(pRightSon);
    }
    //计算平衡
    public int calcBalance(AVLNode p){
        int d1=0;
        int d2=0;
        if(p.left!=null){
            d1=p.left.depth;
        }
        if(p.right!=null){
            d2=p.right.depth;
        }
        return d1-d2;
    }
    //计算深度
    public int calcDepth(AVLNode p){
        int depth=0;
        if(p.left!=null){
            depth=p.left.depth;
        }
        if(p.right!=null){
            if(p.right.depth>depth){
                depth=p.right.depth;
            }
        }
        return depth;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值