• 计算字符串表达式的值


    一、题目描述

    给你一个字符串,包含+,-,*,/和(),数字为0-9,让计算该表达式的值,例如"1+2*3-(8/4)+6",结果为11,这是前几天面试去哪儿网,二面面试官让手撕的题目。记忆中本科的时候遇到过,当时也没啥思路。其实这个题需要分两步完成,第一步:把字符串表达式的中缀形式转为后缀形式,怎么转有一定的规则。第二步:计算后缀表达式的值。

    关于什么是前缀,中缀,后缀表达式,请读者自己查阅资源,这里就不介绍了。我们只谈如何从中缀转为后缀,规则如下:

    首先定义一个栈stack用来保存操作符,定义一个List保存后缀表达式的结果,令字符串的当前字符为c:

    1、如果c为操作数,从'0' - '9',则直接添加到list中

    2、如果c为操作符,例如+,-,*,/,首先判断栈是否为空,如果为空,则操作符入栈,如果不为空,当栈顶操作符的优先级比c的优先级高,或者相等的时候,把栈顶操作符弹出,并添加到list中,直到遇到左括号,或者栈顶元素的优先级比c低的时候停止。然后把操作符c入栈。

    3、如果c为左括号,直接入栈

    4、如果c为右括号,则依次弹出栈内的操作符并添加到list,直到遇到左括号。把左括号弹出,但是不添加到list。

    5、当字符串中每个元素都遍历完后,把栈中所有的操作符全部弹出并添加到list中

    上面的操作完成后,后缀表达式也就全部保存到了list中,然后我们就可以计算后缀表达式的值了。计算步骤如下:

    先定义一个栈stack,用来保存操作数,以及中间结果,当遍历list的时候,如果当前元素为:

    1、如果为操作数,则直接入栈

    2、如果为操作符,则从栈中依次弹出2个元素b和a,然后根据操作符的不同,计算a xxx b的值,把计算结果压栈

    3、当list遍历完后,栈中肯定只剩下一个元素,就是最终的结果。

    二、代码演示

    import java.util.LinkedList;
    import java.util.List;
    import java.util.Scanner;
    import java.util.Stack;
    
    public class Main {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            String s = sc.nextLine();
            sc.close();
            System.out.println(getResult(getPost(s)));
        }
        
        /**
         * 计算后缀表达式的值
         * @param list 后缀表达式
         * @return
         */
        public static int getResult(List<Character> list) {
            Stack<String> stack = new Stack<>();
            for(int i = 0; i < list.size(); i++) {
                char c = list.get(i);
                if(c >= '0' && c <= '9') { //当遇到操作数直接压栈
                    stack.push(c + "");
                }
                else {//当遇到操作符的时候,从栈中弹出两个元素,然后根据运算符的不同做相应的运算,然后把运算结果压栈。
                    int b = Integer.parseInt(stack.pop());
                    int a = Integer.parseInt(stack.pop());
                    if(c == '+') stack.push(a + b + "");
                    else if(c == '-') stack.push(a - b + "");
                    else if(c == '*') stack.push(a * b + "");
                    else stack.push(a / b + "");
                }
            }
            //最终栈中肯定只剩下一个元素,就是计算的结果。
            return Integer.parseInt(stack.pop());
        }
        
        /**
         * 把中缀表达式转为后缀表达式
         * 前提条件:操作数的范围为0-9,操作符为+,-,*,/,以及()
         * @param s 字符串表达式
         * @return 
         */
        public static List<Character> getPost(String s) {
            Stack<Character> stack = new Stack<>(); //保存操作符
            LinkedList<Character> list = new LinkedList<>(); //保存最终的后缀表达式
            for(int i = 0; i < s.length(); i++) {
                char c = s.charAt(i);
                if(c >= '0' && c <= '9') list.add(c); //操作数直接输出到后缀表达式中
                else if(c == '+' || c == '-' || c == '*' || c == '/') { 
                    //把比当前操作符c的优先级高或者等于c的优先级的操作符依次弹出栈并保存到后缀表达式中,直到遇到栈顶操作符的优先级比c低
                    while(!stack.isEmpty()) { 
                        if(compare(stack.peek()) >= compare(c)) {
                            list.add(stack.pop());
                        }
                        else break;
                    }
                    stack.push(c);//当前操作符c入栈
                }
                else if(c == '(') stack.push(c); //左括号直接入栈
                else {
                    //当遇到右括号的时候,把栈中的操作符依次弹出并追加到后缀表达式中,直到遇到左括号停止,并把左括号弹出。
                    while(stack.peek() != '(') { 
                        list.add(stack.pop());
                    }
                    stack.pop();
                }
            }
            //把栈中所有的操作符全部弹出追加到后缀表达式中
            while(!stack.isEmpty())list.add(stack.pop());
            return list;
        }
        
        /**
         * 计算运算符的优先级
         * @param c  运算符
         * @return
         */
        public static int compare(char c) {
            if(c == '+' || c == '-') return 1;
            else if(c == '*' || c == '/') return 2;
            else return 0;
        }
    }
  • 相关阅读:
    rpm 和 yum 的使用技巧
    启动Hadoop时遇到Name or service not knownstname 错误
    使用Pod集成Bugtags填坑记
    xcode 上 crash 调试的三种方法
    在MAC上安装虚拟机搭建Ubuntu开发环境
    shell复习---文件解压命令
    XCODE7新变化之-test
    Object-C单元测试&MOCK(摘录精选)
    shell复习笔记----查找与替换
    shell复习笔记----命令与参数
  • 原文地址:https://www.cnblogs.com/neuzk/p/9655337.html
Copyright © 2020-2023  润新知