• 栈实现综合计算器(中缀表达式)


    栈的特性在上篇中已经介绍,本篇直接讲述实现综合计算器思路。

    使用栈完成表达式的计算思路:

      1.通过一个index值(索引),来遍历我们的表达式

      2.如果我们发现是一个数字,就直接入数栈

      3.如果发现当前的符号栈为空,就直接入栈

      4.如果栈中有操作符,就进行比较,如果当前的操作符优先级小于或者等于栈中的操作符,就需要从数栈中pop出两个数,再从符号栈中pop出一个符号,进行运算,将得到的结果入数栈,然后将当前的操作符入符号栈,如果当前的操作符优先级大于符号栈中的操作符,就直接入符号栈

      5.当表达式扫描完毕,就顺序的从数栈和符号栈中pop出相应的数和符号,并运行。

      6.最后在数栈中只有一个数字,就是表达式的结果

    图示:

     实现代码:

    package com.atxihua;
    
    public class Calculator {
        public static void main(String[] args) {
            //完成如下表达式的计算
            String expression="7*2*2-5+1-5+3-4";//结果为18,如何处理多位数计算
            //创建两个栈,一个数栈,一个符号栈
            ArrayStack2 numStack=new ArrayStack2(10);
            ArrayStack2 operStack=new ArrayStack2(10);
            //定义需要相关的相关变量
            int index=0;//用于扫描
            int num1=0;
            int num2=0;
            int oper=0;
            int res=0;
            char ch=' ';//用于拼接多位数
            String keepNum="";//用于拼接字符,处理多位数
            //开始while循环的扫描expression
            while (true){
                //依次得到expression的每一个字符
                ch=expression.substring(index,index+1).charAt(0);
                //判断ch是什么,然后做相应的处理
                if(operStack.isOper(ch)){//如果是运算符
                    //判断当前的符号栈是否为空
                    if(!operStack.isEmpty()){
                        //如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或者等于栈中的操作符
                        //就需要从数栈中pop出两个数
                        //在从符号栈中pop出一个符号,进行运算,将得到结果,入数栈,然后将当前的操作符入符号栈
                        if(operStack.priority(ch)<=operStack.priority(operStack.peek())){
                            num1=numStack.pop();
                            num2=numStack.pop();
                            oper=operStack.pop();
                            res=numStack.cal(num1,num2,oper);
                            //把运算的结果入数栈
                            numStack.push(res);
                            //然后将当前的操作栈入符号栈
                            operStack.push(ch);
                        }else{
                            //如果当前的操作符的优先级大于栈中的操作符,就直接入符号栈
                            operStack.push(ch);
                        }
                    }else {
                        //如果为空直接入符号栈
                        operStack.push(ch);//1+3
                    }
                }else {
                    //如果是数,直接入数栈
    //                numStack.push(ch-48);//单位数
                    /*
                    * 分析思路
                    * 当处理多位数时,不能发现是一个数就立即入栈,因为他可能是多位数
                    * 因此我们需要定义一个变量 字符串,用于拼接
                    * 处理多位数
                    * */
                    keepNum+=ch;
                    //如果ch已经是expression的最后一位数,就直接入栈
                    if(index==expression.length()-1){
                        numStack.push(Integer.parseInt(keepNum));
                    }else {
                        //判断下一个字符是不是数字,如果是数字,就继续扫描,如果是运算符,则入栈
                        //注意看后一位,不是index++
                        if(operStack.isOper(expression.substring(index+1,index+2).charAt(0))){
                            //如果后一位是运算符,则入栈keepNum="1"或者“123”
                            numStack.push(Integer.parseInt(keepNum));
                            //keepNum清空,非常重要
                            keepNum="";
                        }
                    }
                }
                //让index+1,并判断是否扫描到expression最后
                index++;
                if(index>=expression.length()){
                    break;
                }
            }
            //当表达式扫描完毕,就顺序的从数栈和符号栈中pop出相应的数和符号,并运行
            while (true){
                //如果符号栈为空,则计算到最后的结果,数栈中只有一个数字,即为结果
                if(operStack.isEmpty()){
                    break;
                }
                num1=numStack.pop();
                num2=numStack.pop();
                oper=operStack.pop();
                res=numStack.cal(num1,num2,oper);
                numStack.push(res);//将结果入栈
            }
            //将数栈的最后一个数,pop出,就是结果
            int res2=numStack.pop();
            System.out.println(expression+"="+res2);
            
        }
    }
    //定义一个ArrayStack2表示栈
    class ArrayStack2{
        private int maxSize;//栈的大小
        private int[] stack;//数组,数组模拟栈,数据放在该数组中
        private int top=-1;//top表示栈顶,初始化为-1
        //构造器
        public ArrayStack2(int maxSize) {
            this.maxSize = maxSize;
            stack=new int[this.maxSize];
        }
        //增加一个方法,可以返回当前栈顶的值,但是不是真正的pop
        public int peek(){
            return stack[top];
        }
        //栈满
        public boolean isFull(){
            return top==maxSize-1;
        }
        //栈空
        public boolean isEmpty(){
            return top==-1;
        }
        //入栈-push
        public void push(int value){
            //先判断是否栈满
            if(isFull()){
                System.out.println("栈满");
                return;
            }
            top++;
            stack[top]=value;
        }
        //出栈-pop,将栈顶的数据返回
        public int pop(){
            //先判断栈是否为空
            if(isEmpty()){
                throw new RuntimeException("栈空,没有数据!!");
            }
            int value=stack[top];
            top--;
            return value;
        }
        //显示栈的情况,遍历栈,需要从栈顶开始显示数据
        public void list(){
            //先判断栈是否为空
            if(isEmpty()){
                System.out.println("栈空,没有数据!!");
                return;
            }
            //需要从栈顶开始显示数据
            for (int i=top;i>=0;i--){
                System.out.println(stack[i]);
            }
        }
        //返回运算符的优先级,优先级是程序员来确定,优先级使用数字表示
        //数字越大,则优先级就越高
        public int priority(int oper){
            if(oper=='*'||oper=='/'){
                return 1;
            }else if(oper=='+'||oper=='-'){
                return 0;
            }else {
                return -1;//假定目前的表达式只有+,-,*,/
            }
        }
        //判断是不是一个运算符
        public boolean isOper(char val){
            return  val=='+'||val=='-'||val=='*'||val=='/';
        }
        //计算方法
        public int cal(int num1,int num2,int oper){
            int res=0;//res用于存放计算的结果
            switch (oper){
                case '+':
                    res=num1+num2;
                    break;
                case '-':
                    res=num2-num1;//注意顺序
                    break;
                case '*':
                    res=num2*num1;
                    break;
                case '、':
                    res=num2/num1;
                    break;
                default:
                    break;
            }
            return res;
        }
    }

    运行结果:

     根据上诉思路最终成功实现计算功能。

  • 相关阅读:
    吴恩达深度学习第4课第3周编程作业 + PIL + Python3 + Anaconda环境 + Ubuntu + 导入PIL报错的解决
    Ubuntu 14.04 16.04 17.10 + Win10 双系统安装记录 + 分区大小选择办法
    NVIDIA Titan Xp Star Wars Collector's Edition显卡深度学习工作站 + Ubuntu17.10 + Tensorflow-gpu + Anaconda3 + Python 3.6 设置
    request.getParameter() request.getAttribute()
    Gson 数据解析
    级联查询
    mybatis 从入门到精通 读书笔记
    springboot 随笔
    springboot 跨域
    select
  • 原文地址:https://www.cnblogs.com/ftx3q/p/15713211.html
Copyright © 2020-2023  润新知