对于表达式计算问题可以分成3部分,输入为中缀表达式,输出为:(1)后缀表达式;(2)计算结果;(3)表达式树,其中后面两个问题的求解依赖于前1个问题的求解。本文详细讨论了这三个问题。
1.后缀表达式的生成
读取中缀表达式,根据以下规则处理
(1)当字符不是操作符时,直接输入,否则进行优先级比较
(2)当栈为空时,将操作符直接压入
(3)当操作符为“(”时,直接压入
(4)当操作符为“)”时,依次弹出操作符,直到(为止,但(并不输出
(5)依次比较栈顶与当前操作符的优先级,如栈顶操作符优先级不比当前操作符低的话,则弹出,直到栈顶操作符优先级比当前操作符低或者栈为空为止,然后将当前操作符压入
(6)比较优先级时“(”是个意外,除非当前操作符为“)”,否则不弹出
(7)当读到输入末尾时,将栈内剩余操作符输出
本文不仅讨论了双目运算符,讨论了单目运算符!-,若要添加其他操作符其方法是类似的,使用到的操作符的优先级顺序如下:
操作符 | 优先级 |
( ) | 4 |
! -($在计算结果用来替换负号) | 3 |
* / | 2 |
+ - | 1 |
2.根据后缀表达式计算表达式结果
读取后缀表达式,若不是操作符则压入栈中,若是操作符则从栈中弹出相应个数的数进行计算,并将结果压入栈中
注:本文还讨论了符号-与减号-混用的情况,如果-前面是操作符或者位于第1位,则说明是负号,将其替换成$
3.生成表达式树
生成表达式树的过程和计算表达式类似,不过不是将树压入栈中,而是将相应的节点压入栈中;也不是将结果压入栈中,而是将新的节点压入栈中
4.实现代码
1 /**本文件用于研究表达式树,包括:1.由中缀表达式生成后缀表达式;2.计算后缀表达式 2 * 3.由后缀表达式构造一棵表达式树;4。由后缀表达式生成中缀、前缀表达式 3 * 4 */ 5 6 import java.util.*; 7 8 public class Main { 9 10 public static void main(String[] args) { 11 // 输入中缀表达式,由0-9、+、-、*、/、!符号组成 12 Scanner inSting=new Scanner(System.in); 13 String middleExpression=inSting.nextLine(); 14 //中缀表达式转换为后缀表达式 15 String behindExpression=middleExpToBehindExp(middleExpression); 16 //计算后缀表达式 17 double answer=calculateBehindExp(behindExpression); 18 System.out.println("计算结果为:"+answer); 19 //构造表达式树 20 expTree temp=behindTreeToExpTree(behindExpression); 21 System.out.println("其表达式树为:"); 22 temp.printExpTree(temp, 0); 23 } 24 static String middleExpToBehindExp(String middleExpression){ 25 /*中缀表达式转换为后缀表达式的规则 26 * 1.如果是数字则直接输出,如果是操作符的话就入栈 27 * 2.比较栈里面操作符之间的优先级,将优先级更高或者相等的输出 28 * 3.遇到)前操作符(不弹出 29 * 4.遇到(后弹出到)为止,但(与)都不输出 30 * 5.弹出操作符后,将当期操作符弹出 31 * 6.读到输入末尾时,将栈中元素全部弹出 32 * 7.优先级设置如下,()4;! - 3;/* 2;+ - 1; 33 */ 34 String behindExp=""; 35 StackhelperStack=new Stack (); 36 //添加一个程序处理负号和减号之间的关系,如果-号前是操作符,则认为是负号,将其替换为其他符号,如$,其优先级和其他单目运算符一样 37 for(int i=0;i =temp2)135 return true;136 else137 return false;138 }139 static double calculateBehindExp(String a){140 //构造辅助栈141 Stack helperStack=new Stack ();142 for(int i=0;i 1)185 {System.out.println("表达式有误3,请检查");return -1;}186 return helperStack.pop();187 }188 static expTree behindTreeToExpTree(String a){189 //生成表达式树的过程和计算过程是类似的190 Stack helperStack=new Stack ();191 for(int i=0;i 1)217 {System.out.println("表达式有误3,请检查");return null;}218 return helperStack.pop();219 }220 }221 222 //构造表达式类223 class expTree{224 char symbol;225 expTree left;226 expTree right;227 expTree(){228 229 }230 expTree(char temp){231 symbol=temp;232 }233 expTree(char temp,expTree leftTree,expTree rightTree){234 symbol=temp;235 left=leftTree;236 right=rightTree;237 }238 void printExpTree(expTree a,int width){239 //如果a不为空,则循环遍历,前序打印240 if(a!=null){241 for(int i=0;i
5.演示结果
注意输入阶乘符号!时,不要输成了感叹号!