中缀表达式求值的思路分析与代码实现
一、问题与解决办法
1.问题
输入一个任意给定的合理包含四则运算的表达式字符串,求解出其结果;
例如:1)“7*2*2-5+1-5+3-4”
求解出结果为:18
2.思路
- 设置两个栈,一个数字栈numStack,用于存储表达式中涉及到的数字,operatorStack用于存储表达式中涉及到的运算符
- 逐个字符分析表达式,直到全部字符都已分析完
- 若当前字符为数字,则判断是否后续字符也为数字,若为数字则进行拼接,直到下一个数字为运算符为止,此时将拼接好的多位数字压入数字栈中。(如果已经是最后一个字符则直接压入栈)
- 若当前字符为算数运算符
- 如果运算符栈为空则直接压入栈中
- 运算符不为空,则对运算符优先级进行判断
- 如果当前运算符优先级大于等于栈顶运算符则直接压入栈中
- 如果优先级低于栈顶运算符,则,从数字栈中取出两个数据,将当前栈顶运算符弹出进行运算,将结果压入数字栈中,将当前运算符压入运算符栈中。
- 此时数字与运算符都已经压入栈中,此时运算符栈中均为优先级相同的运算符,需要进行收尾操作,如果运算符栈不为空,则依次从数字栈中弹出两个数据,与当前栈顶的运算符进行运算。将结果压入数字栈中。最后数字栈中的数字就是所要求解的结果。
二、代码实现
所用的数据结构栈:
class CalculatorStack {
private int maxSize;//栈的容量
private int top;//栈顶
private int [] data;//用来存放数据的区域
public CalculatorStack(int maxSize){
top=-1;
this.maxSize=maxSize;
data= new int[maxSize];
}
public void push(int obj){
if (isFull()){
System.out.println("栈已满");
return;
}
data[++top]= obj;
}
public int pop(){
if (isEmpty()){
throw new RuntimeException("栈为空");
}
return data[top--];
}
public int peek(){
if (isEmpty()){
throw new RuntimeException("栈为空");
}
return data[top];
}
public boolean isEmpty(){
return top==-1;
}
public boolean isFull(){
return top==maxSize-1;
}
//用来判断该字符是否是运算符
public boolean isOperator(char val){
return val=='+' ||val=='-' ||val=='*' ||val=='/' ;
}
/**
*
* @param oper 待判断的运算符
* @return 运算符的优先级
*/
public int getPriority(char oper){
if (oper=='/' ||oper=='*')
return 1;
else if (oper=='+'||oper=='-')
return 0;
else
return -1;//假定表达式只有四则运算
}
/**
*
* @param num1 先出栈的数据
* @param num2 后出栈的数据
* @param oper 运算符
* @return
*/
public int calculate(int num1,int num2,int oper){
int res =0;//用于存放计算结果
switch (oper){
case '+':
res=num1+num2;
break;
case '-':
res=num2-num1;
break;
case '*':
res=num1*num2;
break;
case '/':
res=num2/num1;
break;
}
return res;
}
}
具体算法:
public class Calculator {
public static void main(String[] args) {
Calculator cal = new Calculator();
System.out.println(cal.Calculate("7*2*2-5+1-5+3-4"));//问题是不能处理多位数据
}
public int Calculate(String expression){
CalculatorStack numStack = new CalculatorStack(12);//数字栈
CalculatorStack operStack =new CalculatorStack(12);//符号栈
int res = 0;//存放结果
int num1 = 0;//存放先弹出的数字
int num2 = 0;//存放后弹出的数字
String tempNum = "";//用于拼接多位数字
int oper =0;//存放弹出的运算符
int index = 0;//扫描表达式的游标
char ch=' ';//保存扫描得到的字符
char [] expre= expression.toCharArray();
while(true){
//1.获取当前的字符
ch = expre[index];
//2.判断字符类型
if (operStack.isOperator(ch)){//若为运算符
//判断符号栈中是否为空,为空进栈
if (operStack.isEmpty()){
operStack.push(ch);
}else{//不为空比较优先级,优先级高,入栈
if (operStack.getPriority((char) operStack.peek())<operStack.getPriority(ch)){
operStack.push(ch);
}else{//待入栈算符优先级低于栈顶元素,开始计算
num1=numStack.pop();
num2=numStack.pop();
oper=(char)operStack.pop();
res = operStack.calculate(num1,num2,oper);//进行计算
numStack.push(res);
operStack.push(ch);
}
}
}else {//若为数字则应查看下一位是否也是数
tempNum+=ch;
if (index==expre.length-1){
numStack.push(Integer.parseInt(tempNum));
}
else if (operStack.isOperator(expre[index+1])){
numStack.push(Integer.parseInt(tempNum));
tempNum="";
}
}
index++;
if (index>=expre.length){
break;
}
}
//上述步骤仅代表字符串扫描完毕,可能仍存在剩余
while (true){
if (operStack.isEmpty()){
break;
}
num1=numStack.pop();
num2=numStack.pop();
oper=(char)operStack.pop();
res = operStack.calculate(num1,num2,oper);//进行计算
numStack.push(res);
}
return res;
}
}