• 通过不断迭代,编写<通过中缀表达式,构造表达式树>的代码


    今天要练习的算法是通过中缀表达式生成表达式树。中缀、前缀、后缀表达式的概念就不赘述了,学习链接:中缀、前缀、后缀表达式

    参考代码学习链接:表达式树—中缀表达式转换成后缀表达式(一)


     

    • 【迭代 ①】:识别单个运算符,进行分割,通过递归的思想构建表达式树。

    举例:输入“1+2”,输出

    Java code of phase[1]:

     1     void Express2BTree(String str){
     2         root=Express2BTreeProc(str);
     3     }
     4     private BTNode Express2BTreeProc(String str){
     5         BTNode parent=new BTNode();
     6         boolean isSet[]={false,false};    //【0】:left,【1】:right
     7         String tmp=new String();        //临时字符串
     8         for(int i=0;i<str.length();i++){
     9             char ch=str.charAt(i);
    10             if(ch>=48 && ch<=57){            //是数字
    11                 tmp+=ch;
    12             }
    13             else if(ch=='+' || ch=='-' || ch=='*' || ch=='/'){
    14                 parent.data=String.valueOf(ch);
    15                 if(! isSet[0]){            //左子树未构造
    16                     isSet[0]=true;
    17                     parent.lChild=Express2BTreeProc(tmp);
    18                     tmp=new String("");    //归零初始化
    19                 }
    20             }
    21         }
    22         if(isSet[0] && (! isSet[1])){//右子树未构造
    23             isSet[1]=true;
    24             parent.rChild=Express2BTreeProc(tmp);
    25             tmp=new String("");    //归零初始化
    26         }
    27         if(! isSet[0]) parent.data=tmp;//如果函数处理的全是数字(叶子节点),那么就返回叶子节点
    28         return parent;
    29     }

    逻辑盲区:

    1、启动构造右子树的 if  语句不能嵌套在上方的 if 中,否则不能触发。

    2、数字0~9的ascii码是[ 48 , 57 ],故应写<=、>=。


    • 【迭代 ②】:判断多个表达式。

    举例:输入“1+2+3”,输出:

    代码改进:在临时字符串递加段,加入【或】判断条件 isSet[0] ,如果左子树已构造,继续扫描、递加。


    • 【迭代 ③】:识别优先级。*、/ 的优先级比+、- 的要高。

    (在这里我修改了toString打印树函数,填充符由*变为space,避免混淆)

    如果代码按原先的方式跑,结果是:

     

    但是根据运算符优先级,应该是:

    修改两处代码:

    1.递归函数中引入 only_Have_Priority 变量:

    1         boolean only_Have_Priority=false;
    2         if(( str.indexOf("+")<0 && str.indexOf("-")<0 )  
    3                             &&
    4         ( str.indexOf("*")>=0 || str.indexOf("/")>=0 ))
    5             only_Have_Priority=true;
    6         //能够找到 * / 、不能找到 + -

    2.触发对表达式进行分割的判断语句中引入一个【与】判断条件:

    ((!only_Have_Priority)&&(ch=='*' || ch=='/'))

    完整代码:

    Java code of phase[3]:

     1     void Express2BTree(String str){
     2         root=Express2BTreeProc(str);
     3     }
     4     private BTNode Express2BTreeProc(String str){
     5         BTNode parent=new BTNode();
     6         int i;
     7         boolean isSet[]={false,false};    //【0】:left,【1】:right
     8     //    boolean havaAddOrSub = ( str.indexOf("+")<0 || str.indexOf("-")<0 ) ? false : true;
     9         
    10         boolean only_Have_Priority=false;
    11         if(( str.indexOf("+")<0 && str.indexOf("-")<0 )  
    12                             &&
    13         ( str.indexOf("*")>=0 || str.indexOf("/")>=0 ))
    14             only_Have_Priority=true;
    15         //能够找到 * / 、不能找到 + -
    16         
    17         String tmp=new String();        //临时字符串
    18         
    19         for(i=0;i<str.length();i++){
    20             char ch=str.charAt(i);    //是数字、或者左树已构造  || (havaAddOrSub && (ch=='' || ch=='-') )   
    21             if( (ch>=48 && ch<=57 ) || isSet[0] || ((!only_Have_Priority)&&(ch=='*' || ch=='/'))   ){
    22                 tmp+=ch;
    23             }
    24             else if(ch=='+' || ch=='-' || ch=='*' || ch=='/'){
    25                 parent.data=String.valueOf(ch);
    26                 if(! isSet[0]){            //左子树未构造
    27                     isSet[0]=true;
    28                     parent.lChild=Express2BTreeProc(tmp);
    29                     tmp=new String("");    //归零初始化
    30                 }
    31             }
    32         }

    逻辑盲点:

    对 only_Have_Priority 进行赋值时,应该是【与】而不是或。想错了。

    测试:

    输入:1*2+3*4

    输出:

    输入:1*2+3*4+5*6

    输出:


    • 【迭代 ④】:小括号的优先级应最高

     运行中出现bug。经查是原来的 only_Have_Priority  判断语句的不足。修改之。

    加入了堆栈思想的括号判断语句。

    Java code of phase[4]:

     1     void Express2BTree(String str){
     2         root=Express2BTreeProc(str);
     3     }
     4     private BTNode Express2BTreeProc(String str){
     5         BTNode parent=new BTNode();
     6         int i;
     7         boolean isSet[]={false,false};    //【0】:left,【1】:right
     8     //    boolean havaAddOrSub = ( str.indexOf("+")<0 || str.indexOf("-")<0 ) ? false : true;
     9         
    10         boolean only_Have_Priority=false;
    11         int inBracket=0;        //判断当前字符是否在括号中    
    12                 
    13         boolean havaMulti=false;
    14         boolean havaAdd=false;
    15         for(i=0;i<str.length();i++){
    16             char ch=str.charAt(i);
    17             if(ch=='(') inBracket++;
    18             else if(ch==')') inBracket--;
    19             else if(inBracket==0){            //在括号内
    20                 if(ch=='*' || ch == '/') havaMulti=true;
    21                 else if(ch=='-' || ch == '+') havaAdd=true;
    22             }
    23         }
    24         if((!havaAdd) && (havaMulti)) only_Have_Priority=true;
    25         //能够找到 * / 、不能找到 + -
    26         
    27         inBracket=0;
    28         
    29         String tmp=new String();        //临时字符串
    30         
    31         for(i=0;i<str.length();i++){
    32             char ch=str.charAt(i);    //是数字、或者左树已构造  
    33             if(ch=='('){
    34                 if(inBracket>0) tmp+=ch;//括号内的括号
    35                 inBracket++;
    36             }
    37             else if(ch==')'){
    38                 inBracket--;
    39                 if(inBracket>0) tmp+=ch;
    40             }
    41             else if( (ch>=48 && ch<=57 ) 
    42                     || isSet[0] 
    43                     || ((!only_Have_Priority)&&(ch=='*' || ch=='/')) //不存在(只有1*2),也就是1*2+3
    44                     || inBracket>0  ){
    45                 tmp+=ch;
    46             }
    47             else if(ch=='+' || ch=='-' || ch=='*' || ch=='/'){
    48                 parent.data=String.valueOf(ch);
    49                 if(! isSet[0]){            //左子树未构造
    50                     isSet[0]=true;
    51                     parent.lChild=Express2BTreeProc(tmp);
    52                     tmp=new String("");    //归零初始化
    53                 }
    54             }
    55         }
    56         
    57         if(isSet[0] && (! isSet[1])){//右子树未构造
    58             isSet[1]=true;
    59             parent.rChild=Express2BTreeProc(tmp);
    60             tmp=new String("");    //归零初始化
    61         }
    62         if(! isSet[0]) parent.data=tmp;//如果函数处理的全是数字(叶子节点),那么就返回叶子节点
    63         return parent;
    64     }

    测试输入:((3*4)/(1+2))*((1+1)/(1-2))

    测试输出:

    测试输入:(1+2)*3

    测试输出:


    【在一次测试中发现异常】:

    输入:(1+2)*3-2

    输出:

    然后改了一个小时bug。我的函数写的还是有问题,反正现在无论怎么输入,只要是一个正常的表达式,都没什么问题了。

    修改BUG后代码:

     1     void Express2BTree(String str){
     2         root=Express2BTreeProc(str);
     3     }
     4     private BTNode Express2BTreeProc(String str){
     5         int i;
     6         //首尾括号剥夺
     7         if(str.length()>1 && str.charAt(0)=='(' && str.charAt(str.length()-1)==')'){
     8             String tmp=str.substring(1, str.length()-1);
     9             //是否存在括号内字符?
    10             boolean haveInnerChar=false;
    11             int inBracket=0;    
    12             for(i=0;i<str.length();i++){
    13                 char ch=str.charAt(i);
    14                 if(ch=='(') inBracket++;
    15                 else if(ch==')') inBracket--;
    16                 else if(inBracket==0){            //在括号内
    17                     haveInnerChar=true;
    18                 }
    19             }
    20             if(!haveInnerChar) str=tmp;
    21         }
    22         BTNode parent=new BTNode();
    23 
    24         boolean isSet[]={false,false};    //【0】:left,【1】:right
    25     //    boolean havaAddOrSub = ( str.indexOf("+")<0 || str.indexOf("-")<0 ) ? false : true;
    26         
    27         boolean only_Have_Priority=false;
    28         int inBracket=0;        //判断当前字符是否在括号中    
    29         
    30 /*        if(( str.indexOf("+")<0 && str.indexOf("-")<0 )  
    31                             &&
    32         ( str.indexOf("*")>=0 || str.indexOf("/")>=0 ))
    33             only_Have_Priority=true;*/
    34         boolean havaMulti=false;
    35         boolean havaAdd=false;
    36         for(i=0;i<str.length();i++){
    37             char ch=str.charAt(i);
    38             if(ch=='(') inBracket++;
    39             else if(ch==')') inBracket--;
    40             else if(inBracket==0){            //在括号内
    41                 if(ch=='*' || ch == '/') havaMulti=true;
    42                 else if(ch=='-' || ch == '+') havaAdd=true;
    43             }
    44         }
    45         if((!havaAdd) && (havaMulti)) only_Have_Priority=true;
    46         //能够找到 * / 、不能找到 + -
    47         
    48         inBracket=0;
    49         
    50         String tmp=new String();        //临时字符串
    51         
    52         for(i=0;i<str.length();i++){
    53             char ch=str.charAt(i);    //是数字、或者左树已构造  
    54             if(ch=='('){
    55                 tmp+=ch;//括号内的括号
    56                 inBracket++;
    57             }
    58             else if(ch==')'){
    59                 inBracket--;
    60                 tmp+=ch;
    61             }
    62             else if( (ch>=48 && ch<=57 ) 
    63                     || isSet[0] 
    64                     || ((!only_Have_Priority)&&(ch=='*' || ch=='/')) //不存在(只有1*2),也就是1*2+3
    65                     || inBracket>0  ){
    66                 tmp+=ch;
    67             }
    68             else if(ch=='+' || ch=='-' || ch=='*' || ch=='/'){
    69                 parent.data=String.valueOf(ch);
    70                 if(! isSet[0]){            //左子树未构造
    71                     isSet[0]=true;
    72                     parent.lChild=Express2BTreeProc(tmp);
    73                     tmp=new String("");    //归零初始化
    74                 }
    75             }
    76         }
    77         
    78         if(isSet[0] && (! isSet[1])){//右子树未构造
    79             isSet[1]=true;
    80             parent.rChild=Express2BTreeProc(tmp);
    81             tmp=new String("");    //归零初始化
    82         }
    83         if(! isSet[0]) parent.data=tmp;//如果函数处理的全是数字(叶子节点),那么就返回叶子节点
    84         return parent;
    85     }
    View Code

    完整代码:

      1 import java.util.*;
      2 
      3 public class demo {
      4     public static void main(String args[]){
      5 
      6 /*        tree.Express2BTree("((3*4)/(1+2))*((1+1)/(1-2))");
      7         System.out.println(tree);*/
      8         BTtree tree=new BTtree();
      9         tree.splitCh=' ';
     10         Scanner scan;
     11         int flag=10;
     12         while(flag>0){
     13             flag--;
     14             scan=new Scanner(System.in);//generate input flu
     15             System.out.print("请输入中缀表达式: ");//input reminder
     16             String str=new String(scan.nextLine());//assignment
     17             tree.Express2BTree(str);
     18             System.out.println("前缀表达式: ");//input reminder
     19             tree.PreOrderTraversal();
     20             System.out.println("后缀表达式: ");//input reminder
     21             tree.PostOrderTraversal();
     22         }
     23         scan=new Scanner(System.in);
     24         scan.close();
     25 
     26     }
     27 }
     28 
     29 class BTtree{//二叉树类
     30     class BTNode{//节点类
     31         String data=new String("0");
     32         BTNode lChild=null;
     33         BTNode rChild=null;
     34         boolean LTag=false;//=0 : 指向左孩子。 =1 : 指向前驱
     35         boolean RTag=false;//=0 : 指向右孩子。 =1 : 指向后继
     36         int height=1;        //用于AVL树
     37         BTNode(){}
     38         BTNode(String data){this.data=data;}
     39         BTNode(int num){this.data=Integer.toString(num);};
     40     }
     41     void Express2BTree(String str){
     42         root=Express2BTreeProc(str);
     43     }
     44     private BTNode Express2BTreeProc(String str){
     45         int i;
     46         //首尾括号剥夺
     47         if(str.length()>1 && str.charAt(0)=='(' && str.charAt(str.length()-1)==')'){
     48             String tmp=str.substring(1, str.length()-1);
     49             //是否存在括号内字符?
     50             boolean haveInnerChar=false;
     51             int inBracket=0;    
     52             for(i=0;i<str.length();i++){
     53                 char ch=str.charAt(i);
     54                 if(ch=='(') inBracket++;
     55                 else if(ch==')') inBracket--;
     56                 else if(inBracket==0){            //在括号内
     57                     haveInnerChar=true;
     58                 }
     59             }
     60             if(!haveInnerChar) str=tmp;
     61         }
     62         BTNode parent=new BTNode();
     63 
     64         boolean isSet[]={false,false};    //【0】:left,【1】:right
     65     //    boolean havaAddOrSub = ( str.indexOf("+")<0 || str.indexOf("-")<0 ) ? false : true;
     66         
     67         boolean only_Have_Priority=false;
     68         int inBracket=0;        //判断当前字符是否在括号中    
     69         
     70 /*        if(( str.indexOf("+")<0 && str.indexOf("-")<0 )  
     71                             &&
     72         ( str.indexOf("*")>=0 || str.indexOf("/")>=0 ))
     73             only_Have_Priority=true;*/
     74         boolean havaMulti=false;
     75         boolean havaAdd=false;
     76         for(i=0;i<str.length();i++){
     77             char ch=str.charAt(i);
     78             if(ch=='(') inBracket++;
     79             else if(ch==')') inBracket--;
     80             else if(inBracket==0){            //在括号内
     81                 if(ch=='*' || ch == '/') havaMulti=true;
     82                 else if(ch=='-' || ch == '+') havaAdd=true;
     83             }
     84         }
     85         if((!havaAdd) && (havaMulti)) only_Have_Priority=true;
     86         //能够找到 * / 、不能找到 + -
     87         
     88         inBracket=0;
     89         
     90         String tmp=new String();        //临时字符串
     91         
     92         for(i=0;i<str.length();i++){
     93             char ch=str.charAt(i);    //是数字、或者左树已构造  
     94             if(ch=='('){
     95                 tmp+=ch;//括号内的括号
     96                 inBracket++;
     97             }
     98             else if(ch==')'){
     99                 inBracket--;
    100                 tmp+=ch;
    101             }
    102             else if( (ch>=48 && ch<=57 ) 
    103                     || isSet[0] 
    104                     || ((!only_Have_Priority)&&(ch=='*' || ch=='/')) //不存在(只有1*2),也就是1*2+3
    105                     || inBracket>0  ){
    106                 tmp+=ch;
    107             }
    108             else if(ch=='+' || ch=='-' || ch=='*' || ch=='/'){
    109                 parent.data=String.valueOf(ch);
    110                 if(! isSet[0]){            //左子树未构造
    111                     isSet[0]=true;
    112                     parent.lChild=Express2BTreeProc(tmp);
    113                     tmp=new String("");    //归零初始化
    114                 }
    115             }
    116         }
    117         
    118         if(isSet[0] && (! isSet[1])){//右子树未构造
    119             isSet[1]=true;
    120             parent.rChild=Express2BTreeProc(tmp);
    121             tmp=new String("");    //归零初始化
    122         }
    123         if(! isSet[0]) parent.data=tmp;//如果函数处理的全是数字(叶子节点),那么就返回叶子节点
    124         return parent;
    125     }
    126     
    127     protected BTNode root=new BTNode();
    128     BTtree(){
    129     }
    130     BTtree(int layer){
    131         //用队列的方式构造n层树
    132         List<BTNode> queue=new ArrayList<BTNode>();
    133         int front=0;
    134         int rear=0;//队尾插入
    135         queue.add(root);//初始化入队
    136         rear++;
    137         int i , k=0 , j;
    138         for(j=0;j<layer;j++){
    139             int nowRear=rear;
    140             for(i=front;i<nowRear;i++){
    141                 //出队,生两个孩子
    142                 BTNode parent=queue.get(front++);
    143                 BTNode lChild=new BTNode();
    144                 lChild.data=Integer.toString(++k);
    145                 BTNode rChild=new BTNode();
    146                 rChild.data=Integer.toString(++k);
    147                 parent.lChild=lChild;
    148                 parent.rChild=rChild;
    149                 queue.add(lChild);
    150                 rear++;
    151                 queue.add(rChild);
    152                 rear++;
    153             }
    154         }
    155     }
    156     BTtree(String express){//通过中缀表达式进行构造
    157         //1.对表达式进行括号补全。
    158         
    159         
    160     }
    161     public String toString(){//重写打印函数
    162         String padding=new String(" ");
    163         List<BTNode> queue=new ArrayList<BTNode>();
    164         List<String[]> PrintList=new ArrayList<String[]>();
    165         int front=0;
    166         int rear=0;//队尾插入
    167         queue.add(root);//初始化入队
    168         rear++;
    169         int i , k=0 , j;
    170         
    171         String emptySignal=new String("");//空信号
    172         
    173         String str[]=new String[1];
    174         str[0]=root.data;
    175         PrintList.add(str);//打印数据结构初始化
    176         int layer=1;//下一层字符串的数目是2^1=2。
    177         int pos=0;
    178         
    179         boolean flag=true;
    180         ok:
    181         while(flag){
    182             pos=0;//pos初始化
    183             String tmp[]=new String[(int)Math.pow((int)2, (int)(layer++))];//length=2^layer
    184             flag=false;        //循环标志初始化
    185             int nowRear=rear;
    186             int nowFront=front;
    187             for(i=front;i<nowRear;i++){
    188                 String nowStr=new String();
    189                 BTNode parent=queue.get(front++);
    190                 if(parent==null) break ok;    //跳出两重循环
    191                 if(parent.data.equals(emptySignal)){//如果是空的,派生出两个空孩子
    192                     for(int t=0;t<2;t++){
    193                         tmp[pos++]=padding;
    194                         BTNode empty=new BTNode();
    195                         empty.data=emptySignal;
    196                         queue.add(empty);rear++;
    197                     }
    198                 }else{
    199                     if(parent.lChild!=null){
    200                         flag=true;                    //只要这一层存在孩子,就可以继续循环下去。
    201                         queue.add(parent.lChild);
    202                         tmp[pos++]=parent.lChild.data;
    203                         rear++;
    204                     }else{
    205                         tmp[pos++]=padding;
    206                         BTNode empty=new BTNode();
    207                         empty.data=emptySignal;
    208                         queue.add(empty);
    209                         rear++;
    210                     }
    211                     if(parent.rChild!=null){
    212                         flag=true;
    213                         queue.add(parent.rChild);
    214                         tmp[pos++]=parent.rChild.data;
    215                         rear++;
    216                     }else{
    217                         tmp[pos++]=padding;
    218                         BTNode empty=new BTNode();
    219                         empty.data=emptySignal;
    220                         queue.add(empty);
    221                         rear++;
    222                     }
    223                 }
    224             }                // end of for
    225             PrintList.add(tmp);
    226         }                    // end of while
    227         /*
    228         for(i=0;i<PrintList.size();i++){
    229             for(j=0;j<PrintList.get(i).length;j++) System.out.print(PrintList.get(i)[j]+" ");
    230             System.out.println();
    231         }*/
    232         //后处理
    233         String[] PrintListLine=new String[PrintList.size()-1];
    234         for(i=PrintListLine.length-1;i>=0;i--){//循环构造
    235             //首先进行构造
    236             String tmp=new String();
    237             for(j=0;j<PrintList.get(i).length;j++){
    238                 tmp+=PrintList.get(i)[j];
    239                 if(j!=PrintList.get(i).length-1) tmp+=" ";
    240             }
    241             PrintListLine[i]=tmp;
    242         }
    243         for(i=PrintListLine.length-2;i>=0;i--){//居中操作
    244             int spaceNum=(PrintListLine[i+1].length()-PrintListLine[i].length())/2;
    245             String space=new String();
    246             for(int t=0;t<spaceNum;t++) space+=" ";
    247             PrintListLine[i]=space+PrintListLine[i]+space;
    248         }    
    249         String outStr=new String();
    250         for(i=0;i<PrintListLine.length;i++){//最后构造一个字符串
    251             outStr+=PrintListLine[i]+"
    ";
    252         }
    253         return outStr;
    254     }
    255     void PreOrderTraversal(){
    256         PreOrder(root);
    257         System.out.println();
    258     }
    259     char splitCh=',';
    260     private void PreOrder(BTNode obj){
    261         if(obj!=null){
    262             System.out.print(obj.data+splitCh);
    263             PreOrder(obj.lChild);
    264             PreOrder(obj.rChild);
    265         }
    266     }
    267     void InOrderTraversal(){
    268         InOrder(root);
    269         System.out.println();
    270     }
    271     private void InOrder(BTNode obj){    
    272         if(obj!=null){
    273             InOrder(obj.lChild);
    274             System.out.print(obj.data+splitCh);
    275             InOrder(obj.rChild);
    276         }
    277     }
    278     void PostOrderTraversal(){
    279         PostOrder(root);
    280         System.out.println();
    281     }
    282     private void PostOrder(BTNode obj){    
    283         if(obj!=null){
    284             
    285             InOrder(obj.lChild);
    286             InOrder(obj.rChild);
    287             System.out.print(obj.data+splitCh);
    288         }
    289     }
    290 }
    291 
    292 
    293 
    294 //线索二叉树
    295 class BThrTree extends BTtree{
    296     BThrTree(BTtree obj){//由父类构造而来
    297         //首先拷贝根节点
    298         BTNode tmp=new BTNode();
    299         tmp.data=obj.root.data;
    300         copy(root,obj.root);
    301     }
    302     void copy(BTNode node1,BTNode node2){
    303         if(node2.lChild!=null){//左树递归
    304             BTNode l=new BTNode();
    305             l.data=node2.lChild.data;//拷贝左树    
    306             node1.lChild=l;//左树赋值            
    307             copy(node1.lChild,node2.lChild);
    308         }
    309         if(node2.rChild!=null){//右树递归
    310             BTNode r=new BTNode();
    311             r.data=node2.rChild.data;//拷贝右树
    312             node1.rChild=r;//右树赋值
    313             copy(node1.rChild,node2.rChild);
    314         }    
    315     }
    316     public void InThreadingFabric(){//中序线索化构造
    317         BTNode now=root;
    318         InThreading(now); 
    319         pre.RTag=true;//【最后一个后继为null】
    320         pre.rChild=null;
    321     }
    322     private BTNode pre=null;//前驱指针
    323     private void InThreading(BTNode node){//中序线索化递归
    324         if(node!=null){//保证节点非空
    325             InThreading(node.lChild);//左子树线索化
    326             if(node.lChild==null){//如果左子树不存在
    327                 node.LTag=true;//线索化
    328                 node.lChild=pre;//前驱    【第一个前驱为null】
    329             }
    330             if(pre!=null && pre.rChild==null){//后继
    331                 pre.RTag=true;
    332                 pre.rChild=node;
    333             }
    334             pre=node;//保持pre指向node的前驱。
    335             InThreading(node.rChild);//左子树线索化
    336         }
    337     }
    338     void InOrderTraversal_Thr(){//线索化遍历
    339         BTNode now=root;
    340         //遍历前驱
    341         while(now.lChild!=null){//要么有左子树。
    342             now=now.lChild;
    343         }
    344         while(now!=null){//要么有左子树。
    345             System.out.print(now.data+",");
    346             if(now.RTag){now=now.rChild;}//如果是后继,就继续后继。
    347             else{
    348                 now=now.rChild;//如果不是,则令右子树的最左节点为后继
    349                 while(!now.LTag) now=now.lChild;
    350             }
    351         }
    352         System.out.println();
    353     }
    354 }
    355 
    356 
    357 class SearchBST extends BTtree{//二叉查找树
    358     SearchBST(int[] nums){//由二维数组构造
    359         root.data=String.valueOf(nums[0]);//构造根节点
    360         for(int i=1;i<nums.length;i++){//对其他元素进行构造
    361             BTNode node=new BTNode();
    362             node.data=String.valueOf(nums[i]);//构造叶子节点
    363             BTNode parent=root;
    364             int nodeV=nums[i];
    365             while(parent!=null){
    366                 int parentV=Integer.valueOf(parent.data).intValue();//当前根节点的值
    367                 if(nodeV<parentV){//左叶子
    368                     if(parent.lChild==null){//当前根节点的左叶子非空
    369                         parent.lChild=node;//挂入节点
    370                         break;                //如果这里没有加【break】,就会死循环。待解决☆☆☆
    371                     }
    372                     parent=parent.lChild;//如果这里空了,跳出循环
    373                 }else{
    374                     if(parent.rChild==null){
    375                         parent.rChild=node;//挂入节点
    376                         break;                //☆☆☆
    377                     }
    378                     parent=parent.rChild;//如果这里空了,跳出循环                    
    379                 }
    380             }
    381         }
    382     }
    383     SearchBST(){}
    384 }
    385 
    386 class AVLTree extends BTtree{    //平衡二叉树
    387     AVLTree(int[] nums){//由二维数组构造
    388         root.data=String.valueOf(nums[0]);
    389         for(int i=1;i<nums.length;i++) AVLinsert(root,null,true,String.valueOf(nums[i]));
    390     }
    391     BTNode LLRotate(BTNode node){//左子树.高度-右子树.高度==2 【向右旋转】
    392         /*
    393          * 根节点的左孩子  为新的根节点。
    394          * 老根节点成为新根节点的右孩子
    395          * 根节点的左孩子  的右子树作为 老根节点的左子树
    396         */ 
    397         BTNode pre=node;
    398         node=node.lChild;//根节点的左孩子  为新的根节点。
    399         //从此之后node就是【根节点的左孩子】
    400         pre.lChild=node.rChild;//根节点的左孩子(node)  的右子树作为 老根节点(pre)的左子树
    401         node.rChild=pre;
    402         //pre: 老根节点
    403         pre.height=Math.max(getHeight(pre.lChild), getHeight(pre.rChild))+1;//递归增加树的高度
    404         node.height=Math.max(getHeight(node.lChild), getHeight(node.rChild))+1;//递归增加树的高度
    405         return node;//返回根节点
    406     }
    407     
    408     BTNode RRRotate(BTNode node){//左子树.高度-右子树.高度==-2 【向左旋转】
    409         /*
    410          * 根节点的左孩子  为新的根节点。
    411          * 老根节点成为新根节点的右孩子
    412          * 根节点的左孩子  的右子树作为 老根节点的左子树
    413          */    
    414         BTNode pre=node;
    415         node=node.rChild;//根节点的右孩子  为新的根节点。
    416         //从此之后node就是【根节点的左孩子】
    417         pre.rChild=node.lChild;//根节点的左孩子(node)  的右子树作为 老根节点(pre)的左子树
    418         node.lChild=pre;
    419         //pre: 老根节点
    420         pre.height=Math.max(getHeight(pre.lChild), getHeight(pre.rChild))+1;//递归增加树的高度
    421         node.height=Math.max(getHeight(node.lChild), getHeight(node.rChild))+1;//递归增加树的高度
    422         return node;
    423     }
    424     
    425     BTNode LRRotate(BTNode node){//左子树.高度-右子树.高度==2 【向右旋转】
    426         node.lChild=RRRotate(node.lChild);
    427         node=LLRotate(node);
    428         return node;
    429     }
    430     
    431     BTNode RLRotate(BTNode node){//左子树.高度-右子树.高度==2 【向右旋转】
    432         node.rChild=LLRotate(node.rChild);
    433         node=RRRotate(node);
    434         return node;
    435     }
    436     //                  当前节点           父节点               
    437     void AVLinsert(BTNode node,BTNode parent,boolean isLeft,String data){
    438         int dataV=Integer.valueOf(data).intValue();
    439         int nodeV=0;
    440         if(node!=null) nodeV=Integer.valueOf(node.data).intValue();
    441         if(node==null){
    442             BTNode newNode=new BTNode();
    443             newNode.data=data;
    444             if(isLeft) parent.lChild=newNode;
    445             else        parent.rChild=newNode;
    446         }
    447         
    448         else if(dataV<nodeV){//向左插入
    449             AVLinsert(node.lChild,node,true,data);
    450             node.height=Math.max(getHeight(node.lChild), getHeight(node.rChild))+1;//递归增加树的高度
    451             
    452             System.out.println("sub="+(getHeight(node.lChild)-getHeight(node.rChild)));
    453             System.out.println("node="+node.data);
    454             
    455             if(getHeight(node.lChild)-getHeight(node.rChild)==2){
    456                 System.out.println("L变形前
    "+this);
    457                 if(getHeight(node.lChild.lChild)>getHeight(node.lChild.rChild)){
    458                     System.out.println("LL");
    459                     boolean flag=false;
    460                     if(root.data.equals(node.data)) flag=true;
    461                     if(!flag){
    462                         if(isLeft) parent.lChild=LLRotate(node);
    463                         else parent.rChild=LLRotate(node);
    464                     }else node=LLRotate(node);
    465                     if(flag) root=node;
    466                 }else{
    467                     System.out.println("LR");
    468                     boolean flag=false;
    469                     if(root.data.equals(node.data)) flag=true;
    470                     if(!flag){
    471                         if(isLeft) parent.lChild=LRRotate(node);
    472                         else parent.rChild=LRRotate(node);
    473                     }else node=LRRotate(node);
    474                     if(flag) root=node;
    475                 }
    476                 System.out.println("变形后
    "+this);
    477             }
    478             System.out.println(this);
    479             
    480         }else{
    481             AVLinsert(node.rChild,node,false,data);
    482             node.height=Math.max(getHeight(node.lChild), getHeight(node.rChild))+1;//递归增加树的高度
    483             
    484             System.out.println("sub="+(getHeight(node.lChild)-getHeight(node.rChild)));
    485             System.out.println("node="+node.data);
    486             
    487             if(getHeight(node.lChild)-getHeight(node.rChild)==-2){
    488                 System.out.println("R变形前
    "+this);
    489                 if(getHeight(node.rChild.lChild)>getHeight(node.rChild.rChild)){
    490                     System.out.println("RL");
    491                     boolean flag=false;
    492                     if(root.data.equals(node.data)) flag=true;
    493                     if(!flag){
    494                         if(isLeft) parent.lChild=RLRotate(node);
    495                         else parent.rChild=RLRotate(node);
    496                     }else node=RLRotate(node);
    497                     if(flag) root=node;
    498                 }else{
    499                     System.out.println("RR");
    500                     boolean flag=false;
    501                     if(root.data.equals(node.data)) flag=true;
    502                     if(!flag){
    503                         if(isLeft) parent.lChild=RRRotate(node);
    504                         else parent.rChild=RRRotate(node);
    505                     }else node=RRRotate(node);
    506                     if(flag) root=node;
    507                 }
    508                 System.out.println("变形后
    "+this);
    509             }
    510             System.out.println(this);
    511         }
    512     }
    513     
    514     int getHeight(BTNode node){
    515         if(node!=null){
    516             return node.height;
    517         }else{
    518             return 0;
    519         }
    520     }
    521     void test(){
    522         root=new BTNode(0);
    523         BTNode node[]=new BTNode[3];
    524         for(int i=0;i<3;i++) node[i]=new BTNode(i+1);
    525         root.lChild=node[0];
    526         root.lChild.rChild=node[1];
    527         root.lChild.lChild=node[2];
    528         System.out.println(this);
    529         root=LRRotate(root);
    530         System.out.println(this);
    531         System.out.println(root.height);
    532         System.out.println(root.lChild.height);
    533         System.out.println(root.rChild.height);
    534     }
    535     AVLTree(){}
    536 }
    View Code

    程序运行结果:

  • 相关阅读:
    rabbitmq channel参数详解
    rabbitmq direct、fanout、topic 三种Exchange java 代码比较
    spark 性能优化
    spark sql 窗口函数over partition by
    Python爬虫从入门到进阶(4)之xpath的使用
    Python爬虫从入门到进阶(3)之requests的使用
    Python爬虫从入门到进阶(2)之urllib库的使用
    Mac环境下Redis的安装
    Mac环境下Vagrant的安装
    Mac环境下Scrapy的安装
  • 原文地址:https://www.cnblogs.com/TQCAI/p/7635089.html
Copyright © 2020-2023  润新知