栈实现计算器
基本思路:
创建两个栈,一个用来装数字一个用来装符号
1,遍历表达式
2,数字入数栈
3,如果是符号则分情况
如果优先级较低则直接对栈顶两个数运算,运算结果再入栈
若优先级较高或是符号栈为空将符号入栈,等待后续
4,表达式全部入栈后,依次从栈中出栈数字和符号进行运算,直到剩下最后一个结果.
完整流程如下
以3*2+3为例
3入栈,2入栈,*入栈(符号栈为空)
遍历到’+‘,’+‘优先级低于’*’
所以弹出3和2,弹出* ,计算3*2,将运算结果6入栈
最后弹出6和3计算6+3得出结果9
最后是代码
基本属性
double[] number = new double[20];
int topn = -1;
char[] cal = new char[20];
int topc = -1;
入数字栈
public void pushn(double input) {
topn++;
number[topn] = input;
System.out.printf("数字入栈%.2f\n", number[topn]);
}
入符号栈
public void pushc(char input) {
topc++;
cal[topc] = input;
System.out.printf("符号入栈%c\n", cal[topc]);
}
出数字栈
public double popn() {
double op = number[topn];
System.out.printf("数字出栈%.2f\n", op);
topn--;
return op;
}
出符号栈
public char popc() {
char op = cal[topc];
System.out.printf("符号出栈%c\n", cal[topc]);
topc--;
return op;
}
接下来是重头戏
主要计算方法
public void calculate(String input) {
for (int i = 0; i < input.length(); i++) {
char in = input.charAt(i);
switch (in) {
case '*':
if ((topn>=1&&topc!=-1)&&(cal[topc] == '*' || cal[topc] == '/')) {//判断优先级和符号栈是否为空
if(cal[topc] == '*'){
double temp = popn() * popn();//弹出两个数并计算
System.out.println(temp + "运算结果入栈");
popc();//符号出栈
pushn(temp);//结果入栈
}else{
double temp = 1/popn() * popn();
System.out.println(temp + "运算结果入栈");
popc();
pushn(temp);
}
} else {
pushc('*');
}
break;
case '/':
if ((topn>=1&&topc!=-1)&&(cal[topc] == '*' || cal[topc] == '/')) {//判断优先级和符号栈是否为空
if(cal[topc] == '*'){
double temp = popn() * popn();
System.out.println(temp + "运算结果入栈");
popc();
pushn(temp);
}else{
double temp = 1/popn() * popn();
System.out.println(temp + "运算结果入栈");
popc();
pushn(temp);
}
} else {
pushc('/');
}
break;
case '+':
if (topn>=1&&topc!=-1) {//判断符号栈是否为空
if(cal[topc] == '*'){
double temp = popn() * popn();
System.out.println(temp + "运算结果入栈");
popc();
pushc('+');
pushn(temp);
}else if(cal[topc] == '/'){
double temp = 1/popn() * popn();
System.out.println(temp + "运算结果入栈");
popc();
pushc('+');
pushn(temp);
}else if(cal[topc] == '+'){
double temp = popn() + popn();
System.out.println(temp + "运算结果入栈");
popc();
pushc('+');
pushn(temp);
}else{
double temp = -popn() + popn();
System.out.println(temp + "运算结果入栈");
popc();
pushc('+');
pushn(temp);
}
}else{
pushc('+');
}
break;
case '-':
if (topn>=1&&topc!=-1) {//判断符号栈是否为空
if(cal[topc] == '*'){
double temp = popn() * popn();
System.out.println(temp + "运算结果入栈");
popc();
pushc('-');
pushn(temp);
}else if(cal[topc] == '/'){
double temp = 1/popn() * popn();
System.out.println(temp + "运算结果入栈");
popc();
pushc('-');
pushn(temp);
}else if(cal[topc] == '+'){
double temp = popn() + popn();
System.out.println(temp + "运算结果入栈");
popc();
pushc('-');
pushn(temp);
}else{
double temp = -popn() + popn();
System.out.println(temp + "运算结果入栈");
popc();
pushc('-');
pushn(temp);
}
}else{
pushc('-');
}
break;
default:
pushn(in-48);
}
}
System.out.println("字符串遍历完成");
while (topn != 0&&topc!= -1) {//将第一轮处理后的结果进行运算直到剩下最终结果
switch (cal[topc]) {
case '+':
double temp = popn() + popn();
System.out.println(temp + "运算结果入栈");
popc();
pushn(temp);
break;
case '-':
temp = -popn() + popn();
System.out.println(temp + "运算结果入栈");
pushn(temp);
popc();
break;
case '*':
temp = popn() * popn();
System.out.println(temp + "运算结果入栈");
pushn(temp);
popc();
break;
case '/':
temp = 1/popn() * popn();
System.out.println(temp + "运算结果入栈");
pushn(temp);
popc();
break;
}
}
System.out.println("最后结果为"+number[topn]);
}
总结:
这里主要是不带括号的计算器
带括号的基本思路大体类似,即将左括号设置为最高优先级,直接入栈,右括号设置为最低优先级,遍历到直接弹出数据进行运算.
计算器实现思路较为巧妙,主要依靠对栈数据结构的理解,理解了就很难忘记.