數據結構——棧實現計算器(中綴表達式)

棧實現綜合計算器(中綴表達式)

問題提出:

使用棧實現綜合計算器,能夠實現輸入有一個表達式,計算出來表達式最終結果,支持四則運算

實現思路(圖解):

在這裏插入圖片描述

實現要求:

  1. 先實現一位數的運算
  2. 實現多位數的運算:要判斷index下面是否還是一個數字,但是一定一定一定不能夠改變index的值

代碼:

package cn.littleworm.ArrayExperssion;

/*
            peek(): 顯示當前棧頂元素,是顯示,不是將這個元素pop出來
            priority(int oper):返回運算符的優先級,優先級由程序員來定
            isOpera(char oper):判斷是否是一個運算符
            cal(int num1,int num2,int oper):計算方法
 */

public class ArrayStrack {


    //定義全局屬性:棧頂指針
    private int top = -1;
    private int maxsize;
    private int[] stack;

    //創建構造器
    public ArrayStrack(int maxsize){    //maxsize是數組的長度

        this.maxsize = maxsize;
        //創建數組
        stack = new int[this.maxsize];
    }

    //判斷棧是否爲空
    public boolean isEmpty(){
        return top == -1;
    }

    //判斷棧是否已滿
    public boolean isFull(){
        return top == maxsize-1;
    }

    //壓棧
    public void push(int value){
        //判斷是否已滿
        if (isFull()){
            System.out.println("棧已滿");
            return;
        }
        top++;
        stack[top] = value;
    }

    //彈棧
    public int pop(){
        //判讀是否爲空
        if (isEmpty()){
            //拋出異常
            System.out.println("棧爲空,請先輸入數據");
            return 0;
        }
        //用來接收數據
        int value;
        value = stack[top];
        //將top減一
        top--;
        return value;
    }

    //顯示棧中數據
    public void showList(){
        //判斷棧中是否有數據
        if (isEmpty()){
            System.out.println("棧爲空,請先輸入數據");
            return;
        }
        //循環遍歷
        for (int i=top;i>=0;i--){
            System.out.println(stack[i]);
        }

    }

    //顯示棧頂元素,並不是將這個元素pop出去,而是單純的顯示
    public int peek(){
        return stack[top];
    }

    //priority():返回運算符的優先級,優先級由程序員來定,數字越大,優先級越高
    public int priority(int oper){
        if (oper == '*'||oper == '/'){
            return 1;
        }else if (oper == '+'|| oper == '-'){
            return 0;
        }else {
            return -1;
        }
    }

    // isOpera():判斷是否是一個運算符
    public boolean isOpera(char opera){
        if (opera == '+'||opera=='-'||opera=='*'||opera=='/'){
            return true;
        }else {
            return false;
        }
    }

    //cal():計算方法
    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;
        }
        return res;
    }

}
package cn.littleworm.ArrayExperssion;


/*
    實現效果:計算表達式:3+4*2-5;(中綴表達式)
        實現思路:
            1、有兩個棧,一個用來存放數據,一個用來存放運算符號
            2、有一個index(索引)指針,來遍歷我們的表達式
            3、當進行掃描時,如果發現是一個數,那麼就直接將數據放到數棧中
            4、如果時一個運算符,那麼分成以下幾種情況討論
                1、如果符號棧爲空,那麼直接進棧
                2、如果符號棧不爲空,對符號進行比較又分爲兩種情況
                    1、如果當前符號,優先級不大於符號棧中符號的優先級,那麼就從數棧中pop
                    兩個數,從符號棧中pop一個符號,然後進行運算,將運算獲得的數據push進
                    數棧中,然後將當前運算符號push進符號棧中
                    2、如果當前符號,優先級大於符號棧中的優先級,直接將符號push進符號棧
            5、當以上步驟進行 完畢之後,依次從數棧和符號棧中取出數據,進行運算,並將結果放到數棧中。
            6、最後數棧中只有一個數據,就是最後運行的結果,符號棧中沒有數據


        根據以上思路,對於棧(ArrayStrack)需要增加一下擴展方法
            peek(): 顯示當前棧頂元素,是顯示,不是將這個元素pop出來
            priority(int oper):返回運算符的優先級,優先級由程序員來定
            isOpera(char oper):判斷是否是一個運算符
            cal(int num1,int num2,int oper):計算方法


 */

public class Calcluator {

    public static void main(String[] args) {

        //表達式
        String expression = "7*2+10/3-5";
        //創建兩個棧:一個符號棧,一個數棧
        ArrayStrack numStrack = new ArrayStrack(10);
        ArrayStrack operStrack = new ArrayStrack(10);
        //定義相關變量
        int index = 0;  //用於掃描表達式
        int num1 = 0;
        int num2 = 0;
        int oper = 0;
        int res = 0;
        char ch = ' ';  //每次掃描得到的字符都放在ch中
        String keepNum = "";    //用來處理多位數

        while (true){
            //截取表達式字符串,並將截取的字符串轉換成爲char類型數據
            ch = expression.substring(index,index+1).charAt(0);

            //判斷ch是什麼,在進行相對應的操作
            if (operStrack.isOpera(ch)){
                //判斷符號棧是否爲空
                if (operStrack.isEmpty()){
                    //直接將符號push進棧中
                    operStrack.push(ch);
                }else {
                    //如果不爲空
                    //比較當前運算符與棧中運算符的優先級
                    if (operStrack.priority(ch)<=operStrack.priority(operStrack.peek())){
                        //如果當前運算符優先級大於棧中運算符優先級
                        //分別從數棧和符號棧中取出兩個數和一個運算符
                        num1 = numStrack.pop();
                        num2 = numStrack.pop();
                        oper = operStrack.pop();
                        //進行計算
                        res = numStrack.cal(num1,num2,oper);
                        //將運算的結果壓入棧中
                        numStrack.push(res);
                        //將當前的符號壓入棧中
                        operStrack.push(ch);
                    }else {
                        operStrack.push(ch);
                    }
                }
            }else { //如果是數字
               // numStrack.push(ch-48);  //注意對照ASCII碼錶

                /*
                    如果是數字這時又有一個問題:這個數字是一位數字還是多爲數字
                    所以這時候需要進行判斷:
                        1、向當前index的位置向後看一位,但並不改變index的值,並不改變index的值,並不改變index的值
                        2、如果後面一位是一個運算符,就將數據push進數棧中

                 */
                //將數據拼接到keepNum中
                keepNum+=ch;

                //判斷index是否是最後一位,如果是最後一位就沒有要判斷下一位的必要了
                if (index == expression.length()-1){
                    numStrack.push(Integer.parseInt(keepNum));
                }else {
                    //判斷index的下一位是否是運算符
                    if (operStrack.isOpera(expression.substring(index+1,index+2).charAt(0))){
                        //如果是運算符,就將keepNum轉成int類型並加到數棧中
                        numStrack.push(Integer.parseInt(keepNum));
                        //一定要清空keepNum,因爲不清空下一次會繼續拼接
                        keepNum = "";

                    }
                }

            }

            //判斷是否到達最後
            if (index>=expression.length()-1){
                break;
            }
            index++;
        }

        //當掃描完畢之後,就按照順序從數棧和符號棧中取出數據和符號,進行運算
        while (true){
            //當符號棧中的數據爲空的時候,就證明運算到了最後,數棧中只有一個數據,就是最終結果
            if (operStrack.isEmpty()){
                break;
            }
            num1 = numStrack.pop();
            num2 = numStrack.pop();
            oper = operStrack.pop();
            res = numStrack.cal(num1, num2, oper);
            //數入棧
            numStrack.push(res);
        }

        //最後將數據從數棧中pop出來
        int pop = numStrack.pop();
        System.out.println(expression+"="+pop);
    }
}
發佈了26 篇原創文章 · 獲贊 5 · 訪問量 4169
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章