用棧來實現簡易版中綴表達式的計算器
- 2020 年 2 月 20 日
- 筆記
1.什麼是棧 先進後出,元素的刪除和插入只能在同一端的一種線性表
2.棧的實現方式 數組和鏈表都可以,本次使用數組
3.什麼是中綴表達式 3+2-1*6+10
4.代碼:
/** * @author shengjk1 * @date 2020/2/13 */ public class Calcaulator { public static void main(String[] args) { // 中綴表達式 String expression = "5-1*6+2"; //創建兩個棧 數棧、符號棧 ArrayStack1 numStack = new ArrayStack1(10); ArrayStack1 operStack = new ArrayStack1(10); //用於遍歷 int index = 0; int num1, num2 = 0; int oper = 0; int res = 0; //每次掃描得到的char char ch = ' '; //用來拼接多位數 String keepNum = ""; while (true) { ch = expression.substring(index, index + 1).charAt(0); //判斷 ch 是什麼,然後做相應的處理 if (operStack.isOper(ch)) { //判斷當前的符號棧是否為空 if (!operStack.isEmpty()) { //如果當前的操作符的優先級小於等於棧中符號的優先級,就需要從數棧中 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 { //如果為空,直接入符號棧 operStack.push(ch); } } else { // 如果是數字則直接入數棧 // numStack.push(ch - 48); //看 index 後一位,如果是數則繼續進行掃描,如果不是則入棧 keepNum += ch; 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,並判斷是否掃描到 exoression 最後 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); } System.out.printf("表達式 %s = %d ", expression, numStack.pop()); } } class ArrayStack1 { private int maxSize; private int[] stack; private int top = -1; public ArrayStack1(int maxSize) { this.maxSize = maxSize; stack = new int[maxSize]; } // 棧滿 public boolean isFull() { return top == maxSize - 1; } //棧空 public boolean isEmpty() { return top == -1; } //查看當前棧頂的值 public int peek() { return stack[top]; } //入棧 public void push(int element) { if (isFull()) { System.out.println("棧滿"); return; } top++; stack[top] = element; } //出棧 public int pop() { if (isEmpty()) { throw new RuntimeException("stack is empty!"); } int temp = stack[top]; // stack[top]=null; 防止內存泄露 top--; return temp; } // public void list() { if (isEmpty()) { System.out.println("stack is empty"); return; } for (int i = top; i >= 0; i--) { System.out.printf("stack[%d]=%dn", i, stack[i]); } } //返回運算符的優先級 假設優先級越高返回的數字越大 public int priority(int oper) { if (oper == '*' || oper == '/') { return 1; } else if (oper == '+' || oper == '-') { return 0; } else { //假設目前表達式只有 + - * / return -1; } } /** * @param val * @return */ public boolean isOper(char val) { return val == '+' || val == '-' || val == '*' || val == '/'; } /** * 計算 * * @param num1 * @param num2 * @param oper * @return */ public int cal(int num1, int num2, int oper) { int res = 0; 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; } }
5.棧的使用場景: 1.遞歸 2.方法調用 3.表達式的轉化和求值 4.二叉樹遍歷 5.圖的深度優先遍歷 6.逆序輸出 如 單鏈表的反轉