简单四则运算

问题描述

实现一个基本的计算器来计算一个简单的字符串表达式的值。注意事项如下: - 输入是一个字符串表达式(可以假设所给定的表达式都是有效的) - 字符串表达式可以包含的运算符号为:左括号 (, 右括号 ), 加号 +, 减号 - - 可以包含的数字为:非负整数(< 10) - 字符串中不包含空格 - 处理除法 case 的时候,可以直接省略小数部分结果,只保留整数部分参与后续运算 - 请不要使用内置的库函数 eval

思路

首先明确一点,四则运算中乘法和除法的优先级是最高的,所以要优先考虑乘除,加减运算留到最后再去算,加上表达式可以有括号,在将乘除运算完过后要优先把括号中的式子的值计算出来。 那么面对一个带有括号的四则运算表达式,我们怎么进行计算呢?对我们人来说这是很简单的,按照规则一点点算就是了,可是计算机只能从前往后看这个表达式,它是呆板的,怎么把后面的优先级高的计算完再去找前面的优先级低的呢?我们可以利用广为人知的数据结构-栈,来分别存储数字和运算符

ini 复制代码
     static Stack<Character> cal=new Stack<>();
     static Stack<Integer>  number=new Stack<>();

先从前往后遍历一遍表达式,

遇到数字则直接压入数字栈中

遇到乘除运算的时候我们不能直接就取后面的数字来与前面的数组进行运算,因为当遇到4*(2+3*2)这种表达式时,我们只会取到一个左括号,无法计算,所以我们直接将其入栈

遇到加减运算时,我们也不能直接进行计算,因为无法确定两边的数字是否被乘除所占用,或是一个没有被计算完毕的括号表达式,所以也是直接入栈,但是这个时候我们可以看一看运算符栈中是否有乘除运算符,如果有的话,从数字栈中取出两个数进行相应的运算然后再将数字入栈

ini 复制代码
              switch (k) {
                case '(':
                case '/':
                case '*':
                    cal.add(k);
                    break;
                
                case '+':
                if(cal.size()>0){
                    char x=cal.lastElement();
    
                    if(x=='*'){
    
                        cal.pop();
                        int firstnum=number.lastElement();
                        number.pop();
                        int secondnum=number.lastElement();
                        number.pop();
                        number.add(firstnum*secondnum);
    
                    }else if(x=='/'){
    
                        cal.pop();
                        int firstnum=number.lastElement();
                        number.pop();
                        int secondnum=number.lastElement();
                        number.pop();
                        number.add(secondnum/firstnum);
                    }
    
                    
                }
                cal.add(k);                    
                    break;
                case '-':
    
                if(cal.size()>0){
                    char x=cal.lastElement();
    
                    if(x=='*'){
    
                        cal.pop();
                        int firstnum=number.lastElement();
                        number.pop();
                        int secondnum=number.lastElement();
                        number.pop();
                        number.add(firstnum*secondnum);
    
                    }else if(x=='/'){
    
                        cal.pop();
                        int firstnum=number.lastElement();
                        number.pop();
                        int secondnum=number.lastElement();
                        number.pop();
                        number.add(secondnum/firstnum);
                    }
    
                    
                }
                cal.add(k);
                    break;
                default:
                    number.add(k-48);//小于10的单个字符直接入栈
                    break;
            }
        }
        

如果遇到括号,遇到左括号我们不做任何处理,直接将其入栈,然后继续按照上面的规则进行运算即可,如果遇到的是右括号,我们就需要把这个括号表达式的值给算出来。

遇到右括号后循环的从运算符栈中取运算符,每次取两个数字进行相应的运算(这个时候不考虑优先级了,因为如果有加减运算那么它们前面的乘除运算就一定被计算完毕,如果没有加减运算就不用考虑优先级了),直到取到左括号为止,然后继续遍历表达式

scss 复制代码
            char kk=cal.lastElement();
            cal.pop();
            while(kk!='('){
                Traverse(kk);//不考虑优先级进行运算
                kk=cal.lastElement();
                cal.pop();
            }

利用上面这些操作循环遍历一次表达式,剩下的运算就不用考虑优先级了,不断的从运算符栈中取运算符进行计算即可,最后数字栈中只剩一个数,直接取走返回答案即可

下面放一下完整的代码,有兴趣的可以复制下来去测试着玩一下,如上分析如有错误敬请各位指出

ini 复制代码
public class Main {        
static Stack<Character> cal=new Stack<>();
static Stack<Integer>  number=new Stack<>();
public static int solution(String expression) {
    

    int length=expression.length();
    for(int i=0;i<length;i++){
        char k=expression.charAt(i);
        if(k==')'){

            char kk=cal.lastElement();
            cal.pop();
            while(kk!='('){
                Traverse(kk);
                kk=cal.lastElement();
                cal.pop();
            }
        }else{
            switch (k) {
                case '(':
                case '/':
                case '*':
                    cal.add(k);
                    break;
                
                case '+':
                if(cal.size()>0){
                    char x=cal.lastElement();
    
                    if(x=='*'){
    
                        cal.pop();
                        int firstnum=number.lastElement();
                        number.pop();
                        int secondnum=number.lastElement();
                        number.pop();
                        number.add(firstnum*secondnum);
    
                    }else if(x=='/'){
    
                        cal.pop();
                        int firstnum=number.lastElement();
                        number.pop();
                        int secondnum=number.lastElement();
                        number.pop();
                        number.add(secondnum/firstnum);
                    }
    
                    
                }
                cal.add(k);                    
                    break;
                case '-':
    
                if(cal.size()>0){
                    char x=cal.lastElement();
    
                    if(x=='*'){
    
                        cal.pop();
                        int firstnum=number.lastElement();
                        number.pop();
                        int secondnum=number.lastElement();
                        number.pop();
                        number.add(firstnum*secondnum);
    
                    }else if(x=='/'){
    
                        cal.pop();
                        int firstnum=number.lastElement();
                        number.pop();
                        int secondnum=number.lastElement();
                        number.pop();
                        number.add(secondnum/firstnum);
                    }
    
                    
                }
                cal.add(k);
                    break;
                default:
                    number.add(k-48);//小于10的单个字符直接入栈
                    break;
            }
        }

    }

    while(cal.size()>0){
        char kk=cal.lastElement();
        cal.pop();            
        Traverse(kk);
    }
    return number.lastElement();
}
public static void Traverse(char kk){
    int firstnum=number.lastElement();
    number.pop();

    int secondnum=number.lastElement();
    number.pop();
    int num=0;
    switch (kk) {
        case '+':
            num=firstnum+secondnum;
            break;
        case '-':
            num=secondnum-firstnum;
            break;
        case '*':
            num=secondnum*firstnum;
            break;
        case '/':
            num=secondnum/firstnum;
            break;

    }
    number.add(num);
}

public static void main(String[] args) {
    // You can add more test cases here
    System.out.println(solution("1+1") == 2);
    System.out.println(solution("3+4*5/(3+2)") == 7);
    System.out.println(solution("4+2*5-2/1") == 12);
    System.out.println(solution("(1+(4+5+2)-3)+(6+8)") == 23);

    System.out.println("请输入一个10以内的加减乘除计算公式");
    Scanner scan=new Scanner(System.in);

    String s=scan.nextLine();
    System.out.println("结果为"+solution(s));
}

}

相关推荐
火星机器人life2 小时前
基于ceres优化的3d激光雷达开源算法
算法·3d
虽千万人 吾往矣2 小时前
golang LeetCode 热题 100(动态规划)-更新中
算法·leetcode·动态规划
arnold663 小时前
华为OD E卷(100分)34-转盘寿司
算法·华为od
ZZTC3 小时前
Floyd算法及其扩展应用
算法
lshzdq4 小时前
【机器人】机械臂轨迹和转矩控制对比
人工智能·算法·机器人
2401_858286115 小时前
115.【C语言】数据结构之排序(希尔排序)
c语言·开发语言·数据结构·算法·排序算法
猫猫的小茶馆5 小时前
【数据结构】数据结构整体大纲
linux·数据结构·算法·ubuntu·嵌入式软件
u0107735145 小时前
【字符串】-Lc5-最长回文子串(中心扩展法)
java·算法
帅逼码农5 小时前
K-均值聚类算法
算法·均值算法·聚类
姚先生975 小时前
LeetCode 209. 长度最小的子数组 (C++实现)
c++·算法·leetcode