//使用栈完成计算一个表达式的结果 10*9-3+5
- 计算思路: 有两个栈 一个存放数字 一个存放运算符
- 1、将表达式字符串转换成字符数组 遍历字符数组
- 2、如果是数字 直接存放到数字栈
- 3、如果是符号 ;分为两种情况
(1) 如果符号栈为空 直接将符号入栈
(2)如果符号栈不为空
a、当运算符和栈内的运算符进行比较 如果当前的运算符的优先级低于或者等于栈中的运算符,就需要从数栈中pop出两个数,再从符号栈中pop出一个符号,进行运算, 将得到的结果push进数栈,然后将当前的符号push符号栈;
b、如果当前的操作符的优先级大于栈中的运算符 就直接入符号栈 - 4、当表达式扫描完毕 就顺序从数栈和符号栈pop出相应的数和符号 并运行
- 5、最后数栈中只有一个数字 即为表达式的结果
public class UseStack {
public static void main(String[] args) {
//测试
System.out.println(Calculate("10*9-3+5"));
}
public static int Calculate(String str) {
ArrayStack2 numStack=new ArrayStack2(10);//数栈
ArrayStack2 operStack=new ArrayStack2(10);//运算符栈
int index=0;//遍历字符串所用的下标
int num1=0;//弹出的第一个数
int num2=0;//弹出的第二个数
char oper=0;//弹出的运算符
int res=0;//弹出的运算符和结果
char c=0;//从字符串中读取的字符
char[] expression=str.toCharArray();
String keepnum="";
//扫描expression
while(true) {
c=expression[index];
//判断 c 是什么 然后进行相应的处理
if(operStack.isoper(c)) { //c是运算符
if(!operStack.isEmpty()) { //符号栈不为空 分两种情况
//当运算符和栈内的运算符进行比较 如果当前的运算符的优先级低于或者等于栈中的运算符,就需要从数栈中pop出两个数,再从符号栈中pop出一个符号,进行运算,
if(operStack.priority(c)<=operStack.priority((char) operStack.peek())){
num1=numStack.pop();
num2=numStack.pop();
oper=(char) operStack.pop();
res=numStack.calculate(num1, num2, oper);
numStack.push(res);
//操作结束之后 要记得把遍历的操作符存放到符号栈中
operStack.push(c);
}else {//如果当前的操作符的优先级大于栈中的运算符 就直接入符号栈
operStack.push(c);
}
}else { //符号栈 为空 直接将符号入栈
operStack.push(c);
}
}
else { //如果是数字 直接入数栈
//numStack.push(c-48);// "1+3" ---字符1 对应的值是49
//分析思路
//1、当处理多位数时,不能是发现一个数就立即入栈 因为它可能是多位数
//2、在处理数字时需要向expression的表达式
//如果数字是expression中的最后一个数 直接入数栈
keepnum+=c;
if(index==expression.length-1) {
numStack.push(Integer.parseInt(keepnum));
} else {
//如果下一位是运算符 就直接把keepnum push进入栈内 ;如果不是保留keepnum 继续遍历下一个字符
if(operStack.isoper(expression[index+1])) {
numStack.push(Integer.parseInt(keepnum));
//注意!!!每次keepnum用完之后 记得将其恢复为空
keepnum="";
}
}
}
index++;
if(index>=expression.length){ //遍历结束
break;
}
}
while(!operStack.isEmpty()) { //当符号栈中的符号全部弹出的时候 计算完全结束 取出数栈中的第一个数即为运算的结果
num1=numStack.pop();
num2=numStack.pop();
oper=(char) operStack.pop();
res=numStack.calculate(num1, num2, oper);
//及得把res存放到numStack中
numStack.push(res);
}
return res;
}
}
//数组模拟栈
class ArrayStack2 {
private int maxsize;
private int[] array;
private int top=-1;
public ArrayStack2(int maxsize) {
this.maxsize=maxsize; //这里注意将maxsize传入this.maxsize
array=new int[this.maxsize];
}
//是否栈满
public boolean isFull() {
return top==maxsize-1;
}
//是否栈空
public boolean isEmpty() {
return top==-1;
}
//入栈操作
public void push(int value) {
//判断是否栈满
if(top==maxsize-1) {
System.out.println("栈已满");
}else {
top++;
array[top]=value;
}
}
//出栈操作
public int pop() {
//判断是否栈空
if(top==-1) {
throw new RuntimeException("栈空,没有数据");
}else {
int value=array[top];
top--;
return value;
}
}
//弹出栈顶元素
public int peek() {
return array[top];
}
//遍历栈 从栈顶到栈底部
public void read() {
if(top!=-1) {
for(int i=top;i>=0;i--) {
System.out.println(i+"---"+array[i]);
}
}
}
//返回运算符的优先级 优先级是有程序员设定 优先级用数字表示
//数字越大优先级越高
public int priority(char oper) {
if(oper=='*'||oper=='/') {
return 1;
}
if(oper=='+'||oper=='-') {
return 0;
}else {
return -1;
}
}
//判断是不是一个运算符
public boolean isoper(char c) {
if(c=='+'||c=='-'||c=='*'||c=='/') {
return true;
}else
return false;
}
//计算
public int calculate(int num1,int num2,char oper) {
int res=0;
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;
}
}