數據結構——中綴轉后綴表達式


一、手工方式

如果只是用於解題的話,這種方法是最快最准確的。但是它不適用於計算機。下面以a+b*c+(d*e+f)*g為例子講以下人應該怎么把中綴表達式轉換成后綴表達式。

  1. 按先加減后乘除的原則給表達式加括號

    結果:((a+(b*c))+(((d*e)+f)*g))

  2. 由內到外把每個括號里的表達式換成后綴

    最終結果:abc*+de*f+g*+

這樣就得到了中綴表達式轉后綴表達式的最終結果。此法應付考試有神效。

二、棧的方式

計算機畢竟沒有人的思路,需要借助棧來實現從中綴表達式到后綴表達式的轉換。

這里明確一下使用棧轉換的算法思想

從左到右開始掃描中綴表達式 遇到數字, 直接輸出 遇到運算符 a.若為“(” 直接入棧 b.若為“)” 將符號棧中的元素依次出棧並輸出, 直到 “(“, “(“只出棧, 不輸出 c.若為其他符號, 將符號棧中的元素依次出棧並輸出, 直到遇到比當前符號優先級更低的符號或者”(“。 將當前符號入棧。 掃描完后, 將棧中剩余符號依次輸出

下面以a+b*c+(d*e+f)*g為例子來講講計算機的轉換過程。下面在描述棧的情況是直接用文字描述了,由左到右為棧底到棧頂表示棧空

  1. 由左向右遍歷表達式,首先遇到a,直接將其輸出。

    此時輸出為:a

    棧的情況為:空

  2. 繼續遍歷,遇到+,將其放入棧中。

    此時輸出為:a

    棧的情況為:+

  3. 繼續遍歷,遇到b,直接將其輸出。

    此時輸出為:ab

    棧的情況為:+

  4. 繼續遍歷,遇到*,因為*的優先級大於棧頂的+,所以將*放入棧內。

    此時輸出為:ab

    棧的情況為:+*

  5. 繼續遍歷,遇到c,直接將其輸出。

    此時輸出為:abc

    棧的情況為:+*

  6. 繼續遍歷,遇到+,因為+的優先級低於棧頂的*,故將*彈出;然后新的棧頂元素的+與這個+優先級相同,故也要彈出現在棧頂的+;然后棧空了,將現在這個+放入棧中。

    此時輸出為:abc*+

    棧的情況為:+

  7. 繼續遍歷,遇到(,直接將其放入棧中,不遇到)不會將(彈出。

    此時輸出為:abc*+

    棧的情況為:+(

  8. 繼續遍歷,遇到d,直接將其輸出。

    此時輸出為:abc*+d

    棧的情況為:+(

  9. 繼續遍歷,遇到*,因為棧頂為(,不遇到)不將(彈出,故直接將*放入棧中。

    此時輸出為:abc*+d

    棧的情況為:+(*

  10. 繼續遍歷,遇到e,直接將其輸出。

    此時輸出為:abc*+de

    棧的情況為:+(*

  11. 繼續遍歷,遇到+,因為+比棧頂*的優先級低,故將*彈出;新的棧頂元素為(,不遇到)不彈出(,故將+放入棧中。

    此時輸出為:abc*+de*

    棧的情況為:+(+

  12. 繼續遍歷,遇到f,直接將其輸出。

    此時輸出為:abc*+de*f

    棧的情況為:+(+

  13. 繼續遍歷,遇到),直接將棧中元素依次彈出並輸出直到遇到(為止,注意:(彈出但不輸出

    此時輸出為:abc*+de*f+

    棧的情況為:+

  14. 繼續遍歷,遇到*,因為*的優先級大於棧頂元素+的優先級,故直接將*入棧。

    此時輸出為:abc*+de*f+

    棧的情況為:+*

  15. 繼續遍歷,遇到g,直接將其輸出。

    此時輸出為:abc*+de*f+g

    棧的情況為:+*

  16. 繼續遍歷,為空,遍歷結束。將棧內元素依次彈出。

    此時輸出為:abc*+de*f+g*+

    棧的情況為:空

至此,中綴表達式轉后綴已經全部完成,結果為abc*+de*f+g*+

三、代碼實現

 借助C++的stack實現

//中綴表達式轉后綴

#include<iostream>
#include<string>
#include<stack>

using namespace std;

int prio(char op)                   //給運算符優先級排序
{
    int priority;
    if (op == '*' || op == '/')
        priority = 2;
    if (op == '+' || op == '-')
        priority = 1;
    if (op == '(')
        priority = 0;
    return priority;
}
bool Trans(string &str,string &str1)     //引用傳遞
{
    stack<char> s;                   //定義一個char類型的棧s
    int i;
    for (i = 0; i<str.size(); i++)
    {
        if (str[i] >= '0' && str[i] <= '9'||str[i] >= 'a' && str[i] <= 'z')      //如果是數字,直接入棧
        {
            str1+=str[i];
        }
        else                          //否則不是數字
        {
            if (s.empty())            //棧空則入站
                s.push(str[i]);
            else if (str[i] == '(')   //左括號入棧
                s.push(str[i]);
            else if (str[i] == ')')    //如果是右括號,只要棧頂不是左括號,就彈出並輸出
            {
                while (s.top() != '(')
                {
                    str1+= s.top();
                    s.pop();
                }
                s.pop();                 //彈出左括號,但不輸出
            }
            else
            {
                while (prio(str[i]) <= prio(s.top()))   //棧頂優先級大於等於當前運算符,則輸出
                {
                    str1+= s.top();
                    s.pop();
                    if (s.empty())      //棧為空,停止
                        break;
                }
                s.push(str[i]);   //把當前運算符入棧
            }
        }
    }
    while (!s.empty())        //最后,如果棧不空,則彈出所有元素並輸出
    {
        str1+= s.top();
        s.pop();
    }
    return true;
}
int main()                  //主程序
{
    string infix;
    string postfix;
    cout << "請輸入中綴表達式:" << infix << endl;
    cin >> infix;
    Trans(infix,postfix);
    cout << "后綴表達式為:" << postfix << endl;
    return 1;
}

 

 測試通過!

四、考研例題

這里給出兩道統考真題。

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM