java数据结构与算法总结(四)--Java实现表达式计算(中缀表达式转化为后缀表达式/逆波兰式)

在做一道算法题时遇到该问题,写一个计算器其中有加减乘除和括号,用最快的算法算出来。后来根据答案想了下用下面的算法是复合答案的意思。

定义:

  • 中缀表达式:

我们平时写的数学表达式一般为中缀表达式,如“5+2*(3*(3-1*2+1))”,直接拿中缀表达式直接让计算机计算表达式的结果并不能做到。

  • 后缀表达式:

把中缀表达表达式“5+2*(3*(3-1*2+1))”转化“523312*-1+**+”这样的形式,就是后缀表达式。这种记法叫做后缀(postfix)或逆波兰(reverse Polish)记法。计算这个问题最容易的方法就是使用一个栈。
转换方法:

  1. 按次序读取中缀表达式的字符。
  2. 读到一个操作数的时候,立即放入到输出中。
  3. 读到操作符“+”,“-”,“*”,“/”,则从栈中弹出栈元素并输出,直到遇到优先级更低或者“(”的为止操作符为止(该元素不出栈)。
  4. 读到操作符“(”,则直接把“(”压入栈中。
  5. 读到操作符“)”,则从栈中弹出栈元素并输出,直到遇到第一个“(”为止。其中“(”不再添加到输出中,而是直接舍弃。
  6. 当输入为空时,把栈里的操作符全部依次弹出并输出。

举例:

操作说明输出
读取5把操作数直接输出 5
读取+栈为空,把操作符压入栈+5
读取2把操作数直接输出+52
读取*栈顶元素为+,优先级低于*,把操作符压入栈+*52
读取(把 ( 直接压入栈+*(52
读取3把操作数直接输出+*(523
读取*栈顶元素为(,把操作符压入栈+*(*523
读取(把 ( 直接压入栈+*(*(523
读取3把操作数直接输出+*(*(5233
读取-栈顶元素为(,把操作符压入栈+*(*(-5233
读取1把操作数直接输出+*(*(-52331
读取*栈顶元素为-,优先级低于*,把操作符压入栈+*(*(-*52331
读取2把操作数直接输出+*(*(-*523312
读取+栈顶元素为*,优先级高于+,以此弹出*,-到输出,到 ( 停止,把操作符压入栈中+*(*(+523312*-
读取1把操作数直接输出+*(*(+523312*-1
读取)从栈中弹出+到输出,遇到第一个 ( 停止,把 ( 弹出栈+*(*523312*-1+
读取)从栈中弹出*到输出,遇到第一个 ( 停止,把 ( 弹出栈+*523312*-1+*
结束读取把栈中的元素全部弹出到输出 523312*-1+**+

后缀表达式的计算:

  1. 按次序读取后缀表达式的每一个字符。
  2. 读取到操作数时,把操作数压入栈中。
  3. 读取到操作符时,对栈顶的2个操作数做相应运算,要注意操作数的前后顺序。结果压入栈中。
  4. 读取完所有的字符后,弹出栈。得到的值就是所求结果。

代码:

import java.util.Stack; 
 
 
public class Main {
 
    static Stack<Character> op = new Stack<>();
 
    public static Float getv(char op, Float f1, Float f2){
        if(op == '+') return f2 + f1;
        else if(op == '-') return f2 - f1;
        else if(op  == '*') return f2 * f1;
        else if(op == '/') return f2 / f1;
        else return Float.valueOf(-0);
    }
 
    /**
     * calculate the value of the reverse Polish expression
     * @param rp - reverse Polish expression
     * @return - result of the expression
     */
    public static float calrp(String rp){
        Stack<Float> v = new Stack<>();
        char[] arr = rp.toCharArray();
        int len = arr.length;
        for(int i = 0; i < len; i++){
            Character ch = arr[i];
 
            // if is operand, push to the stack
            if(ch >= '0' && ch <= '9') v.push(Float.valueOf(ch - '0'));
 
            // if is operator, calculate the result
            // with top 2 operands in the stack,
            // push the result into the stack
            else v.push(getv(ch, v.pop(), v.pop()));
        }
        return v.pop();
    }
 
    /**
     * from infix to postfix
     * @param s - String in the form of infix
     * @return String in the form of postfix
     */
    public static String getrp(String s){
         char[] arr = s.toCharArray();
         int len = arr.length;
         String out = "";
 
         for(int i = 0; i < len; i++){
             char ch = arr[i];
             if(ch == ' ') continue;
 
             // if is operand, add to 
             // the output stream directly
             if(ch >= '0' && ch <= '9') {
                 out+=ch;
                 continue;
             }
 
             //if is '(', push to the stack directly
             if(ch == '(') op.push(ch);
 
             //if is '+' or '-', pop the operator 
             // from the stack until '(' and add to 
             // the output stream
             //push the operator to the stack
             if(ch == '+' || ch == '-'){
                 while(!op.empty() && (op.peek() != '(')) 
                     out+=op.pop();
                 op.push(ch);
                 continue;
             }
 
             //if is '*' or '/', pop the operator stack and 
             // add to the output stream 
             // until lower priority or '('
             //push the operator to the stack
             if(ch == '*' || ch == '/'){
                 while(!op.empty() && (op.peek() == '*' || op.peek() == '/')) 
                     out+=op.pop();
                 op.push(ch);
                 continue;
             }
 
             //if is ')' pop the operator stack and 
             // add to the output stream until '(', 
             // pop '('
             if(ch == ')'){
                 while(!op.empty() && op.peek() != '(') 
                     out += op.pop();
                 op.pop();
                 continue;
             }
         }
         while(!op.empty()) out += op.pop();
         return out;
    }
 
    public static void main(String[] args){
        //constraint: the operand should be 
        // equal or greater than 0 
        // but equal or less than 9
        String exp = "5+2*(3*(2-1))";
        System.out.println(calrp(getrp(exp)));
    }
 
}

输出:

11.0

————————————————
版权声明:本文为CSDN博主「Ring_k」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ring_k/article/details/79598961

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
做一门精致,全面详细的 java数据结构与算法!!!让天下没有难学的数据结构,让天下没有难学的算法,不吹不黑,我们的讲师及其敬业,可以看到课程视频,课件,代码的录制撰写,都是在深夜,如此用心,其心可鉴,他不掉头发,谁掉头发???总之你知道的,不知道的,我们都讲,并且持续更新,走过路过,不要错过,不敢说是史上最全的课程,怕违反广告法,总而言之,言而总之,这门课你值得拥有,好吃不贵,对于你知识的渴求,我们管够管饱话不多说,牛不多吹,我们要讲的本门课程内容:稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀后缀表达式中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序、排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二叉树、二叉树与数组转换、二叉排序树(BST)、AVL树、线索二叉树、赫夫曼树、赫夫曼编码、多路查找树(B树B+树和B*树)、图、图的DFS算法和BFS、程序员常用10大算法、二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法马踏棋盘算法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值