栈的实例----表达式计算(不带括号)
1)使用两个栈
1.数栈(numberStack):存放数
2.符号栈(operStack):存放运算符
2)思路分析
1.通过一个索引index值,遍历表达式
2.如果索引发现一个数字,就入数栈
3.如果索引发现一个符号,就有如下情况
3.1如果发现当前符号栈为空,就直接入栈
3.2如果符号栈有操作符,就进行比较,如果当前符号的优先级小于或者等于栈中操作符,就需要从数栈中pop出两个数,再从符号栈中pop出一个符号,进行运算,得到结果再入数栈,然后将当前运算符入符号栈。**如果当前符号的优先级大于栈中操作符,**直接入栈。
4.当表达式扫描完毕,就顺序从数栈和符号栈进行pop出相应的数和符号
5.最后数栈只有一个数字,就是运算结果
3)代码实现
package com.cwnu.stack;
public class CalculatorStack {
public static void main(String[] args) {
//输入表达式
String expression = " 2 / 1 + 3 * 3 - 2";
expression = expression.replaceAll(" ", "");//将表达式的空格去除
char[] expressArray = expression.toCharArray();//将表达式转变为数组
//创建两个栈,数栈还有符号栈
ArrayStack2 numberStack = new ArrayStack2(10);//数栈
ArrayStack2 operStack = new ArrayStack2(10);//符号栈
int index = 0;
String keepNum = "";
for (char e : expressArray) {
//判断是否为运算符
if (isOper(e)) {
//判断符号栈是否为空,如果为空,直接入栈
if (operStack.isEmpty()) {
operStack.push(e);
} else {
//判断当前符号和栈顶的符号的优先级
if (priority(e) > priority(operStack.showTop())) {
//如果当前符号大于栈顶元素符号就直接入栈
operStack.push(e);
} else {
//如果当前符号的优先级小于或者等于栈中操作符,就需要从数栈中pop出两个数,
// 再从符号栈中pop出一个符号,进行运算,得到结果再入数栈,然后将当前运算符入符号栈
int num1 = numberStack.pop();
int num2 = numberStack.pop();
int oper = operStack.pop();
//运算,将结果进行入数栈
numberStack.push(cal(num1, num2, oper));
//当前运算符入栈
operStack.push(e);
}
}
} else {
keepNum += e;
if (index == expressArray.length - 1){
//判断是否为最后一位数
numberStack.push(Integer.parseInt(keepNum));
}else{
if (isOper(expressArray[index + 1])){
//判断下一位是否为字符
numberStack.push(Integer.parseInt(keepNum));
keepNum = "";
}
}
}
index++;
}
int res;
while (true) {
if (numberStack.getTop() == 0) {
res = numberStack.pop();
break;
}
int num1 = numberStack.pop();
int num2 = numberStack.pop();
int oper = operStack.pop();
numberStack.push(cal(num1, num2, oper));
}
System.out.println("表达式计算结果为:" + res);
}
//返回运算符的优先级,优先级越高,返回的数字越大
public static int priority(int oper) {
if (oper == '*' || oper == '/') {
return 1;
} else if (oper == '+' || oper == '-') {
return 0;
} else {
return -1;
}
}
//判断是否为操作符
public static boolean isOper(char val) {
return val == '+' || val == '-' || val == '*' || val == '/';
}
//计算的方法
public static 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 = num1 * num2;
break;
case '/':
res = num2 / num1;
break;
}
return res;
}
}
/*
* 创建一个栈
* 需要扩展功能
* */
class ArrayStack2 {
private int maxSize;//栈的最大容量
private int[] stack;
private int top = -1;//表示栈顶
public int getTop() {
return top;
}
//构造器
public ArrayStack2(int maxSize) {
this.maxSize = maxSize;
stack = new int[this.maxSize];
}
//栈满
public boolean isFull() {
return top == maxSize - 1;
}
//栈空
public boolean isEmpty() {
return top == -1;
}
//入栈
public void push(int value) {
if (isFull()) {
System.out.println("栈已满,无法加入");
return;
}
top++;
stack[top] = value;
}
//出栈
public int pop() {
if (isEmpty()) {
throw new RuntimeException("栈空,无法取得数据");
}
int value = stack[top];
top--;
return value;
}
//显示栈顶元素
public int showTop() {
return stack[top];
}
//显示栈的情况,遍历时需要从栈顶开始显示
public void showList() {
if (isEmpty()) {
System.out.println("栈空");
return;
}
for (int i = top; i >= 0; i--) {
System.out.printf("stack[%d] = %d\n", i, stack[i]);
}
}
}