表达式求值


表达式求值分为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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值