# Stack# Infix to Postfix# Operator Precedence

f377 - 運算式轉換

🔗 前往 ZeroJudge 原題

題目描述

題目要求將一個中序運算式轉換為後序運算式。中序運算式是我們日常書寫的表達式形式,例如 a+b*c。後序運算式,也稱為波蘭式,將運算符放在操作數之後,例如 a b c * +。題目給定的中序運算式包含加、減、乘、除和括號,需要按照運算符的優先級和括號的規則進行轉換。

解題思路

本題使用堆疊 (Stack) 資料結構來實現中序轉後序的演算法。演算法的步驟如下:

  1. 遍歷中序運算式中的每個字元。
  2. 如果字元是操作數(字母),則直接輸出。
  3. 如果字元是左括號 (,則將其壓入堆疊。
  4. 如果字元是右括號 ),則從堆疊中彈出運算符,直到遇到左括號為止,並輸出彈出的運算符。然後將左括號彈出(但不輸出)。
  5. 如果字元是運算符(+, -, *, /),則將其與堆疊頂部的運算符的優先級進行比較。如果堆疊頂部的運算符優先級更高或相等,則從堆疊中彈出運算符並輸出,直到堆疊頂部的運算符優先級低於當前運算符或堆疊為空。然後將當前運算符壓入堆疊。
  6. 遍歷完中序運算式後,將堆疊中剩餘的所有運算符彈出並輸出。

p() 函數用於定義運算符的優先級。括號的優先級最高,乘除的優先級高於加減。

複雜度分析

  • 時間複雜度: O(n),其中 n 是中序運算式的長度。因為每個字元最多被壓入和彈出堆疊一次。
  • 空間複雜度: O(n),在最壞的情況下,例如 ((((a+b)))),堆疊可能需要儲存所有左括號和運算符。

程式碼

#include <iostream>
#include <stack>
using namespace std;
inline int p(char x){
	if(x=='+'||x=='-'){
		return 1;
	}
	else if(x=='*'||x=='/'){
		return 2;
	}
	else{
		return 0;
	}
}
int main(){
	cin.tie(0); ios::sync_with_stdio(false);
	string input;
	while(getline(cin,input)){
		stack <char> back;
		for(int i=0,il=input.length();i<il;++i){
			if(input[i]!=' '){
				if(input[i]=='('){
					back.push('(');
				}	
				else if(input[i]=='+'||input[i]=='-'||input[i]=='*'||input[i]=='/'){
					while(!back.empty()&&p(back.top())>=p(input[i])){
						cout << back.top() << " ";
						back.pop();
					}
					back.push(input[i]);
				}
				else if(input[i]==')'){
					while(!back.empty()&&back.top()!='('){
						if(back.top()!='('&&back.top()!=')')cout << back.top() << " ";
						back.pop();
					}
					back.pop();
				}
				else{
					cout << input[i] << " ";
				}
			}
		}
		while(!back.empty()){
			if(back.top()!='('&&back.top()!=')')cout << back.top() << " ";
			back.pop();
		}
		cout << "\n";
	}
}

Discussion