韩顺平老师数据结构与算法的栈实现综合计算器的课后练习: 添加小括号
写出来记录一下,挺开心的...花了我一个小时多...可能写的一般般..大佬可以指点一下
public class Calculator {
public static void main(String[] args) {
//根据前面韩老师的思路完成表达式的一个运算
String expression = "30/(5+5)*20";
//先创建俩个栈, 数栈 符号栈
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
String keepNum = "";// 用于拼接多位数
//开始while循环的扫描 expression
while (true){
//依次得到 expression 的每一个字符
ch = expression.substring(index, index+1).charAt(0);
//判断 ch是什么, 然后做相应的处理
if (operStack.isOper(ch)){ //如果是运算符
//判断当前符号栈是否为空
if (!operStack.isEmpty()){
// //如果符号栈有操作符, 就进行比较, 如果当前操作符优先级小于或等于栈中的操作符, 就需要从
// //数栈中pop出俩个数, 在从符号栈中pop出一个符号, 进行运算, 将得到结果, 入数栈, 然后将当前
// //的操作符入符号栈
if (ch == '('){
operStack.push(ch);
}else if (ch == ')'){
num1 = numStack.pop();
num2 = numStack.pop();
oper = operStack.pop();
res = numStack.cal(num1,num2,oper);
numStack.push(res);
operStack.pop();
}else 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 {
//如果为空直接入栈
operStack.push(ch);
}
} else { //如果是数, 则直接入数栈
// numStack.push(ch - 48);
//当处理多为数时,不能发现是一个数就立即入数栈, 因为他可能是多位数
//在处理数时需要向expression表达式的index 后在看一位, 如果是数就继续扫描,如果是符号就才入栈
//因此需要定义一个变量字符串变量, 用于拼接
keepNum += ch;
//如果ch已经是expression最后一位就直接入栈
if (index == expression.length()-1){
numStack.push(Integer.parseInt(keepNum));
}else {
//判断下一个字符是否数字, 是数字则继续扫描, 否则入栈
if (operStack.isOper(expression.substring(index+1,index+2).charAt(0))){
//如果后一位是运算符, 入栈
numStack.push(Integer.parseInt(keepNum));
keepNum = ""; //!!!清空
}
}
}
//让index + 1 并判断是否扫描到expression 最后
index++;
if (index >= expression.length()){
break;
}
}
// 当表达式扫描完毕, 就顺序的从 数栈和符号栈中pop 出相应的数和符号, 并运行
while (true){
//如果符号栈为空, 则计算到最后的结果, 数栈中只有一个数字[结果]
if (operStack.isEmpty()){
break;
}
num1 = numStack.pop();
num2 = numStack.pop();
oper = operStack.pop();
res = numStack.cal(num1,num2,oper);
numStack.push(res); //入栈
}
//将数栈的最后数, pop 出就是结果
int res2 = numStack.pop();
System.out.printf("表达式 %s = %d",expression,res2);
}
}
//先创建一个栈, 直接使用前面创建好的, 需要扩展功能
class ArrayStack2{
private int maxSize; //栈的大小
private int[] stack; //数组, 数组模拟栈, 数据就放在数组
private int top = -1; //top表示栈顶, 初始化为-1
//构造器
public ArrayStack2(int maxSize){
this.maxSize = maxSize;
stack = new int[this.maxSize];
}
//增加一个方法可以返回当前栈顶的值, 但是不出栈
public int peek(){
return stack[top];
}
//栈满
public boolean isFull(){
return top == maxSize - 1;
}
//栈空
public boolean isEmpty(){
return top == -1;
}
//入栈-push
public void push(int value){
//先判断栈是否满
if(isFull()){
System.out.println("栈满");
return;
}
stack[++top] = value;
}
//出栈-pop 将栈顶的数据返回
public int pop(){
//先判断栈是否空
if (isEmpty()){
//抛出异常
throw new RuntimeException("栈空");
}
return stack[top--];
}
//显示[遍历]栈, 遍历时,需要从栈顶开始显示数据
public void list(){
if(isEmpty()){
System.out.println("栈空");
return;
}
for (int i = top; i >= 0; i-- ){
System.out.printf("stack[%d]: %d\n", i, stack[i]);
}
}
//返回运算符的优先级, 优先级是程序员来确定, 优先级使用数字表示
//数字越大, 则优先级就越高
public int priority(int oper){
if (oper == '*' || oper == '/'){
return 2;
}else if (oper == '+' || oper == '-'){
return 1;
}else if (oper == '(' || oper == ')'){
return 0;
}else {
return -1; //假定目前的表达式只有 + - * /
}
}
//判断是不是一个运算符
public boolean isOper(char val){
return val == '+' || val == '-' || val == '*' || val == '/' || val == '(' || val == ')';
}
//计算方法
public 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;
default:
break;
}
return res;
}
}