1. 程式人生 > >java中綴表達式轉後綴表達式

java中綴表達式轉後綴表達式

棧 邏輯運算 後綴表達式 逆波蘭 數據結構

四則運算是棧的重要應用之一

中綴表達式轉後綴表達式(逆波蘭算法)過程

  1. 從左到右遍歷中綴表達式
  2. 數字直接輸出為後綴表達式一部分
  3. 如果是符號,則判斷與棧頂元素的優先級
  4. 高於棧頂元素優先級直接入棧
  5. 低於或等於棧頂優先級棧頂元素出棧並輸出為後綴表達式一部分(註意這裏是遞歸比較棧頂元素的優先級並出棧),最後將當前元素入棧
    直到遍歷完中綴表達式,最終輸出後綴表達式

下面是自己的實現源碼

package com.yhq.demospringboot;
import org.apache.commons.lang3.StringUtils;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
/**
 * yanghq
 * 2018/3/12
 */
public class PreToAfterUtil {

private static String leftChar = "(";
private static String rightChar = ")";
private static Map<String, Integer> operationSymbolMap = new HashMap<>();

static {
        //初始化符號和優先級
        operationSymbolMap.put(")",00); //右括號需匹配左括號,故優先級最低
        operationSymbolMap.put("+",10);
        operationSymbolMap.put("-",10);
        operationSymbolMap.put("*",20);
        operationSymbolMap.put("/",20);
        operationSymbolMap.put("(",30);
}

/**
 * 中綴表達式轉化為後綴表達式
 * @param strings
 * @return
 */
public Queue parsePre(String[] strings) {
        Stack<String> preStack = new Stack<String>();
        Queue<String> queue = new LinkedBlockingQueue();
        int i = 0;
        while(i<strings.length && Objects.nonNull(strings[i])) {
                if(StringUtils.isNumeric(strings[i])) {
                        queue.add(strings[i]);
                }else if(StringUtils.isNotEmpty(strings[i])) {
                        if(preStack.isEmpty()) {
                                preStack.push(strings[i]);
                        } else {
                                String top = preStack.pop();
                                if(comparePriority(strings[i], top) < 0) {
                                        if(top.equals(leftChar)) {
                                                preStack.push(top);
                                                preStack.push(strings[i]);
                                        }else if(strings[i].equals(rightChar)) {
                                                appendTo(queue, top);
                                                preStack.pop();
                                        } else{
                                                appendTo(queue, top);
                                                popPre(preStack, strings[i], queue);
                                                preStack.push(strings[i]); //當前元素入棧
                                        }
                                } else {
                                        preStack.push(top);
                                        preStack.push(strings[i]);
                                }
                        }
                }
                i++;
        }
        while (!preStack.isEmpty()) {
                queue.add(preStack.pop());
        }
        return queue;
}

/**
 * 遞歸比較當前元素與棧頂元素優先級
 * @param preStatck
 * @param charTemp
 * @param queue
 */
public void popPre(Stack<String> preStatck, String charTemp, Queue queue) {
        if(!preStatck.isEmpty()) {
                String top = preStatck.pop();
                if(comparePriority(charTemp, top) <= 0) {
                        //低於棧頂元素,成為後綴表達式一部分
                        appendTo(queue, top);
                        popPre(preStatck, charTemp, queue);
                } else {
                        preStatck.push(top);
                }
        }
}

private void appendTo(Queue queue, String s) {
        if(!s.equals(leftChar) && !s.equals(rightChar)) {
                queue.add(s);
        }
}

/**
 * 比較優先級
 * @param start
 * @param to
 * @return
 */
private int comparePriority(String start, String to) {
        return operationSymbolMap.get(start).compareTo(operationSymbolMap.get(to));
}

/**
 * 計算後綴表達式結果
 * @param queue
 * @return
 */
public int computeResult(Queue<String> queue) {
        int result = 0;
        if(Objects.isNull(queue)) {
                return result;
        }
        String s = queue.poll();
        Stack<Integer> stack = new Stack();
        while(Objects.nonNull(s)) {
                if(StringUtils.isNumeric(s)) {
                        stack.push(Integer.valueOf(s));
                }else if(!StringUtils.isEmpty(s)) {
                        int first = 0;
                        int second = 0;
                        switch (s) {
                                case "+" :
                                        first = stack.pop();
                                        second = stack.pop();
                                        result = first + second;
                                        stack.push(result);
                                        break;
                                case "-" :
                                        first = stack.pop();
                                        second = stack.pop();
                                        result = second - first;
                                        stack.push(result);
                                        break;
                                case "*" :
                                        first = stack.pop();
                                        second = stack.pop();
                                        result = first * second;
                                        stack.push(result);
                                        break;
                                case "/" :
                                        first = stack.pop();
                                        second = stack.pop();
                                        result = second/first;
                                        stack.push(result);
                                        break;
                        }
                }
                s = queue.poll();
        }
        return result;
}

/**
 * 測試
 * @param args
 */
public static void main(String[] args) {
        String[] pre = new String[]{"8","+","(","6","-","1",")","*","2","+","10","/","2"};
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < pre.length; i++) {
                sb.append(pre[i]);
        }
        System.out.println("前綴表達式:" + sb.toString());
        Queue queue = new PreToAfterUtil().parsePre(pre);
        System.out.println("後綴表達式:" + queue.toString());
        System.out.println("後綴表達式計算結果:" + new PreToAfterUtil().computeResult(queue));
}

}

輸出結果展示
前綴表達式:8+(6-1)2+10/2
後綴表達式:[8, 6, 1, -, 2,
, +, 10, 2, /, +]
後綴表達式計算結果:23

java中綴表達式轉後綴表達式