zoukankan      html  css  js  c++  java
  • 四则运算(逆波兰表达式)

    1.四则运算

    输入一个表达式(用字符串表示),求这个表达式的值。

    保证字符串中的有效字符包括[‘0’-‘9’],‘+’,‘-’, ‘*’,‘/’ ,‘(’, ‘)’,‘[’, ‘]’,‘{’ ,‘}’。且表达式一定合法。

    示例:

    ​ 输入: 3+2{1+2[-4/(8-6)+7]}

    ​ 输出: 25

    解题思路: 逆波兰表达式

       1)初始化两个栈,运算符栈s1, 数据栈s2 (将此栈定义为集合)
       2)从左到右扫描中缀表达式
       3)遇到操作数,将其压入s2
       4)遇到用算符,比较其与s1栈顶元素的优先级:
           1.如果s1为空,或者栈顶运算符为 "( || [ || {",直接压入栈中
           2.否则,优先级比栈顶元素优先级高也压入s1中,
           3.否则,将s1中用算符弹出压入s2,再转到 4.1中执行
       5) 遇到括号时:
           如果为左括号:"( || [ || {",直接压入s1
           如果为右括号: ") || ] || }", 依次弹出s1中运算符,并压入s2,直到遇到对应的左括号为止,此时丢弃这对括号
       6) 重复步骤2至5,直到表达式最右边
       7)将s1中剩余的运算符依次弹出压入s2
       8) s2即为后缀表达式
     
    
    负数的处理:
       出现负数有两种情况: 
          ①: 表达式第一个就为 '-' 号,则判定此数为负数 如:-3+1
          ②: 表达式中'-'的前一个符号为左括号'(',则判定 此数为负数 如: (-3+1)
       转化方法在前面补0即可如: 0-3+1;   
    

    代码:

    import java.util.*;
    public class Main{
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            String str = sc.nextLine();
            str = str.replaceAll("[\{\[]", "(").replaceAll("[\}\]]",")"); //将中缀表达式中的括号转为小括号
            List<String> l1 =  strToList(str);
            List<String> l2 =  zToH(l1);
            int num = getNum(l2);
            System.out.println(num);
        }
        // 计算后缀表达式
        private static int getNum(List<String> ls) {
            Stack<String> s1 = new Stack<>();
            for (String s : ls) {
                if (s.matches("\d+")) {
                    // 如果为数字压入到s1中
                    s1.push(s);
                } else {
                    // 如果不为数字,从栈中弹出两个数字,进行计算,再压入栈中
                    int num1 = Integer.parseInt(s1.pop());
                    int num2 = Integer.parseInt(s1.pop());
                    int num = cal(num1, num2, s);
                    s1.push(String.valueOf(num));
                }
            }
            return Integer.parseInt(s1.pop());
        }
        //计算结果
        private static int cal(int num1, int num2, String oper) {
            int val = 0;
            switch(oper) {
                case "+":
                    val = num2 + num1;
                    break;
                case "-":
                    val = num2 - num1;
                    break;
                case "*":
                    val = num2 * num1;
                    break;
                case "/":
                    val = num2 / num1;
                    break;
            }
            return val;
        }
        // 将中缀表达式转化为后缀表达式
        private static List<String> zToH(List<String> ls) {
             Stack<String> s1 = new Stack<>(); // 存储字符
             List<String> s2 = new ArrayList<>(); //存储数字
            int i=0;
            for (String s : ls) {
                if (s.matches("\d+")) {
                    // 如果为数字,直接添加到s2中
                    s2.add(s);
                } else if (s1.size() ==0 || "(".equals(s) || "(".equals(s1.peek())) {
                    // 处理负数, 负数有两种情况
                    // 1. 负数存在与第一位如: -3+1
                    //2.负数存在与左括号后面: (-3+1)
                    // 处理方法为在前面补0如: 0-3+1
                    if("-".equals(s) && (i == 0 || "(".equals(ls.get(i-1)))) {
                        s2.add("0");
                    }
                    s1.push(s);
                } else if (")".equals(s)) {
                    // 如果遇到右括号')',依次弹出s1直到遇到左括号'('
                    while(!"(".equals(s1.peek())) {
                        s2.add(s1.pop());
                    }
                    s1.pop(); //弹出左括号
                } else {
                    // 如果栈顶也为 ‘+,-,*,/’,需要比较优先级。
                    //若s的优先级小于等于栈顶元素,s1弹出插入到s2中
                    // 否则,将s压入到s1中
                    while(s1.size() != 0 && isLeve(s) <= isLeve(s1.peek())) {
                        s2.add(s1.pop());
                    }
                    s1.push(s);
                    
                }
                i++;
            }
            // 将s1中剩余的符号插入到s2中
            while(s1.size() != 0) {
                s2.add(s1.pop());
            }
            return s2;
        }
        // 判断优先级
        private static int isLeve(String str) {
            if ("+,-".contains(str)) {
                return 1;
            } else if("*,/".contains(str)) {
                return 2;
            } else {
                return 0;
            }
        }
        // 将中缀表达式转为字符串数组
        private static List<String>  strToList(String str) {
            char[] chars = str.toCharArray();
            List<String> ls = new ArrayList<>();
            int i = 0;
            String s = "";
            for (char ch: chars) {
                if (ch<48 || ch >57) {
                    // 如果不是数字直接添加到集合中
                    ls.add(ch + "");
                } else {
                    // 如果为数字,则需要处理,因为数字可能为多位数
                    s += ch; //数字拼接起来
                    if (i == str.length()-1) {
                        // 如果当前字符串为最后一个则直接添加
                        ls.add(s);
                    } else {
                        if (chars[i+1] <48 || chars[i+1] >57) {
                            ls.add(s);
                            s = ""; 
                        }
                    }
                }
                i++;
            }
            return ls;
        } 
    }
    
  • 相关阅读:
    前端之JQuery
    前端之BOM和DOM
    前端之js
    Django之创建项目、目录层级、基本操作
    前端小练习-Michael的博客界面(粗糙版)
    前端之CSS(下)
    Django简介(MVC、MTV)
    react中自定义函数、生命周期钩子函数、修改状态、组件、组件传值
    react中类组件、函数组件、state、单层遍历、多层遍历、先遍历后渲染、if-else、三目运算符
    搭建react的架手架
  • 原文地址:https://www.cnblogs.com/cqyp/p/15490177.html
Copyright © 2011-2022 走看看