PTA-7-20 表達式轉換(中綴轉後綴,帶括號,負數,小數轉換)

本題考點:中綴表達式轉後綴表達式。
難點:

  1. 帶有小數的數字
  2. 數字可能帶有正負號

題目描述:
算術表達式有前綴表示法、中綴表示法和後綴表示法等形式。日常使用的算術表達式是採用中綴表示法,即二元運算符位於兩個運算數中間。請設計程序將中綴表達式轉換爲後綴表達式。

本題的測試點如下:

輸入 輸出 說明
2+3*(7-4)+8/4 2 3 7 4 - * + 8 4 / + 正常測試6種運算符
((2+3)*4-(8+2))/5 2 3 + 4 * 8 2 + - 5 / 嵌套括號
1314+25.5*12 1314 25.5 12 * + 運算數超過1位整數且有非整數出現
-2*(+3) -2 3 * 運算數前有正負號
123 123 只有一個數字

我們先來說明中綴轉後綴的思路:

  1. 中綴轉後綴
  • 建立一個操作符棧,用以臨時存放操作符,建立一個數組或者隊列,用以存放後綴表達式

    • 從左到右掃描中綴表達式,如果碰到操作數,就把操作數加入到後綴表達式中
    • 如果碰到操作符 op,就把其優先級和操作符棧頂操作符優先級比較
    • 如果 op 的優先級高於棧頂,就壓入操作符棧(trick:初始化操作符棧時候增加一個 # 運算符爲最低)
    • 如果低於或者等於棧頂,就將操作符棧的操作符不斷彈出到後綴表達式中,直到 op 的優先級高於棧頂操作符
    • 重複直到中綴表達式掃描完畢,如果操作符棧中仍然有元素,則依次彈出放到後綴表達式中
  • 括號的處理方式

    • 將左括號的優先級設置爲比 + - 更低,但是直接插入
    • 如果遇到右括號,那麼直接從操作符棧中彈出到後綴表達式中,直到遇到左括號
  1. 後綴表達式的計算
  • 從左到右掃描後綴表達式,如果是操作數,就壓入棧,如果是操作符,就連續彈出兩個操作數,(後彈出的是第一操作數)
  • 然後進行操作符的操作,直到後綴表達式掃描完畢,這個時候結果棧中只剩一個元素,即爲運算的結果

那麼迴歸到本題,本題只要我們先把中綴轉成後綴,所以我們可以先不計算出每個位置具體數值,而是用字符串保存下來即可。

完整代碼和註釋如下:

/* 
	Author: Veeupup
 */
#include <iostream>
#include <vector>
#include <string>
#include <stack>
#include <map>
using namespace std;

vector<string> ans;
map<char, int> priority;
string operators = "+-*/()";    // 保存所有的計算符號

void trans(string str) 
{
    stack<char> ops;
    ops.push('#');
    string tempStr;
    for (int i = 0; i < str.size(); i++)
    {   // 檢查是否是帶符號的數字
        // 1. 帶正負號且前一個字符爲運算符(i=0時直接帶正負號的也是數字)
        // 2. 當前字符爲數字
        if( ((str[i] == '-' || str[i] == '+') && (i == 0 || string("+-/*(").find(str[i-1])!=string::npos)) || isdigit(str[i]) ) 
        {   // 把操作數加入到後綴式中
            // 如果是正號就不用加入,負號或者數字本身都要加入
            tempStr = str[i] != '+' ? str.substr(i, 1) : "";
            while (i + 1 < str.size() && operators.find(str[i+1]) == string::npos)
            {
                tempStr += str[++i];
            }
            ans.push_back(tempStr);
        }else { // 出現操作符
            if(str[i] == '(') 
                ops.push(str[i]);
            else if(str[i] == ')') {
                while (ops.top() != '(')
                {
                    ans.push_back(string(1, ops.top()));
                    ops.pop();
                }
                ops.pop();
            }else {
                while (priority[str[i]] <= priority[ops.top()])
                {
                    ans.push_back(string(1, ops.top()));
                    ops.pop();
                }
                ops.push(str[i]);
            }
        }
    }
    while (ops.size() > 1)
    {
        ans.push_back(string(1, ops.top()));
        ops.pop();
    }
}

int main()
{
    priority['*'] = priority['/'] = 3;
    priority['+'] = priority['-'] = 2;
    priority['('] = 1;
    priority['#'] = 0;
    string str;
    getline(cin, str);
    trans(str);
    for (int i = 0; i < ans.size(); i++)
        cout << (i ? " " : "") << ans[i]; 
    return 0;
}

路漫漫其修遠兮,吾將上下而求索。

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