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

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

 

 


 

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

举例:输入“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

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-06-01
  • 2021-11-29
  • 2021-11-26
  • 2022-02-08
  • 2021-06-28
  • 2022-02-26
猜你喜欢
  • 2022-12-23
  • 2021-11-21
  • 2021-04-26
  • 2022-01-12
  • 2022-12-23
  • 2021-05-17
  • 2022-12-23
相关资源
相似解决方案