波兰式和逆波兰的相互转化

前言:

       公司软件开发的新特性,里面有部分代码读起来很生涩,一直在入栈出栈,搞的一头雾水,后来问了公司的SE大牛(膜拜),说这个是逆波兰式,当时就懵逼了,后来wiki了下,发现原来就是后缀表达式,想想当年刷ACM还刷过这类题,不过太久远了,早就忘记了!我们平时数学中接触到最多的是中缀表达式:1+2*(1+5)/3,这种表达式非常适合人去阅读,但是不适合用数据结构进行表示用于计算,而后缀表达式就可以用非常简单的入栈出栈来进行计算。

1、波兰式(中缀表达式)转化为逆波兰(后缀表达式)

先看一段伪代码

BEGIN:
   1.将波兰式进行分割,存放到数组中element[]中
   2.从左向右扫描波兰式,执行下面的操作;
   3.if (当扫描到的elemen[i]为数值时)
         将element[i]添加到输出串str中;
   4.if (当扫描到的elemen[i]是括号'('时)
                        将elemen[i] push到stack中;
   5.while (当扫描到的elemen[i]是操作符op时)
                       if (stack为空 或 stack栈顶为'(' 或 扫描到的运算符优先级比栈顶操作符高,不包括相等)
                             将elemen[i] push 到stack中;
                             break;
                       else
                             stack出栈保存到字符串str中
   6.if (当扫描到的elemen[i]是闭括号')')
                       stack中运算符逐个出栈并输出到str中,直到遇到开括号'(';
                       将'('出栈并丢弃;
   7.返回第2.步
   8.while (扫描结束而栈中还有运算符)
                        运算符出栈并加到字符串str中
END



直接上代码:
public class ReversePolish {
    private Set ele = new HashSet<>();

    private ReversePolish() {
        ele.add("+");
        ele.add("-");
        ele.add("*");
        ele.add("/");
        ele.add("(");
        ele.add(")");
    }

    public boolean isOp(String element) {
        if (ele.contains(element))
            return true;
        else
            return false;
    }

    public int priority(String op) {
        if (op.equals("+") || op.equals("-"))
            return 1;
        if (op.equals("*") || op.equals("/"))
            return 2;
        else
            return 0;
    }


    public String reversePolish(String[] element, Stack stack) {
        StringBuffer str = new StringBuffer("");
        for (int i = 0; i < element.length; i++) {
            if (!isOp(element[i])) {
                str.append(element[i] + " ");
                continue;
            }
            while (true) {
                if (stack.empty() || element[i].equals("(") || priority(element[i]) > priority(stack.peek())) {
                    stack.push(element[i]);
                    break;
                }
                String elementStr = stack.pop();
                if (elementStr.equals("(")) {
                    break;
                }
                str.append(elementStr+" ");
            }
        }
        while (!stack.empty()) {
            str.append(stack.pop()+" ");
        }
        return str.toString().trim();
    }
}

2.逆波兰式运算

上面的代码展示的是将波兰式转化为逆波兰式,而逆波兰式,就可以通过非常简单的出栈入栈来进行计算
比如波兰式1+2*3/6转化为逆波兰式为1 2 3 * 6 / +,逆波兰的计算就通过下面的方法
同样上一段伪代码

BEGIN:
   1.将逆波兰式进行分割,存放到数组中element[]中
   2.从左向右扫描波兰式,执行下面的操作;
   3.if(扫描到elemen[i]为数值)
	将elemen[i]存到stack栈中
   4.if(扫描到elemen[i]为运算符时)
	将stack中取出两个数,进行elemen[i]运算符的操作
   5.返回到2.步
   6.取出stack的数为逆波兰式的运算结果
END

波兰式和逆波兰的相互转化_第1张图片

上代码:

public class CalReversePolish {
    private double calculate(String op, double val1, double val2) {
        if (op.equals("+"))
            return val1 + val2;
        if (op.equals("-"))
            return val1 - val2;
        if (op.equals("/"))
            return val2 / val1;
        if (op.equals("*"))
            return val1 * val2;
        throw new RuntimeException("wrong operator");
    }

    public double calReversePolish(String polish) {
        Stack stack = new Stack<>();
        String[] element = polish.split(" ");
        for (int i = 0; i < element.length; i++) {
            if (element[i].equals("+") || element[i].equals("-") || element[i].equals("*") || element[i].equals("/")) {
                stack.push(calculate(element[i], stack.pop(), stack.pop()));
                continue;
            }
            stack.push(Double.parseDouble(element[i]));
        }
        return stack.pop();
    }
}



你可能感兴趣的:(算法,逆波兰)