“携手创作,共同成长!开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第14天,点击查看活动详情”
案例:使用栈来实现综合计算机功能
思路分析:
1.使用栈完成表达式的计算
1) 通过index(一个索引值)来进行遍历表达式,
2) 设置两个栈,一个栈存放数据,一个栈存放运算符。若遍历的是数据就入数据栈中
3) 若遍历的是运算符就要分情况再入运算符栈中
a. 如果发现当前的符号栈为空,就直接入栈
b. 如果符号栈有操作符,就进行比较,如果当前的操作符的操作符的优先级小于或者等于栈中的操作符,数栈中pop出两个数,再在从符号栈中pop出一个运算符,进行运算,将得到的结果入数栈,然后将当前的操作符入符号栈,
c. 如果当前的操作符的操作符的优先级大于栈中的操作符,就直接入符号栈
4)当表达式扫描完毕后,就顺序的从数栈和符号栈中pop出相应的数和符号,并进行运算
5)最后数栈只有一个数字,就是表达式的结果
代码实现:
public static void main(String[] args) {
//开始完成表达式的运算
String experssion="3+2*6-2";
//创建两个栈,一个是数栈,一个是运算符栈
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=' '; //将每次扫描得到的char保存到ch中
//先开始while循环的扫描expression,直到没有运算符和数字结束
while (true){
//依次得到expression表达式中的每一个字符
//使用substring即使取出来了也是一个字符的字符串,还需要用charAt(0)将其变成字符
ch=experssion.substring(index,index+1).charAt(0);
//判断是字符还是数字
if (operstack.isOper(ch)){ //当字符为运算符时候
//判断字符是否为空
if (operstack.isNull()){ //如果为空会直接入栈
operstack.push(ch);
} else{ //如果符号栈有操作符,就进行比较,如果当前的操作符的操作符的优先级小
// 于或者等于栈中的操作符,数栈中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{ //若是数则会入栈,因为字符本身有ASCII码,所以要减去本身的值
numstack.push(ch-48);
}
//让index+1,并判断扫描experssion是否结束
index++;
//因为每次执行完就多了一,所以index的值会不断的增加,可以与表达式的长度进行比较
if (index>=experssion.length()){
break;
}
}
//当表达式扫描完毕后,就顺序的从数栈和符号栈中pop出相应的数和符号,并进行运算
while (true){
//如果符号栈为空,则数栈就会只有一个值,也就是结果
if (operstack.isNull())
{break; }
else{ num1=numstack.pop();
num2=numstack.pop();
oper=operstack.pop();
res=numstack.cal(num1,num2,oper);
numstack.push(res);
}
}
//将数栈最后的值出栈,就是结果
res=numstack.pop();
System.out.println("表达式的值为:"+experssion+'='+res);
}
}
//先创建一个栈,并在其中加入返回优先级的函数,优先级的大小是由自己设置的,
// 这里采用的是数字越大代表的优先级越高,再在其中加入数据运算的函数
class ArrayStack2{
private int Maxsize;
private int[] stack;
private int top=-1;
public ArrayStack2(int maxsize) {
Maxsize = maxsize;
stack=new int[maxsize];
}
//判断是否为满
public boolean isFull(){
return top==Maxsize-1;
}
//判断是否为空
public boolean isNull(){
return top==-1;
}
//入栈
public void push(int value){
//判断栈是否满了,满了无法再入栈
if(isFull()){
System.out.println("栈满了");
return;
}
top++;
stack[top]=value;
}
//出栈
public int pop(){
//判断栈是否为空,为空将无法出栈
if(isNull()){
//通过抛出程序运行异常来显示错误,该运行异常不需要捕获,同时运行异常抛出的同时会结束运行
throw new RuntimeException("栈空,没有数据");
}
int value=stack[top];
top--;
return value;
}
//显示栈的情况,需要从栈顶开始开始查询数据
public void list(){
if(isNull()){
System.out.println("栈空,没有数据");
}
for (int i = top; i >= 0; i--) {
System.out.printf("stack[%d]=%d\n",i,stack[i]);
}
}
//返回优先级的函数
//数字越大代表的优先级越高
public int priority(int oper){ //在java中字符本身代表一个数值,可以在数值和字符之间进行转换
if (oper=='*'||oper=='/'){
return 1;
} else if (oper=='+'||oper=='-'){
return 0;
} else return -1; //这里只有加减乘除的运算
}
//判断运算符
public boolean isOper(int oper){
return oper=='+'||oper=='-'||oper=='*'||oper=='/';
}
//数据运算的函数
public int cal(int num1,int num2,int oper){
int res=0; //用于存放计算结果
switch (oper){ //要注意数的顺序,因为栈是先进后出,所以本身后面的数应该放在前面
case '+':
res=num2+num1;break;
case '-':
res=num2-num1;break;
case '*':
res=num2*num1;break;
case '/':
res=num2/num1;break;
default:
break;
}
return res;
}
//可以返回当前的栈顶值,但是不会进行改变任何操作
public int peek(){
return stack[top];
}
}