逆波兰表达式(后缀表达式)

  

   逆波兰式,也叫做后缀表达式,每一运算符都置于其运算对象之后,故称为后缀表示。值得注意的是,后缀表达式没有优先级的概念,会按照运算符从左向右进行运算。这种理解这对于把普通表达式转换为后缀表达式很重要。比如下面的式子:

   a+b ---> a,b,+
   a+(b-c) ---> a,b,c,-,+
   a+(b-c)*d ---> a,b,c,-,d,*,+
   a+d*(b-c)--->a,d,b,c,-,*,+
   a=1+3 ---> a=1,3 +

 实现代码如下:

 /**
     * 计算后缀表达式,操作很简单,就是入栈和出栈进行计算
     * @param tokens 后缀表达式
     */
	public static int evalRPN(String[] tokens) {
		int returnValue = 0;
		String operators = "+-*/";
		Stack<String> stack = new Stack<String>();

		for (String t : tokens) {
			//如果解析到的字符不是运算符就将当前的值push到栈里,
			if (!operators.contains(t)) {
				//push~
				stack.push(t);
			} else {
				//如果解析到的是运算符,那么就可以进行计算了
				//能够保证计算结果的正确性的前提是有两个保证:
				//1、后缀表达式的特性:运算符是紧跟着操作数后面的
				//2、栈的特点:栈是先进后出的特点,先push进去的元素,在pop出一个元素时,取出的是最后push进去的元素,注意,pop出一个元素后,该元素就不存在栈中了
				//基于以上两点,可以形成基本思路:对后缀表达式进行遍历,如果遇到的不是运算符那么就push到栈中,如果遇到运算符就将前面的两个数字取出运算
				//由此可见,如果一个表达式的第一个运算符的前面只有一个数字,这样的表达式不应该算是后缀表达式
				int a = 0, b = 0;
				if (!stack.empty()) {
					a = Integer.valueOf(stack.pop());
				}
				if (!stack.empty()) {
					b = Integer.valueOf(stack.pop());
				}
				//当前解析到的运算符,本例中的运算符是用一个字符串表示的四种基本运算
				int index = operators.indexOf(t);
				//将计算后的值再次push到栈中
				switch (index) {
				case 0:
					stack.push(String.valueOf(a + b));
					break;
				case 1:
					stack.push(String.valueOf(b - a));
					break;
				case 2:
					stack.push(String.valueOf(a * b));
					break;
				case 3:
					stack.push(String.valueOf(b / a));
					break;
				}
			}
		}
		//栈顶上的元素就是累计算的结果
		returnValue = Integer.valueOf(stack.pop());
		return returnValue;
	}


   以上算法是摘自:http://www.programcreek.com/2012/12/leetcode-evaluate-reverse-polish-notation/ 我只加了两个if判断。

   后缀表达式,运算及其简洁,只需要通过入栈和出栈就可以完成简单运算,但是我们平时使用的都是普通表达式,因此下面来实现将普通表达式转换为后缀表达式的算法:

  

/** 
     * 优先级比较 
     * @param operator1 比较值 
     * @param operator2 被比较值 
     * @return 小于等于返回false,大于返回true 
     */  
    public static  boolean comparePrior(String operator1, String operator2) {  
        if("(".equals(operator2)) {  
            return true;  
        }  
        if ("*".equals(operator1) || "/".equals(operator1)) {  
            if ("+".equals(operator2) || "-".equals(operator2)) {  
                return true;  
            }  
        }  
        return false;  
    }  
  
    /** 
     * 转为后缀表达式: 
     * 1、如果是"("直接压入stack栈。 
     * 2、如果是")",依次从stack栈弹出运算符加到数组newExpressionStrs的末尾,值到遇到"("; 
     * 3、如果是非括号,比较扫描到的运算符,和stack栈顶的运算符。如果扫描到的运算符优先级高于栈顶运算符则,
     *   把运算符压入栈。否则的话,就依次把栈中运算符弹出加到数组newExpressionStrs的末尾,直到遇到优先级低于扫描到的运算符或栈空,
     *   并且把扫描到的运算符压入栈中。就这样依次扫描,知道结束为止。如果扫描结束,栈中还有元素,则依次弹出加到数组newExpressionStrs的末尾,
     *   就得到了后缀表达式。 
     * @param expressionStrs 
     * @return 
     */  
    public static String[] toSuffixExpression(String[] expressionStrs) {  
        //新组成的表达式  
        List<String> newExpressionStrs = new ArrayList<String>();  
        Stack<String> stack = new Stack<String>();  
        for (int i = 0; i < expressionStrs.length; i++) {  
        	 // 如果是左括号,则直接
            if ("(".equals(expressionStrs[i])) {
                stack.push(expressionStrs[i]);  
            } else if ("+".equals(expressionStrs[i]) || "-".equals(expressionStrs[i]) || "*".equals(expressionStrs[i]) || "/".equals(expressionStrs[i])) {  
                if (!stack.empty()) { 
                    String s = stack.pop();  
                  //如果栈值优先级小于要入栈的值,则继续压入栈  
                    if(comparePrior(expressionStrs[i], s)) { 
                        stack.push(s);  
                    } else { 
                    	//否则取出值  
                        newExpressionStrs.add(s);  
                    }  
                }  
                stack.push(expressionStrs[i]);  
            } else if (")".equals(expressionStrs[i])) { //如果是")",则出栈,一直到遇到"("  
                while (!stack.empty()) {  
                    String s = stack.pop();  
                    if (!"(".equals(s)) {  
                        newExpressionStrs.add(s);  
                    } else {  
                        break;  
                    }  
                }  
            } else {  
                newExpressionStrs.add(expressionStrs[i]);  
            }  
        }  
        while (!stack.empty()) {  
            String s = stack.pop();  
            newExpressionStrs.add(s);  
        }  
        return newExpressionStrs.toArray(new String[0]);  
    }  


  

  

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值