數據結構與算法:中綴表達式轉後綴表達式

步驟:

1、初始化兩個棧:運算符棧s1和儲存中間結果的棧s2;

2、從左至右掃描中綴表達式;

3、遇到操作數時,將其壓s2;

4、遇到運算符時,比較其與s1棧頂運算符的優先級:

(1)、如果s1爲空,或棧頂運算符爲左括號“(",則直接將此運算符入棧;

(2)、否則,若優先級比棧頂運算符的高,也將運算符壓入s1;

(3)、否則,將s1棧頂的運算符彈出並壓入到s2中,再次轉到(1)中與s1中新的棧頂運算符相比較;

5、遇到括號時:

(1)、如果是左括號“(”,則直接壓入s1;

(2)、如果是右括號“)",則依次彈出s1棧頂的運算符,並壓入s2,直到遇到左括號爲止,此時將這一對括號丟棄。

6、重複步驟2至5,直到表達式的最右邊;

7、將s1中剩餘的運算符依次彈出並壓入s2;

8、依次彈出s2中的元素並輸出,結果的逆腳爲中綴表達式對應的後綴表達式。

舉例:1 + ( 2 + 3 ) * 4 - 5

①、中綴表達式:1 + ( ( 2 + 3 ) * 4 ) - 5

②、後綴表達式:- 5 + * 4 + 3 2 1 => 1 2 3 + 4 * + 5 -

在這裏插入圖片描述
具體代碼:

package com.ycx.stack;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class PolandNotation1 {
    public static void main(String[] args) {
        /*
        完成中綴表達式轉後綴表達式
        1、1+(2+3)*4-5 => 1 2 3 + 4 * 5 -
        2、直接對str操作,不方便;所以將" 1+(2+3)*4-5" 轉成中綴的List
            " 1+(2+3)*4-5"  => ArrayList[1, +, (, 2, +, 3, ), *, 4, -, 5]
       3、將中綴表達式對應的List => 後綴表達式對應的List
             ArrayList[1, +, (, 2, +, 3, ), *, 4, -, 5] =>ArrayList[1, 2, 3, +, 4, *, 5, -]
        */

        String expression = "1+(2+3)*4-5 ";
        List<String> expression1 = expressionList(expression);
        System.out.println("中綴表達式:"+ expression1); // [1, +, (, 2, +, 3, ), *, 4, -, 5]

        List<String> expression2 = expressionList1(expression1);
        System.out.println("後綴表達式:"+ expression2);
    }


    /* 將中綴表達式轉成對應的List  s = "1+(2+3)*4-5" */

        public static List<String> expressionList (String s){
            //定義一個List,存放中綴表達式對應的內容
            List<String> list = new ArrayList<>();
            int i = 0;  //指針:遍歷中綴表達式字符串
            String str; //多位數的拼接
            char c; //每遍歷到一個字符,就放入c
            do {
                //如果c是一個非數字,需要加入到list
                if ((c = s.charAt(i)) < 48 || (c = s.charAt(i)) > 57) {   // '0' → 48    '9' → 57
                    list.add(c + "");
                    i++; // i後移
                } else {  //否則c是一個數(需要考慮多位數)
                    str = ""; //將str置空
                    while (i < s.length() && (c = s.charAt(i)) >= 48 && (c = s.charAt(i)) <= 57) {
                        str += c;//拼接
                        i++;
                    }
                    list.add(str);
                }
            } while (i < s.length());
            return list;
        }




     /* 1) 初始化兩個棧:運算符棧s1和儲存中間結果的棧s2;
        2) 從左至右掃描中綴表達式;
        3) 遇到操作數時,將其壓s2;
        4) 遇到運算符時,比較其與s1棧頂運算符的優先級:
            1.如果s1爲空,或棧頂運算符爲左括號“(",則直接將此運算符入棧;
            2.否則,若優先級比棧頂運算符的高,也將運算符壓入s1;
            3.否則,將s1棧頂的運算符彈出並壓入到s2中,再次轉到1與s1中新的棧頂運算符相比較;
        5) 遇到括號時:
            1.如果是左括號“(”,則直接壓入s1
            2.如果是右括號“)",則依次彈出s1棧頂的運算符,並壓入s2,直到遇到左括號爲止,此時將這一對括號丟棄
        6) 重複步驟2至5,直到表達式的最右邊
        7) 將s1中剩餘的運算符依次彈出並壓入s2
        8) 依次彈出s2中的元素並輸出,結果的逆腳爲中綴表達式對應的後綴表達式 */

    // ArrayList[1, +, (, 2, +, 3, ), *, 4, -, 5] =>ArrayList[1, 2, 3, +, 4, *, 5, -]
    //將中綴表達式對應的List => 後綴表達式對應的List

    public static List<String> expressionList1(List<String> list){
        //定義兩個棧
        Stack<String> s1 = new Stack<String>(); //符號棧
        /*
        說明:
            s2這個棧在整個轉換過程中,沒有出棧操作,而且最後還需要逆序輸出,比較麻煩,
        所以我們不用Stack<String> ,直接用List<String>;
       */
        List<String> s2 = new ArrayList<String>();

        //遍歷list
        for(String ele:list){
            if(ele.matches("\\d+")){  //如果是一個數字
                s2.add(ele);
            }else if(ele.equals("(")){
                s1.push(ele);
            }else if(ele.equals(")")){  //如果是右括號“)"
                while (!s1.peek().equals("(")){
                    s2.add(s1.pop());//依次彈出s1棧頂的運算符,並壓入s2,直到遇到左括號爲止
                }
                s1.pop();//彈出"("     將這一對括號丟棄
            }else {  //如果是運算符
                /*當ele的優先級小於棧頂操作符時:*/
                while (s1.size()!=0 && Operation.getValue(ele) <= Operation.getValue(s1.peek())){
                    s2.add(s1.pop()); // 將s1棧頂的運算符彈出並壓入到s2中,再次轉到1與s1中新的棧頂運算符相比較
                }
                s1.push(ele);//再將ele壓入棧
            }
        }
        //將s1中剩餘運算符依次彈出並加入s2中
        while (s1.size()!=0){
            s2.add(s1.pop());
        }
        return s2;
    }
}

//編寫一個類:比較符號的優先級(數字大的優先級高)
class Operation{
    private static int ADD = 1;
    private static int SUB = 1;
    private static int MUL = 1;
    private static int DIV = 1;

    //寫一個方法返回
    public static int getValue(String ss){
        int result = 0 ;
        switch (ss){
            case "+":
                result=ADD;
                break;
            case "-":
                result=SUB;
                break;
            case "*":
                result=MUL;
                break;
            case "/":
                result=DIV;
                break;
            default:
                result=0;
                break;
        }
        return result;
    }
}



運行結果:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章