栈实现综合计算器
栈实现综合计算器
输入一个表达式并计算结果。例:3+2*6-2=13
思路分析
-
定义一个index指针来遍历表达式
-
创建一个数栈、一个符号栈 ;当遍历到的是数字时直接入数栈。
-
当遍历到符号栈时,若符号栈为空,则直接入符号栈;若遍历到的符号小于等于栈中符号时,则从数栈中取出两个数,符号栈中取出一个符号进行运算,将运算后的结果入数栈,最后将遍历到的当前符号入符号栈。
-
当表达式遍历完毕时,顺序从数栈和符号栈中依次取出
-
当数栈中只有一个数字时,就是表达式的结果
代码实现
package 栈;
public class 栈实现计算器功能 {
public static void main(String[] args) {
//要计算的表达式
String expression = "7*2*2-5+1-5+3-4";
//创建一个遍历指针,一个数栈,一个符号栈
int index = 0;
Stack0 numstack = new Stack0(10);
Stack0 operastack = new Stack0(10);
//定义需要的变量
char ch = ' ';//将扫描到的字符保存到ch中
int num1 = 0;//数字栈中取出的第一个数
int num2 = 0;//数字栈中取出的第二个数
int opera = 0;//符号栈中取出的符号
int res = 0;//运算结果
String keepnum = " ";//用于拼接多位数
//利用while循环扫描表达式
while (true) {
//依次得到表达式的每一个字符
ch = expression.substring(index, index + 1).charAt(0);
//判断ch是什么做相应的处理
if (operastack.isopera(ch)) {//如果是运算符
//判断符号栈是否为空
if (!operastack.isEmpty()) {
if (operastack.priority(ch) <= operastack.priority(operastack.peek())) {//若遍历到的符号小于等于栈中符号时
// 则从数栈中取出两个数,符号中取出一个符号
num1 = numstack.pop();
num2 = numstack.pop();
opera = operastack.pop();
//进行运算,将运算后的结果入数栈,
res = numstack.cal(num1, num2, opera);
numstack.push(res);
//当前符号入符号栈。
operastack.push(ch);
} else {//如果为空直接入符号栈
operastack.push(ch);
}
} else {//如果是数字,直接入数字栈
//1、在入栈前需要判断是否为多位数
//2、在处理数时,需要向表达式的后面再看一位,如果是数进行扫描,当为符号时入栈
//3、定义一个字符串变量,用于拼接。
keepnum += ch;//处理多位数
//如果ch已经是表达式最后一位,直接入栈
if (index == (expression.length() - 1)) {
numstack.push(Integer.parseInt(keepnum));
} else {//判断下一位是否为数字,如果是数字则继续扫描,如果是符号则入栈
if (numstack.isopera(expression.substring(index + 1, index + 2).charAt(0))) {
numstack.push(Integer.parseInt(keepnum));
//记得入栈以后一定要清空 keepnum清空,不然一直在后面拼接
keepnum = " ";
}
}
}
index++;
if (index >= expression.length() - 1) {
break;
}
}
//当表达式扫描完成,顺序从数栈和符号栈中pop出相应的数和符号,并运行。
while (true) {
//如果符号栈为空,则计算到最后的结果,数栈中只有一个数字【结果】
if (operastack.isEmpty()) {
break;
}
num1 = numstack.pop();
num2 = numstack.pop();
opera = operastack.pop();
res = numstack.cal(num1, num2, opera);
numstack.push(res);//入栈
}
//将数栈中的最后数,pop出,就是结果
int res2 = numstack.pop();
System.out.println(res2);
}
}
}
class Stack0 {
public int[] stack;
public int maxsize;
public int top = -1;
//构造方法
public Stack0() {
}
public Stack0(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 num) {
if (isfull()) {
System.out.println("栈满");
return;
}
top++;
stack[top] = num;
}
//出栈
public int pop() {
if (isEmpty()) {
throw new RuntimeException("栈空,无数据");
}
int value = stack[top];
top--;
return value;
}
//显示栈
public void show() {
if (isEmpty()) {
System.out.println("栈空");
return;
}
//需要从栈顶开始显示数据
for (int i = top; i >= 0; i--) {
System.out.println(stack[i]);
}
}
//返回栈顶值
public int peek() {
return stack[top];
}
//判断是否为运算符
public boolean isopera(char ch) {
return ch == '+' || ch == '-' || ch == '*' || ch == '/';
}
//定义符号优先级
public int priority(int oper) {
if (oper == '*' || oper == '/') {
return 1;
} else if (oper == '+' || oper == '-') {
return 0;
} else {
return -1;
}
}
//定义运算法方法
public int cal(int num1, int num2, int opera) {
int res = 0;//用于存放计算的结果
switch (opera) {
case '+':
res = num1 + num2;
break;
case '-':
res = num2 - num1;
break;//注意顺序
case '*':
res = num1 * num2;
break;
case '/':
res = num2 / num1;
break;
default:
break;
}
return res;
}
}
代码分析
变量定义
定义表达式,字符串类型
定义数字栈,符号栈,遍历指针
定义辅助变量,数字栈取出的数字num1,num2;符号栈取出运算符opera
定义栈类
数组模拟栈:成员变量要有 maxsize表示栈的大小,数组,top栈顶指针;
集合模拟栈:则不用考虑数组的大小,因为集合可以自动扩容。
定义栈的成员方法
是否为空
是否为满
出栈
入栈
栈的显示(从栈顶开始遍历)
返回栈顶元素
是否为运算符
运算符优先级
计算方法
主程序
将字符串表达式转换为每个字符
ch = expression.substring(index, index + 1).charAt(0);
判断每个字符是否为运算符(符号栈不为空,优先级小于等于栈中优先级,数栈中取数,符号栈中取符号运算,计算结果入数栈,遍历的当前符号入符号栈;否则直接入符号栈)
若符号为数字,需要判断是否为多位数,定义字符串变量keepnum+=ch用来拼接。若为最后一个数字直接入数栈(需要将字符串表达式转换为十进制数),否则判断下一位是否为符号。
if (numstack.isopera(expression.substring(index + 1, index + 2).charAt(0))) {
numstack.push(Integer.parseInt(keepnum));
//记得入栈以后一定要清空 keepnum清空,不然一直在后面拼接
keepnum = " ";
}
这时候一个字符的判断已经结束,index++判断下一个字符。这样将表达式遍历以后,顺序从数栈,符号栈中取出;如果符号栈中不为空,则数栈中取数,符号栈中取符号,得到计算结果,存入数栈;若符号栈为空;则得到计算的结果。将结果pop出即可。

浙公网安备 33010602011771号