步驟:
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;
}
}
運行結果: