數據結構——棧——中綴表達式和后綴表達式


什么是中綴表達式,什么是后綴表達式

我們一般看見的多項式計算都是中綴表達式構成的:1+2*3+4/3

類似這種,為什么說是中綴呢?因為它的計算符號都是在兩個數中間的。

那么自然而然的明白了后綴表達式是一種計算符號在兩個數后面的。

如123*+43/+

 

中綴表達式和后綴表達式有什么關系?

其實仔細你就會發現,上面給出的式子其實都是一樣的,只是計算的順序在后綴表達式中你看不懂而已。

因為我們習慣去看中綴表達式的計算。

其實他們之間是可以互相轉換的。他們也可以表達同一個意思,同一個計算式子。

 

為什么會提出后綴表達式

這里馬上就會有問題了,為什么好好的不用中綴表達式,而提出那么一個難看的后綴表達式。

首先對於我們人來說,計算的時候看到乘法和除法自然而然的就會去先計算,而對於計算機這么笨的東西來說,它不知道。

對於中綴表達式來說,計算機不能預料到后面是否會出現高階的計算符號,是否要先進行計算,所以在計算的次序上面很有可能出錯。

所以就有了后綴表達式,計算機在計算后綴表達式的時候不用擔心計算的次序。那么問題就來了,如何計算一個后綴表達式的值呢?

別急,我們先來看看如何把一個中綴表達式轉換成一個后綴表達式。

 

中綴表達式轉換成后綴表達式

這里我們提前約定一下,我們的式子包含加減乘除和小括號,所有的數據我們暫時用個位數來表示,不包含次方開方和中括號。當然也不是可以,我們這邊將問題盡量簡單化。

1.   從左向右掃遍歷表達式:
2.   If 當前遍歷到的字符 ch 是操作數,則打印
3.   Else If 當前遍歷的ch是 ‘(‘, 入棧
4.   Else If 當前遍歷的ch是 ‘)’, 不斷彈出棧頂元素,直到棧為空或彈出’(‘
5.   Else,
…….5.1 If  上一個操作符的優先級比當前操作符ch的優先級小,或棧是空的就入棧。
……. 5.2 Else, 不斷彈出棧頂的操作符,並打印,直到棧為空或當前的操作符ch的優先級大於棧頂的操作符。將當前操作符入棧。
6.  重復2-6步,直到遍歷完成
7.  彈出並打印棧中的剩余的操作符

 

代碼描述

#include<cstdio> 
#include<iostream>
#include<cstdlib>
#include<string> 
#include<string.h> 
#include<stack>

using namespace std;

int getRank(char sign)
{
    switch(sign)
    {
        case '+':
        case '-':
            return 1;
        case '*':
        case '/':
            return 2;
    }
    return -1;
}

int main()
{
    int i=0;
    stack<char> expStack;
    string expression;
    cin>>expression;
    
    for(i=0; i<expression.length(); i++)
    {
        if(expression[i]>='0' && expression[i]<='9')
        {
            cout<<expression[i];
        }
        else if(expression[i] == '(')
        {
            expStack.push(expression[i]);
        }
        else if(expression[i] == ')')
        {
            char top = expStack.top();
            expStack.pop();
            while(!expStack.empty() && top != '(')
            {
                cout<<top;
                top = expStack.top();
                expStack.pop();
            }
        }
        else
        {
            int now = getRank(expression[i]);
            if(expStack.empty() || now > getRank(expStack.top()))
            {
                expStack.push(expression[i]);
            }
            else
            {
                while(!expStack.empty() && now <= getRank(expStack.top()))
                {
                    cout<<expStack.top();
                    expStack.pop();
                }
                expStack.push(expression[i]);
            }
        }
    }
    
    while(!expStack.empty())
    {
        cout<<expStack.top();
        expStack.pop();
    }
    return 0;
}

 

 

后綴表達式的計算

我們現在已經能得到后綴表達式了,那么如何利用它計算。

其實很簡單,首先我們觀察到后綴表達式中已經沒有任何括號了,所以對於我們來說計算順序就很容易了。

從左往右讀取,數字入棧,如果遇到計算符號(比如遇到一個加號),出棧兩個數然后計算(比如兩個數相加),然后將結果入棧。

最后在棧中的數據就為計算的結果。

 

思考

棧對於帶有括號的計算式,四則運算等比較好用,利用棧的特性能保存一些計算等級低的,讓等級高的先進行計算。

之后遇到這樣的問題可以首先考慮使用棧。


免責聲明!

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



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