中綴轉後綴表達式——java(附四則運算)

1. 後綴表達式

後綴表達式,即爲逆波蘭表達式,其運算方法爲從左到右掃描表達式,當遇到符號時,取該符號前兩位數,使用前一個數運算後一個數,將結果放入剛纔兩個數的位置,運算的兩個數以及符號便去掉。由此得知,使用棧運算會很方便,下面會有完整的計算一個四則運算表達式的代碼

2. 思路分析

1.將字符串轉化爲list,目的是方便操作
2.簡歷一個符號棧與結果隊列,符號棧用於存儲遍歷得到的符號,隊列利用其先進先出的特性來記錄轉化後的後綴表達式
3.遍歷該list
3.1該元素爲數字,直接入結果隊列
3.2該元素爲符號
3.2.1棧爲空或者棧頂元素爲”(“,則將該元素直接入符號棧
3.2.2棧頂元素優先級小於該元素,則將該元素直接入符號棧
3.2.3如果不滿足以上條件,則將棧頂元素入結果隊列,並且從3.2.1繼續開始進行判斷
3.3遍歷list結束後,將棧中剩餘的元素依次加入結果隊列中,結果即爲對應的後綴表達式

3. 代碼實現

//本代碼包含: 中綴表達式轉化後綴表達式,計算後綴表達式
package stack;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

/**
 * 逆波蘭計算器
 */
public class ReversePolish {

    public static void main(String[] args) {
        String s = "2*(16+8/4-5)+4";
        ReversePolish reversePolish = new ReversePolish();
        System.out.println(reversePolish.toReversePolish(stringToList(s)).toString());
        System.out.println(reversePolish.calculate(reversePolish.toReversePolish(stringToList(s))));
    }

    private List<String> toReversePolish(List<String> list){
        Stack<String> stack = new Stack<String>();
        List<String> linkedList = new LinkedList<String>();
        for (int i = 0; i < list.size(); i++){
            String s = list.get(i);
            int chk = check(s);
            //如果當前元素爲符號
            if (chk == 0){
                //如果棧爲空或者棧頂元素爲( 直接壓入棧
                if (stack.isEmpty() || "(".equals(stack.peek())){
                    stack.push(s);
                    continue;
                }
                //如果符號棧不爲空
                //取當前符號的優先級
                int a = compare(s);
                //取棧頂元素的優先級
                int b = compare(stack.peek());
                //如果當前符號優先級大於棧頂元素優先級
                if (a > b){
                    stack.push(s);
                }else{//如果棧不爲空或棧頂不爲(或者當前符號不比棧頂元素優先級高
                    //繼續判斷棧是否爲空或者棧頂元素是否爲(
                    while (true){
                        if (stack.isEmpty() || "(".equals(stack.peek())){
                            stack.push(s);
                            break;
                        }
                        //繼續判斷棧頂元素與當前元素優先級
                        if (a > compare(stack.peek())){
                            linkedList.add(s);
                            break;
                        }
                        //如果不滿足以上條件,將棧頂元素加入結果隊列中,並且繼續循環
                        linkedList.add(stack.pop());
                    }
                }
            }else if (chk == 1){//如果當前元素爲( 則直接入棧
                stack.push(s);
            }else if (chk == 2){//如果當前元素爲) 則將棧頂一次加入結果隊列 直到棧頂爲(
                while(true){
                    String top = stack.pop();
                    if ("(".equals(top)){//如果棧頂爲( 則結束循環 將這對括號丟棄
                        break;
                    }else {//棧頂不爲( 將棧頂元素加入到結果集中即可
                        linkedList.add(top);
                    }
                }
            }else{
                linkedList.add(s);
            }
        }
        //循環結束後,將棧中剩餘的元素依次入結果集
        while(!stack.isEmpty()){
            linkedList.add(stack.pop());
        }
        //返回隊列即爲後綴表達式
        return linkedList;
    }

    private int compare(String s){
        if ("+".equals(s) || "-".equals(s)){
            return 1;
        }else {
            return 2;
        }
    }

    private int check(String s){
        if ("+".equals(s) || "-".equals(s) || "/".equals(s) || "*".equals(s)){
            return 0;
        }else if ("(".equals(s)){
            return 1;
        }else if (")".equals(s)){
            return 2;
        }else{
            return 3;
        }
    }

    private  int calculate(List<String> list){
        Stack<Integer> numStack = new Stack<Integer>();
        for (int i = 0; i < list.size(); i++){
            String s = list.get(i);
            if (notNumber(s)){
                int num1 = numStack.pop();
                int num2 = numStack.pop();
                if ("+".equals(s)){
                    numStack.push(num1 + num2);
                }else if ("-".equals(s)){
                    numStack.push(num2 - num1);
                }else if ("*".equals(s)){
                    numStack.push(num2 * num1);
                }else if ("/".equals(s)){
                    numStack.push(num2 / num1);
                }
            }else {
                numStack.push(Integer.parseInt(s));
            }
        }
        return numStack.pop();
    }

    private boolean notNumber(String s){
        return "+".equals(s) || "-".equals(s) || "*".equals(s) || "/".equals(s);
    }

    private static List<String> stringToList(String s){
        List<String> res = new ArrayList<String>();
        int i = 0;
        while(i < s.length()){
            char c = s.charAt(i);
            //數字
            if (c >= 48 && c <= 57){
                String str = "";
                while (i < s.length() && ((c = s.charAt(i)) >= 48 && (c <= 57)) ){
                    str = str + String.valueOf(c);
                    i++;
                }
                res.add(str);
            }else{//符號
                res.add(String.valueOf(c));
                i++;
            }
        }
        return res;
    }
}

4. 後記

本文重點記錄思路,代碼較爲粗糙,太累了…以後有時間了再美化吧。

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