平衡二叉树Java实现

本文介绍了一种平衡二叉树的Java实现方法,包括添加节点、旋转操作、判断是否为平衡二叉树等功能,并通过随机插入的方式验证了算法的有效性和正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

平衡二叉树Java实现

平衡二叉树Java实现

static class TreeNode{

        public int val;
        public TreeNode left;
        public TreeNode right;

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

    }

    static class BTree{

        private TreeNode root ;
        private int length=0;
        //添加子节点
        public void add(int val){
            if (root==null){
                root = new TreeNode(val);
            }else {
                TreeNode bTree = root;
                TreeNode parent = root;
                //寻找位置插入
                while (bTree!=null){
                    parent = bTree;
                    if (bTree.val < val){
                        bTree = bTree.right;
                    }else {
                        bTree = bTree.left;
                    }
                }
                if (parent.val < val){
                    parent.right = new TreeNode(val);
                }else {
                    parent.left = new TreeNode(val);
                }

                //插值看平衡是否被破坏,若被破坏则需要旋转二叉树保存平衡
                int count=1;
                while (!isBTree(root)){
                    System.out.println("正在进行第"+(count++)+"次旋转" );
                    //存储父节点和祖父节点方便旋转
                    TreeNode[] tns = new TreeNode[2];
                    TreeNode treeNode = root;
                    //找到最小的不平衡树 tns[1]
                    while (!isBTree(treeNode)){
                        tns[0] = tns[1];
                        tns[1] = treeNode;
                        if (!isBTree(treeNode.left)){
                            treeNode = treeNode.left;
                        }else if(!isBTree(treeNode.right)) {
                            treeNode = treeNode.right;
                        }else {
                            break;
                        }
                    }
                    //通过对tns[1]子树的高度 和 tns[1]的子节点来判断旋转类型
                    int hl = height(tns[1].left);
                    int hr = height(tns[1].right);
                    int type = 0; // 0:ll型,1:rr型,2:rl型,3:lr型
                    if (hl>hr && tns[1].left.right!=null){
                        type = 3;
                    }
                    if (hl<hr && tns[1].right.left==null){
                        type = 1;
                    }
                    if(hl<hr && tns[1].right.left!=null){
                        type = 2;
                    }
                    //旋转
                    rotate(type,tns[1],tns[0]);
                }

            }
        }

        /**
         * 旋转函数
         * @param type // 0ll,1rr,2rl,3lr
         * @param parent 父节点
         * @param parentsPatent 祖父节点
         */
        private void rotate(int type,TreeNode parent,TreeNode parentsPatent){
            TreeNode treeNode ;
            switch (type){
                case 0:  //ll型
                    treeNode = parent.left;
                    treeNode.right = parent;
                    parent.left = null;
                    break;
                case 1: //rr
                    treeNode = parent.right;
                    treeNode.left = parent;
                    parent.right = null;
                    break;
                case 2: // rl
                    treeNode = parent.right.left;
                    TreeNode r = parent.right;
                    parent.right = treeNode.left;
                    r.left = treeNode.right;
                    treeNode.left = parent;
                    treeNode.right = r;
                    break;
                case 3: //lr
                    treeNode = parent.left.right;
                    TreeNode l = parent.left;
                    parent.left = treeNode.right;
                    l.right = treeNode.left;
                    treeNode.right = parent;
                    treeNode.left = l;
                    break;
                default:
                    throw new RuntimeException("旋转错误");
            }
            //若果父节点是根节点,则需要更新root
            if (parent==root){
                root = treeNode;
            }else {
                if(parentsPatent.left == parent){
                    parentsPatent.left = treeNode;
                }else {
                    parentsPatent.right = treeNode;
                }
            }
        }

        public boolean isBTree(){
            return isBTree(root);
        }
        public int height(){
            return height(root);
        }
        //判断是否是平衡二叉树
        private boolean isBTree(TreeNode treeNode){
            if(treeNode == null){
                return true;
            }
            return isBTree(treeNode.left) && isBTree(treeNode.right) && Math.abs(height(treeNode.left)-height(treeNode.right))<=1;
        }
        //计算二叉树的高度
        private int height(TreeNode treeNode){
            if(treeNode==null){
                return 0;
            }
            return Math.max(height(treeNode.left),height(treeNode.right))+1;
        }
        //计算该二叉树的元素个数
        public int getLength(){
            length = 0;
            calLength(root);
            return length;
        }
        //计算该二叉树的元素个数
        private void calLength(TreeNode root){
            if (root!=null){
                length++;
                calLength(root.left);
                calLength(root.right);
            }
        }
        //将二叉树先序遍历转换成数组
        public int[] bTreeToArray(){
            int[] rs = new int[getLength()];
            length = 0;
            preorderTraversal( root,rs);
            return rs;
        }

        //先序遍历二叉树
        private void preorderTraversal(TreeNode root,int[] rs){
            if (root != null){
                preorderTraversal(root.left,rs);
                rs[length++] = root.val;
                preorderTraversal(root.right,rs);
            }
        }

        public void preorderTraversal(){
            System.out.println("-----------------------------------------------------------------------");
            preorderTraversal( root);
            System.out.println("-----------------------------------------------------------------------");
        }
        private void preorderTraversal(TreeNode root){
            if (root != null){
                preorderTraversal(root.left);
                System.out.print(root.val+"  ");
                preorderTraversal(root.right);
            }
        }

    }

    //测试验证函数
    public static void main(String[] args) {
        BTree bTree ;
        int nz=100000;
        int ng=50;
        int[] flag;
        for (int i = 0; i < nz; i++) {
            flag = new int[101];
            bTree = new BTree();
            Random random = new Random(System.currentTimeMillis());
            int[] sources = new int[ng];
            for (int j = 0; j < ng; j++) {
                sources[j] = random.nextInt(100);
                flag[sources[j]] +=1 ;
                System.out.println(sources[j]);
                try {
                    bTree.add(sources[j]);
                }catch (StackOverflowError e){
                    System.out.println(Arrays.toString(bTree.bTreeToArray()));
                    return;
                }
            }
            if(!bTree.isBTree()){
                throw new RuntimeException("不是平衡二叉树,算法有误");
            }
            System.out.println(Arrays.toString(sources));
            int[] ints = bTree.bTreeToArray();
            if (bTree.getLength()!=ng){
                System.out.println("bTreeLength ="+bTree.getLength() +",ng="+ng);
                bTree.preorderTraversal();
                throw new RuntimeException("二叉搜索树异常");
            }else {
                //平衡二叉树数组
                System.out.println(Arrays.toString(ints));
                for (int j = 0; j < ng-1; j++) {
                    flag[ints[j]] --;
                    if (ints[j]> ints[j+1]){
                        throw new RuntimeException("二叉排序树数组生成异常");
                    }
                    if(flag[ints[j]] < 0){
                        throw new RuntimeException("二叉排序树插入异常");
                    }
                }
                if(flag[ints[ng-1]] <= 0){
                    throw new RuntimeException("二叉排序树插入异常");
                }
            }

        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值