數據結構與算法分析c++:棧的應用(3)

中綴表達式轉後綴表達式

中綴表達式轉換成後綴表達式的方法闡述

依舊利用棧這種數據結構,本文只是以+、-、*、/、()幾個運算符爲例,有興趣的小夥伴可以自己拓展。
如何將a + b * c + ( d * e + f ) * g形式的中綴表達式轉換成後綴表達式呢?
先上正確答案,abc*+de*f+g*+

步驟如下:

· 建立一個空棧;
· 遍歷字符串。當讀到操作數時,直接輸出;
· 當讀到運算符時:
a 若爲 ‘(‘,入棧;
b 若爲 ‘)’,則依次把棧中的的運算符加入後綴表達式中,直到出現’(‘,從棧中刪除’(’ ;
c 若爲除括號外的其他運算符, 當其優先級高於除’(‘以外的棧頂運算符時,直接入棧。
d 否則,依次彈出比當前處理的運算符優先級高和優先級相等的運算符,直到一個比它優先級低的或者遇到了一個左括號爲止。
e 遍歷結束時,棧中的所有運算符出棧;

那廢話不多說,直接上代碼。第一個函數int sortOperator(char c)主要是給運算符規定優先順序,方便後續判斷,可以看出如果想添加運算符種類的話,在這個函數擴展也很方便;第二個函數void infixToPostfix(string expression)就是實現轉換的函數了。

#include <iostream> 
#include <stack>
#include <string> 
using namespace std;

int sortOperator(char c) {
    switch (c)
    {
    case ')':
        return 0;
    case '*':
        return 1;
    case '/':
        return 1;
    case '+':
        return 2;
    case '-':
        return 2;
    case '(':
        return 3;
    default:
        return -1;
    }
}

void infixToPostfix(string expression){
    stack<char> s;
    for (int i = 0; i < expression.length();i++) {
        //字母代表操作數,直接輸出
        if (expression.at(i) >= 'a' && expression.at(i) <= 'z') {
            cout << expression.at(i) << "";
        }
        //去除空格
        else if (expression.at(i) == ' ') {}
        else
            switch (expression.at(i)){
            //左括號直接入棧
            case '(':
                s.push(expression.at(i));
                break;
            //同級運算符寫一種就可以,因爲sortOperator返回值相同,這裏未做省略
            //這裏還要注意sortOperator的返回值和實際運算優先級相反,
            //也可調整爲和實際運算優先級相同,方便理解。
            case'*':
                //棧非空,且棧頂運算符優先級高於或等於當前運算符,出棧並輸出,直到棧頂運算符
                //優先級低於當前運算符,該運算符入棧
                while (!s.empty() && 
                    sortOperator(s.top()) <= sortOperator('*')) {
                    cout << s.top();
                    s.pop();
                }
                s.push(expression.at(i));
                break;

            case '/':
                while (!s.empty() &&
                    sortOperator(s.top()) <= sortOperator('/')) {
                    cout << s.top();
                    s.pop();
                }
                s.push(expression.at(i));
                break;

            case '+':
                while (!s.empty() &&
                    sortOperator(s.top()) <= sortOperator('+')) {
                    cout << s.top();
                    s.pop();
                }
                s.push(expression.at(i));
                break;

            case '-':
                while (!s.empty() &&
                    sortOperator(s.top()) <= sortOperator('-')) {
                    cout << s.top();
                    s.pop();
                }
                s.push(expression.at(i));
                break;

            case ')':
                //遇到右括號,一直進行出棧操作並輸出,直到遇到左括號結束循環,再將左括號
                //出棧,且不輸出
                while (!s.empty() && s.top() != '(')
                {
                    cout << s.top() << "";
                    s.pop();
                }
                s.pop();
                break;

            default:
                break;
        }

    }
    //遍歷表達式後,棧內所有操作符依次出棧並輸出。
    while (!s.empty())
    {
        cout << s.top() << "";
        s.pop();
    }
    cout << endl;
}

測試代碼如下,

int main(int argc, char* argv[])
{
    cout << "input expression" << endl;
    string line; 
    getline(cin, line);
    infixToPostfix(line);
    system("pause");
    return 0;
}

結果

有興趣的小夥伴,可以嘗試多添加幾種運算符,^, ! 等等。

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