一、前綴表達式
從右至左掃描表達式:
1、遇到數字時,將數字壓入堆棧;
2、遇到運算符時,彈出棧頂的兩個數,用運算符對它們做相應的計算(棧項元素和次頂元素),並將結果入棧;
3、重複上述過程直到表達式最左端,最後運算得出的值即爲表達式的結果。
【舉例】
( 3 +4 ) * 5 - 6 對應的前綴表達式 - * + 3 4 5 6
步驟如下:
(1)、從右至左掃描,將6、5、4、3壓入堆棧;
(2)、遇到+運算符,因此彈出3和4 (3爲棧頂元素,4爲次頂元素),計算出3+4的值,得7,再將7入棧;
(3)、接下來是運算符,因此彈出7和5,計算出75=35,將35入棧;
(4)、最後是-運算符,計算出35-6的值,即29,即爲最終結果。
二、中綴表達式
1、中綴表達式就是常見的運算表達式,如(3+4)*5-6;
2、 中綴表達式的求值是我們人最熟悉的,但是對計算機來說卻不好操作(上一個博客寫過代碼),因此,在計算結果時,往往會將中綴表達式轉成其它表達式來操作。(常見的操作是:中綴表達式轉後綴表達式)。
三、後綴表達式
1、後綴表達式又稱逆波蘭表達式,運算符位於操作數之後。
2、舉例說明: ( 3 + 4 ) * 5 - 6 對應的後綴表達式 3 4 + 5 * 6 -
3、一些轉後綴表達式的例子:
① a + b → a b +
② a + ( b - c ) → a b c - +
③ a + d * ( b - c ) → a d b c - * +
④ a = 1 + 3 → a 1 3 + =
⑤ a + ( b - c ) * d → a b c - d * +
那麼如何實現逆波蘭表達式呢?
從左至右掃描表達式:
1、遇到數字時,將數字壓入堆棧;
2、遇到運算符時,彈出棧頂的兩個數,用運算符對它們做相應的計算(次項元素和棧項元素),並將結果入棧;
3、重複上述過程直到表達式最右,最後運算得出的值即爲表達式的結果。
【舉例】
( 3 + 4 ) * 5 - 6 對應的前綴表達式 3 4 + 5 * 6 -
步驟如下:
(1)、從左至右掃描,將3和4壓入堆棧;
(2)、遇到+運算符, 因此彈出4和3 (4爲棧頂元素,3爲次頂元素),計算出3+4的值,得7,再將7入棧;
(3)、將5入棧;
(4)、 接下來是運算符,因此彈出5和7,計算出75=35,將35入棧;
(5)、將6入棧;
(6)、 最後是-運算符,計算出35-6的值, 即29,即爲最終結果。
具體代碼實現如下:
package com.ycx.stack;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class PolandNotation {
public static void main(String[] args) {
//先定義一個逆波蘭表達式:(3+4)*5-6 => 3 4 + 5 * 6 -
//測試
// 4 * 5 - 8 + 60 + 8 / 2=> 4 5 * 8 - 60 + 8 2 /
//爲了方便,逆波蘭表達式的數字和符號使用空格隔開
String expression = "30 4 + 5 * 6 -";
/*
思路:
1、將"3 4 + 5 * 6 -" 放到ArrayList中
2、將ArrayList傳遞給一個方法,遍歷ArrayList,配合棧完成計算
*/
List<String> list1 = getListString(expression);//放在List中方便取數,如果用index索引 需要一個一個的掃描,比較麻煩
System.out.println("list1 =" + list1);
int result1 = calculate(list1);
System.out.println("計算結果是:"+ result1);
}
//將一個逆波蘭表達式,依次將數據和運算符 放到ArrayList中
public static List<String> getListString(String expression){
//將expression用空格分割
String[] split = expression.split(" ");
List<String> list = new ArrayList<String>();
for (String ele : split){ //對split進行for循環 每循環一次就取出波蘭表達式中的一個元素
list.add(ele);
}
return list;
}
/*
完成逆波蘭表達式的步驟:
1) 從左至右掃描,將3和4壓入堆棧;
2) 遇到+運算符, 因此彈出4和3 (4爲棧頂元素,3爲次頂元素),計算出3+4的值,得7,再將7入棧;
3) 將5入棧;
4) 接下來是X運算符,因此彈出5和7,計算出7X5=35,將35入棧;
5) 將6入棧;
6) 最後是-運算符,計算出35-6的值, 即29,由此得出最終結果
*/
public static int calculate(List<String> list2){
//創建棧
Stack<String> stack = new Stack<String>();
//遍歷list2
for (String ele1:list2){
if(ele1.matches("\\d+")){ //正則表達式:匹配多位數
//如果是數就入棧
stack.push(ele1);
}else { //如果是字符 就pop出兩個數 進行運算
int num1 = Integer.parseInt(stack.pop()); //stack.pop() 出來的是字符 需要轉化成數字
int num2 = Integer.parseInt(stack.pop());//num2 比 num1 後 pop出 所以注意減法和除法時的順序
int result = 0;
if(ele1.equals("+")){
result = num1 + num2;
}else if(ele1.equals("-")){
result = num2 - num1;
}else if(ele1.equals("*")){
result = num1 * num2;
}else if(ele1.equals("/")){
result = num2 / num1;
}else {
throw new RuntimeException("運算符有誤");
}
//結果入棧
stack.push(result+"");//整數轉化爲字符串
}
}
//最後留在stack中的是運算結果
return Integer.parseInt(stack.pop());
}
}
運行結果如下: