用棧實現了一個求簡單表達式值的算法。算法最後是一個同優先級的表達式,需要先入先出,這違背了棧先入後出的性質。最終使用遞歸解決這個問題,先把一個操作數和一個操作法pop出來,然後遞歸的pop,直到操作法棧爲空,遞歸結束。
package cn.agan.mystack;
import java.util.Scanner;
/**
* 表達式計算:
* 用棧來計算一個表達式的值 7 * 2 * 2 - 5 +1 + 4 / 2 * 3 = 30
* 兩個棧,一個用來壓數字,一個壓入運算符,如果棧爲空就直接將運算符壓人棧中;如果要壓入的運算符優先級大於棧頂的運算符
* 則彈出兩個數字,算完再將結果押入數字棧,棧頂運算符彈出,目的運算符繼續與下一個棧頂運算符比較。。。
* 在壓完運算符後,依次彈出運算符,每彈出一個運算符,就彈出兩個數字進行運算,結果壓入數字棧。。。直至運算符彈出完畢。
*/
public class ExpressionCalculate {
public static void main(String[] args) {
ArrayStack2 digitalStack = new ArrayStack2(1024);
ArrayStack2 operatorStack = new ArrayStack2(1024);
boolean loop = true;
Scanner scanner = new Scanner(System.in);
String line;
int index = 0, num1 = 0, num2 = 0, res = 0, oper = 0;
char ch = ' ';
while ( loop ) {
index = 0;
System.out.println("輸入一個表達式,給你算出表達式的值。暫時只支持+-*/ 和單位數,12+1不支持");
System.out.println("輸入exit退出程序");
line = scanner.nextLine().trim();
switch (line) {
case "exit":
loop = false;
break;
default:
while (true) {
ch = line.substring(index, index+1).charAt(0);
if (operatorStack.isOper(ch)) { //運算符
if (!operatorStack.isEmpty()) {
if (operatorStack.priority(ch) <= operatorStack.priority(operatorStack.peak())) {
num1 = digitalStack.pop();
num2 = digitalStack.pop();
oper = operatorStack.pop();
res = digitalStack.cal(num2, num1, oper);
digitalStack.push(res);
operatorStack.push(ch);
} else {
operatorStack.push(ch);
}
} else { //直接入棧
operatorStack.push(ch);
}
} else { //數字,直接入數值棧
digitalStack.push(ch - 48);
}
index++;
if (index >= line.length()) {
break;
}
}
// while (!operatorStack.isEmpty()) {
// num1 = digitalStack.pop();
// num2 = digitalStack.pop();
// oper = operatorStack.pop();
// res = digitalStack.cal(num2, num1, oper);
// digitalStack.push(res);
// }
res = calStack(digitalStack, operatorStack);
System.out.println("表達式結果爲:"+ res);
break;
}
}
}
//按照先入先出的順序算出棧裏面的數據
public static int calStack(ArrayStack2 digitalStack, ArrayStack2 operatorStack) {
if (operatorStack.isEmpty()) {
return digitalStack.pop();
}
int num1 = digitalStack.pop();
int oper = operatorStack.pop();
int res = 0;
res = digitalStack.cal(calStack(digitalStack, operatorStack), num1, oper);
return res;
}
}
class ArrayStack2 {
private int maxSize ; //棧的大小
private int[] stack; //存儲數據的數組
private int top = -1; //棧頂,初始化爲-1
public ArrayStack2( 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 value) {
if (isFull()) {
System.out.println("棧已經滿了");
return;
}
stack[++top] = value;
}
//返回運算符的優先級,預定數字越大,優先級越高
public int priority(int opr) {
if (opr == '*' || opr == '/') {
return 4;
} else if (opr == '+' || opr == '-') {
return 3;
} else {
return -1; //暫時只支持+-*/
}
}
//判斷字符是否是一個運算符
public boolean isOper(char val) {
return val == '+' || val == '-' || val == '*' || val == '/';
}
//計算方法
public int cal(int num1, int num2, int oper) {
int res = 0;
switch (oper) {
case '+':
res = num1 + num2;
break;
case '-':
res = num1 - num2;
break;
case '*':
res = num1 * num2;
break;
case '/':
res = num1 / num2;
break;
default:
System.out.println("獲取尚未支持的運算符");
return 0;
}
return res;
}
//查看棧頂元素
public int peak() {
if (isEmpty()) {
throw new RuntimeException("棧空");
}
return stack[top];
}
public int pop() {
if (isEmpty()) {
throw new RuntimeException("棧空");
}
return stack[top--];
}
//遍歷棧,從棧頂開始顯示
public void show() {
if (isEmpty()) {
System.out.println("棧空,沒有數據");
return;
}
for (int i = top; i >= 0; i--) {
System.out.printf("%d\t", stack[i]);
}
}
}