表达式求值分为2个步骤:
1、中缀表达式=》后缀表达式
2、后缀表达式求值
以9+(3+5)*2+10/2为例
一、中缀表达式=》后缀表达式 思路
遍历整个表达式,如果是数字直接输出,如果是操作符则与栈顶元素比较操作符的优先级,如果优先级比栈顶元素大,则入栈,如果小于等于则栈顶元素出现(循环比较),然后该操作符入栈。
以上为例(设op为操作符栈):
9 3 5 + 2 * + 10 2 / +
二、求值
循环后缀表达式,并以此进栈,碰到操作符则pop两个操作数计算后再入栈,重复上面步骤,直到结束
三、代码如下
public class ReversePolishNotation {
Stack<Character> stack;
Queue<String> queue;
/*
* test case 9+(3+5)*2+10/2
*/
public int calculate(String s) {
stack = new Stack<Character>();
queue = new LinkedList<String>();
for(int i=0;i<s.length();i++){
char c = s.charAt(i);
if(c==' ')//去除表达式空的字符
continue;
int v = 0;
if(Character.isDigit(c)){//if a digit
//有可能这个不是个位数,要进行判断
while(Character.isDigit(c)){
v = v*10+(int)(c-'0');
if(i+1<s.length()){
i++;
c = s.charAt(i);
}
else
break;
}
if(!Character.isDigit(c))
i--;
queue.add(Integer.toString(v));
}
else{
if(stack.isEmpty()){
stack.add(c);
continue;
}
if(c=='('){
stack.add('(');
}
else if(c==')'){
while(!stack.isEmpty()&&stack.peek()!='('){
queue.add(stack.pop().toString());
}
stack.pop();//pop '('
}
else if(stack.peek()=='('){//如果栈顶元素为'(',则直接进栈
stack.add(c);
}
else if(compareOpc(c, stack.peek())>0){//比栈顶元素优先级高,进栈
stack.add(c);
}
else {//小于等于栈顶元素的优先级
if(!stack.isEmpty())
{/*出栈的时候要判断栈顶元素是不是'('*/
while(!stack.isEmpty()&&stack.peek()!='('&&compareOpc(c, stack.peek())<=0){
queue.add(stack.pop().toString());
}
stack.add(c);
}
}
}
}
while(!stack.isEmpty())//当遍历完表达式,要pop出操作符栈的所有操作符
queue.add(stack.pop().toString());
/*中缀表达是转后缀表达式完毕,下面求后缀表达式的值*/
Object[] obj = queue.toArray();
String[] str = new String[obj.length];
queue.toArray(str);
return evalRPN(str);
}
/*比较运算符的优先级*/
public int compareOpc(char c1,char c2){
if((c1=='+'||c1=='-')&&(c2=='+'||c2=='-'))
return 0;
if((c1=='+'||c1=='-')&&(c2=='*'||c2=='/'))
return -1;
if((c1=='*'||c1=='/')&&(c2=='*'||c2=='/'))
return 0;
if((c1=='*'||c1=='/')&&(c2=='+'||c2=='-'))
return 1;
return 0;
}
/*给定后缀表达式求值*/
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<Integer>();
for(String s:tokens){
if(s.equals("+")){
stack.push(stack.pop()+stack.pop());
}
else if(s.equals("-")){
int va = stack.pop();
int vb = stack.pop();
stack.push(vb-va);
}
else if(s.equals("*")){
stack.push(stack.pop()*stack.pop());
}
else if(s.equals("/")){
int va = stack.pop();
int vb = stack.pop();
stack.push(vb/va);
}
else
stack.push(Integer.valueOf(s));
}
return Integer.valueOf(stack.pop());
}
}
参考:
http://www.nowamagic.net/librarys/veda/detail/2307