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

使用栈实现综合计算器

请输入一个表达式

例:[3+2*6-2] ,直接点击计算,就可以计算出值。

思路分析(图解)

 

 代码如下

【1.先实现一位数的运算,2.扩展到多位数的运算】

  1 package com.jyj.stack;
  2 
  3 public class Calculator {
  4     public static void main(String[] args) {
  5         String expression = "30+2*6-2";
  6         //创建两个栈,数栈和符号栈
  7         ArrayStack2 numStack = new ArrayStack2(10);
  8         ArrayStack2 operStack = new ArrayStack2(10);
  9         //定义需要的相关变量
 10         int index = 0; //用于扫描
 11         int num1 = 0;
 12         int num2 = 0;
 13         int oper = 0;
 14         int res = 0;
 15         char ch = ' '; //将每次扫描得到char保存到ch
 16         String keepNum = "";//用于拼接 多位数
 17         //开始while循环的扫描expression
 18         while(true) {
 19             //依次得到expression的每一个字符
 20             ch = expression.substring(index, index+1).charAt(0);
 21             //判断ch是什么,然后做相应的处理
 22             if(operStack.isOper(ch)){//如果是运算符
 23                 //判断当前的符号栈是否为空
 24                 if(!operStack.isEmpty()) {
 25                     //如果符号栈有操作符,进行比较,如果当前操作符的优先级小于等于栈中的操作符,就需要从数栈中pop出两个数,
 26                     //在从符号栈中pop出一个符号,进行计算,将得到结果,入数栈,然后将当前的操作符入符号栈
 27                     if(operStack.priority(ch) <= operStack.priority(operStack.peek())) {
 28                         num1 = numStack.pop();
 29                         num2 = numStack.pop();
 30                         oper = operStack.pop();
 31                         res = numStack.cal(num1, num2, oper);
 32                         //把运算的结果入数栈
 33                         numStack.push(res);
 34                         //然后将当前的操作符入符号栈
 35                         operStack.push(ch);
 36                     } else {
 37                         //如果当前的操作符的优先级大于栈中的操作符,就直接入符号栈。
 38                         operStack.push(ch);
 39                     }
 40                 }else {
 41                     //如果为空,就直接入符号栈
 42                     operStack.push(ch);
 43                 }
 44             }else{
 45                 //如果是数字,直接入数栈
 46                 //numStack.push(ch - 48);
 47                 //思路:
 48                 //1.当处理多位数时,不能发现是一个数,就立刻入栈,因为可能是多位数
 49                 //2.在处理数时,需要向expression的表达式的index后再看一位,如果是数,继续扫描,如果是符号,才入栈
 50                 //3.因此需要定义字符串keepNum,用于拼接 多位数
 51                 
 52                 //处理多位数
 53                 keepNum += ch;
 54                 
 55                 //如果ch已经是expression的最后一位,直接入栈
 56                 if(index == expression.length() - 1) {
 57                     numStack.push(Integer.parseInt(keepNum));
 58                 }else{
 59                     //判断下一个符号是不是数字,如果是数字,就继续扫描,如果是运算符,则入栈
 60                     //注意是看后一位,不是index++
 61                     if(operStack.isOper(expression.substring(index+1, index+2).charAt(0))){
 62                         numStack.push(Integer.parseInt(keepNum));
 63                         //注意:keepNum要清空
 64                         keepNum = "";
 65                     }
 66                 }
 67             }
 68             //让index + 1,并判断是否扫描到expression最后
 69             index++;
 70             if(index >= expression.length()) {
 71                 break;
 72             }
 73         }
 74         
 75         //当表达式扫描完毕,就顺序的从 数栈和符号栈中pop出相应的数和符号,并运行。
 76         while(true) {
 77             //如果符号栈为空,则计算到最后的结果,数栈中只有一个数字[结果]
 78             if(operStack.isEmpty()) {
 79                 break;
 80             }
 81             num1 = numStack.pop();
 82             num2 = numStack.pop();
 83             oper = operStack.pop();
 84             res = numStack.cal(num1, num2, oper);
 85             numStack.push(res);
 86         }
 87         System.out.printf("表达式 %s = %d\n",expression,numStack.pop());
 88     }
 89 }
 90 
 91 //定义ArrayStack2表示栈,需要扩展
 92 class ArrayStack2 {
 93     private int maxSize; //栈的大小
 94     private int top = -1; //栈顶,初始化为-1
 95     private int[] stack;
 96     
 97     public ArrayStack2(int size) {
 98         maxSize = size;
 99         stack = new int[maxSize];
100     }
101     
102     //增加一个方法,可以返回当前栈顶的值,但是不是真的的pop
103     public int peek() {
104         return stack[top];
105     }
106     
107     //栈满
108     public boolean isFull(){
109         return top == maxSize - 1;
110     }
111     //栈空
112     public boolean isEmpty(){
113         return top == -1;
114     }
115     //入栈-push
116     public void push(int value) {
117         if(isFull()){
118             System.out.println("栈满");
119             return;
120         }
121         top++;
122         stack[top] = value;
123     }
124     
125     //出栈-pop
126     public int pop(){
127         if(isEmpty()){
128             throw new RuntimeException("栈空");
129         }
130         int value = stack[top];
131         top--;
132         return value;
133     }
134     
135     //显示栈[遍历数据]
136     public void list(){
137         //判空
138         if(isEmpty()){
139             System.out.println("栈空,没有数据");
140         }
141         //遍历
142         for(int i = top;i >= 0;i--) {
143             System.out.printf("stack[%d] = %d\n",i,stack[i]);
144         }
145     }
146     //返回运算符的优先级,优先级是程序员来确定,优先级使用数字来表示
147     //数字越大,则优先级就越高
148     public int priority(int oper) {
149         if(oper == '*' || oper == '/') {
150             return 1;
151         }else if(oper == '+' || oper == '-') {
152             return 0;
153         }else {
154             return -1;//假定目前的表达式只有+,-,*,/
155         }
156     }
157     //判断是不是一个运算符
158     public boolean isOper(char val) {
159         return val == '+' || val == '-' || val == '*' || val == '/';
160     }
161     
162     //计算
163     public int cal(int num1,int num2,int oper) {
164         int res = 0;
165         switch(oper) {
166         case '+':
167             res = num1 + num2;
168             break;
169         case '-':
170             res = num2 - num1; //注意顺序
171             break;
172         case '*':
173             res = num1 * num2;
174             break;
175         case '/':
176             res = num2 / num1;
177             break;
178         }
179         return res;
180     }
181 }
View Code

以上。

 

posted @ 2020-02-26 21:59  指尖上的生产者  阅读(316)  评论(0编辑  收藏  举报