zoukankan      html  css  js  c++  java
  • 数据结构和算法 — 平衡二叉树的实现

    创建平衡二叉树,主要是一旦出现不平衡状态如何更改,这个一直是一个比较晕的,什么左旋右旋很乱。下面跟大家说下如何比较好理解的来进行平衡,阅读本文前需要先明白,不平衡的四种情况即,左左,左右,右左,右右四种情况,如果不懂的,可以自己百度,关于这个很多理解。本文主要是针对对于左旋和右旋理解不了或者想学习用java编写的代码。

    其实不管怎么转,其实只是重新改变不平衡节点的左右子树,因此,我们只需要记住不平衡节点的左右子树的左右子树分别该如何得到,就可以。

    1、左左情况。

    因为左边的过长,所以要吧左边的过长的部分从中间折断,这样就可以把3层节点来弄成两层,这样就可以平衡。

    (图片来自网络,侵删)

    因此可以看出,新的左子树的左子树为原不平衡节点K2的左子树的左子树的左子树。新的右子树的左子树为不平衡点的左子树的右子树,新右子树的右子树为不平衡点的右子树,右子树的节点为不平衡节点的值,不平衡点值为原不平衡点左子树的值。

    代码化为:

    BalancedBinaryNode newleftnode=balancedBinaryNode.left.left;

                       BalancedBinaryNode newrightnode=new BalancedBinaryNode();

                       newrightnode.left=balancedBinaryNode.left.right;

                       newrightnode.right=balancedBinaryNode.right;

                       newrightnode.data=balancedBinaryNode.data;

                       balancedBinaryNode.data=balancedBinaryNode.left.data;

                       balancedBinaryNode.left=newleftnode;

                       balancedBinaryNode.right=newrightnode;

    分析:因为左边过长,所以要折半,即把不平衡点左子树的值作为这部分树的根,那么,根的左子树,也就是新的左子树,所有值都比根要小,而新的右子树要比根大。所以,比根小的 只有根的左子树比他小,所以:新的左子树就是新根原来的左子树:即BalancedBinaryNode newleftnode=balancedBinaryNode.left.left;。剩下的三部分很好理解,新根原来的右子树、原根的右子树、原根的大小关系,很明显:新根原来的右子树<原根<原根的右子树,所以将原根作为新根的右子树,也就是新的右子树,将新根的右子树作为新右子树的左子树,将原根的右子树作为新子树的右子树,

    2、右右情况

    与左左情况原理相同,只需要左换右即可

    3、左右

    先附上旋转图(来自网络,侵删)

    说实话,这个做法很完美,但是,理解起来有点困难,尤其是没空间想象能力较差。那我们现在来看一看能不能从结果找到什么。

    首先,既然是左右了,那么一定是存在 不平衡点、不平衡点左孩子、不平衡点左孩子的有孩子  (原因是左右就是左子树的右子树插入孩子),很显然大小关系:不平衡点左孩子<不平衡点左孩子的右孩子<不平衡点,所以平衡成一颗新树就是  新根节点一定是不平衡节点的左孩子的右孩子,那么新左子树是不平衡点的左孩子,新右子树是不平衡点   ok,来看左右子节点的左右子树分别是啥,先看新左子树的左子树,比新左子树小的 只有原来树中比它小的,那就是原树种不平衡点左子树(新左子树)的左子树,同理,新右子树的右子树就是原不平衡点(新右子树)的右子树。现在还剩下不平衡点的左子树的右子树(新根节点)的左右子树,先看左子树,小于新根节点,所以只能是位于新左子树的一部分,但是,它由于属于新左子树原来右子树的一部分,所以大于新左子树,所以为左子树的右子树,同理,新根节点的原右子树就是右子树的左子树。

    所以结论就是:

    根节点的值是:不平衡点的左子树的右子树的值

    根的左子树节点是:不平衡点的左子树的值

    根的右子树节点是:不平衡点的值

    新左子树的左子树是:不平衡点的左子树的左子树

    新左子树的右子树是:不平衡点左子树的右子树的左子树

    新右子树的左子树是:不平衡点左子树的右子树的右子树

    新右子树的右子树是:不平衡点的右子树

    BalancedBinaryNode newleftnode=new BalancedBinaryNode();

                       BalancedBinaryNode newrightnode=new BalancedBinaryNode();

                       newleftnode.data=balancedBinaryNode.left.data;

                       newleftnode.left=balancedBinaryNode.left.left;

                       newleftnode.right=balancedBinaryNode.left.right.left;

                       newrightnode.data=balancedBinaryNode.data;

                       newrightnode.left=balancedBinaryNode.left.right.right;

                       newrightnode.right=balancedBinaryNode.right;

                       balancedBinaryNode.data=balancedBinaryNode.left.right.data;

                       balancedBinaryNode.left=newleftnode;

                       balancedBinaryNode.right=newrightnode;

    4、右左理解方式一样

    5、下面放入整体代码:

    package DataStruct;

    import java.util.LinkedList;

    import java.util.Queue;

    public class BalancedBinaryTree {

             public static class BalancedBinaryNode{

                       public int data;

                       public BalancedBinaryNode left;

                       public BalancedBinaryNode right;

                       public int ceng ;

                       public int du;

             }

             public static BalancedBinaryNode init(int data){

                       BalancedBinaryNode root=new BalancedBinaryNode();

                       root.data=data;

                       root.left=null;

                       root.right=null;

                       root.du=0;

                       return root;

             }

             public static void add(BalancedBinaryNode root,int data){

                       BalancedBinaryNode temp=root;

                       BalancedBinaryNode newNode=new BalancedBinaryNode();

                       newNode.left=null;newNode.right=null;newNode.data=data;

                       while(true){

                                if(data<temp.data){

                                         if(temp.left!=null){

                                                   temp=temp.left;

                                         }else{

                                                   temp.left=newNode;

                                                   return ;

                                         }

                                }else if(data>temp.data){

                                         if(temp.right!=null){

                                                   temp=temp.right;

                                         }else{

                                                   temp.right=newNode;

                                                   return ;

                                         }

                                }else{

                                         return;

                                }

                       }

                      

             }

             public static void balance(BalancedBinaryNode root,int data){

                       Queue<BalancedBinaryNode> queue=new LinkedList<>();

                       if(root==null){

                                return ;

                       }

                       queue.add(root);

                       root.ceng=1;

                       BalancedBinaryNode balancedBinaryNode;

                       while(queue.size()!=0){

                                balancedBinaryNode=queue.poll();

                                int leftheaght=balancedBinaryNode.left==null?0:getDu(balancedBinaryNode.left);

                                int rightheaght=balancedBinaryNode.right==null?0:getDu(balancedBinaryNode.right);

                                //该节点平衡

                                if(Math.abs(leftheaght-rightheaght)<2){

                                         if(balancedBinaryNode.left!=null){

                                                   queue.add(balancedBinaryNode.left);

                                         }

                                         if(balancedBinaryNode.right!=null){

                                                   queue.add(balancedBinaryNode.right);

                                         }

                                }

                                //否则不平衡

                                else{

                                        

                                         if(leftheaght>rightheaght){

                                                   if(data<balancedBinaryNode.left.data){

                                                            leftAndLeft(balancedBinaryNode);

                                                   }else{

                                                            leftandright(balancedBinaryNode);

                                                   }

                                         }else{

                                                   if(data<balancedBinaryNode.right.data){

                                                            System.out.println("右左");

                                                            rightandleft(balancedBinaryNode);

                                                   }else{

                                                            rightandright(balancedBinaryNode);

                                                   }

                                         }

                                }

                       }

             }

             //左左的平衡

             public static void leftAndLeft(BalancedBinaryNode balancedBinaryNode){

                       BalancedBinaryNode newleftnode=balancedBinaryNode.left.left;

                       BalancedBinaryNode newrightnode=new BalancedBinaryNode();

                       newrightnode.left=balancedBinaryNode.left.right;

                       newrightnode.right=balancedBinaryNode.right;

                       newrightnode.data=balancedBinaryNode.data;

                       balancedBinaryNode.data=balancedBinaryNode.left.data;

                       balancedBinaryNode.left=newleftnode;

                       balancedBinaryNode.right=newrightnode;

             }

             //右右的平衡

             public static void rightandright(BalancedBinaryNode balancedBinaryNode){

                       BalancedBinaryNode newleftnnode=new BalancedBinaryNode();

                       BalancedBinaryNode newrightnode=balancedBinaryNode.right.right;

                       newleftnnode.left=balancedBinaryNode.left;

                       newleftnnode.right=balancedBinaryNode.right.left;

                       newleftnnode.data=balancedBinaryNode.data;

                       balancedBinaryNode.data=balancedBinaryNode.right.data;

                       balancedBinaryNode.left=newleftnnode;

                       balancedBinaryNode.right=newrightnode;

             }

             //左右的平衡

             public static void leftandright(BalancedBinaryNode balancedBinaryNode){

                       BalancedBinaryNode newleftnode=new BalancedBinaryNode();

                       BalancedBinaryNode newrightnode=new BalancedBinaryNode();

                       newleftnode.data=balancedBinaryNode.left.data;

                       newleftnode.left=balancedBinaryNode.left.left;

                       newleftnode.right=balancedBinaryNode.left.right.left;

                       newrightnode.data=balancedBinaryNode.data;

                       newrightnode.left=balancedBinaryNode.left.right.right;

                       newrightnode.right=balancedBinaryNode.right;

                       balancedBinaryNode.data=balancedBinaryNode.left.right.data;

                       balancedBinaryNode.left=newleftnode;

                       balancedBinaryNode.right=newrightnode;

             }

             //右左的旋转

             public static void rightandleft(BalancedBinaryNode balancedBinaryNode){

                       BalancedBinaryNode newleftnode=new BalancedBinaryNode();

                       BalancedBinaryNode newrightnode=new BalancedBinaryNode();

                       newleftnode.data=balancedBinaryNode.data;

                       newleftnode.left=balancedBinaryNode.left;

                       newleftnode.right=balancedBinaryNode.right.left.left;

                       newrightnode.data=balancedBinaryNode.right.data;

                       newrightnode.left=balancedBinaryNode.right.left.right;

                       newrightnode.right=balancedBinaryNode.right.right;

                       balancedBinaryNode.data=balancedBinaryNode.right.left.data;

                       balancedBinaryNode.left=newleftnode;

                       balancedBinaryNode.right=newrightnode;

                      

                      

             }

             //获得某个节点的度

             public static int getDu(BalancedBinaryNode binaryNode){

                       int result=0;

                       if(binaryNode.left==null && binaryNode.right==null){

                                result=1;

                       }else if(binaryNode.left==null){

                                result=1+getDu(binaryNode.right);

                       }else if(binaryNode.right==null){

                                result=1+getDu(binaryNode.left);

                       }else{

                                result=1+Math.max(getDu(binaryNode.left),getDu(binaryNode.right));

                       }

                       return result;

             }

             //

             public static void show(BalancedBinaryNode root){

                       Queue<BalancedBinaryNode> queue=new LinkedList<>();

                       if(root==null){

                                System.out.println("空的");

                                return ;

                       }

                       queue.add(root);

                       root.ceng=1;

                       BalancedBinaryNode balancedBinaryNode;

                       while(queue.size()!=0){

                                balancedBinaryNode=queue.poll();

                                if(balancedBinaryNode.left!=null){

                                         balancedBinaryNode.left.ceng=balancedBinaryNode.ceng+1;

                                         queue.add(balancedBinaryNode.left);

                                }

                                if(balancedBinaryNode.right!=null){

                                         balancedBinaryNode.right.ceng=balancedBinaryNode.ceng+1;

                                         queue.add(balancedBinaryNode.right);

                                }

                                System.out.println("数据为:"+balancedBinaryNode.data+" 所在层数 "+balancedBinaryNode.ceng);

                       }

                      

             }

    }

    6、测试代码和结果

             package TestMain;

    import DataStruct.BalancedBinaryTree;

    import DataStruct.BalancedBinaryTree.BalancedBinaryNode;

    public class Main {

                       public static void main(String args[]) {

    //                         int data[]={62, 88, 58, 47, 35, 73, 51, 99, 37, 93};

                                int data[]={1,2,3,4,5,6,7,8};

                                BalancedBinaryNode root=BalancedBinaryTree.init(data[0]);

                                for(int i=1;i<data.length;i++){

                                         BalancedBinaryTree.add(root, data[i]);

                                         BalancedBinaryTree.balance(root,data[i]);

                                }

                                BalancedBinaryTree.show(root);

                       }

             }

                      

    数据为:5 所在层数 1

    数据为:3 所在层数 2

    数据为:6 所在层数 2

    数据为:2 所在层数 3

    数据为:4 所在层数 3

    数据为:7 所在层数 3

    数据为:1 所在层数 4

    数据为:8 所在层数 4

    ---------------------

    [转]

    原文:https://blog.csdn.net/m1179457922/article/details/81745013

  • 相关阅读:
    软件工程最后一次作业
    软件工程第二次结对作业
    软件工程第三次作业
    软件工程第二次个人作业
    软件工程第二次作业
    软件工程第一次作业
    2020软件工程最后一次作业
    软件工程第四次作业
    软件工程第三次作业
    软件工程第二次作业
  • 原文地址:https://www.cnblogs.com/binghuaZhang/p/10810352.html
Copyright © 2011-2022 走看看