DS棧—波蘭式,逆波蘭式


題目描述

       表達式有三種表示方法,分別為:

    前綴表示(波蘭式):運算符+操作數1+操作數2

    中綴表示:操作數1+運算符+操作數2

    后綴表示(逆波蘭式):操作數1+操作數2+運算符

    例如:a +b * (c -d ) - e/f

    波蘭式:-+a*b-cd/ef     (運算符在操作數的前面,用遞歸計算波蘭式)

    中綴式:a+b*c-d-e/f  

    逆波蘭式:abcd-*+ef/   (運算符在操作數的后面,用棧計算逆波蘭式)

       中綴表示就是原表達式去掉扣號。       

     根據表達式求波蘭式、逆波蘭式都是教材第三章表達式求值的思想。     

      求波蘭式,需要操作數棧(注意不是計算結果入棧,有計算式入棧),運算符棧。區別在於從后往前掃描表達式,‘(’ 換成')','('換成‘)’。棧頂運算符優先級>新讀入運算符優先級出棧,表3.1中的相同運算符優先級>(從左往右計算)改為<,例如棧頂為‘+‘,新讀入的為‘+’,則棧頂優先級<新讀入的優先級。

     求逆波蘭式,只需要運算符棧。操作數直接輸出,操作符按表3.1優先級順序出棧,輸出。

 

       輸入表達式,求其波蘭式和逆波蘭式。

 

 

輸入

 測試次數

每組測試數據一行,一個合法表達式

輸出

 對每組測試數據,輸出兩行

第一行,表達式的波蘭表示

第二行,表達式的逆波蘭表示

不同組測試數據間以空行分隔。

樣例輸入

2 4+2*3-10/5 12+3*5+(2+10)*5

樣例輸出

- + 4 * 2 3 / 10 5 4 2 3 * + 10 5 / - + + 12 * 3 5 * + 2 10 5 12 3 5 * + 2 10 + 5 * +

提示

#include<iostream>
#include<stack>
#include<string>
#include<sstream>
#include<algorithm>
using namespace std;
#define ok 0
#define error -1
#define opsetsize 7
char PoPrior[7][7]=
{
    '<','<','<','<','>','<','>',
    '<','<','<','<','>','<','>',
    '>','>','<','<','>','<','>',
    '>','>','<','<','>','<','>',
    '>','>','>','>','>','=','>',
    '<','<','<','<','=','<','>',
    '<','<','<','<','<','<','='
};
char Prior[7][7]=
{
    ///運算符間的優先關系,分別是+ - * / ( ) #
    ///按行看+ - * / ( ) #
    '>','>','<','<','<','>','>',
    '>','>','<','<','<','>','>',
    '>','>','>','>','<','>','>',
    '>','>','>','>','<','>','>',
    '<','<','<','<','<','=',' ',
    '>','>','>','>',' ','>','>',
    '<','<','<','<','<',' ','='
};
double Operate(double a,char theta,double b)
{
    if(theta=='+')
        return a+b;
    else if(theta=='-')
        return a-b;
    else if(theta=='*')
        return a*b;
    else if(theta=='/')
        return a/b;
    return error;
}
char opset[opsetsize]={'+', '-', '*', '/', '(', ')','#'};///運算符集合
int in(char Test,char *p)///1是運算符,0不是運算符
{
    ///判斷字符Test是否是運算符
    for(int j=0;j<opsetsize;j++)
    {
        if(Test==p[j])
            return 1;
    }
    return 0;
}
char Poprecede(char Aop,char Bop)
{
    ///獲取兩個運算符之間的優先級,Aop是棧頂,Bop是下一個運算符
    int i;
    for(i=0;i<opsetsize;i++)
        if(opset[i]==Aop)
            break;
    int j;
    for(j=0;j<opsetsize;j++)
        if(opset[j]==Bop)
            break;
    return PoPrior[i][j];
}
char precede(char Aop,char Bop)
{
    ///獲取兩個運算符之間的優先級,Aop是棧頂,Bop是下一個運算符
    int i;
    for(i=0;i<opsetsize;i++)
        if(opset[i]==Aop)
            break;
    int j;
    for(j=0;j<opsetsize;j++)
        if(opset[j]==Bop)
            break;
    return Prior[i][j];
}
void Poland(string exp)
{
    stack<char>Optr;
    string Myexp=exp;
    reverse(Myexp.begin(),Myexp.end());
    stack<string>Output;
    string Tempdata;
    stringstream ss;
    string theta;
    char c;
    int i=0;
    Optr.push('#');
    c=Myexp[0];
    while(c!='#'||Optr.top()!='#')
    {
        if(in(c,opset)==0)
        {
            Tempdata+=c;
            c=Myexp[++i];///讀取下一個字符
            if(in(c,opset)!=0)
            {
                ///如果c是運算符,表明前面讀入了一個完整的操作數
                ss.clear();
                if(Tempdata.size()!=0)
                {
                    reverse(Tempdata.begin(),Tempdata.end());
                    Output.push(Tempdata);
                    Tempdata.clear();
                }
            }
        }
        else
        {
            ///是運算符,開始計算
            switch(Poprecede(Optr.top(),c))
            {
                case'<':///棧頂的優先級低,即Op1<Op2,壓入新的運算符
                    Optr.push(c);
                    c=Myexp[++i];
                    break;
                case'=':///脫括號和脫#號,壓入新的運算符
                    Optr.pop();
                    c=Myexp[++i];
                    break;
                case'>':///退棧,暫時先保留該運算符,用來繼續判斷
                    theta=Optr.top();
                    Optr.pop();
                    Output.push(theta);
                    break;
            }
        }
    }
    int tag=0;
    while(!Output.empty())
    {
        if(tag==0)
        {
            cout<<Output.top();
            Output.pop();
            tag++;
        }
        else
        {
            cout<<" "<<Output.top();
            Output.pop();
            tag++;
        }
    }
    cout<<endl;
}
 
void rePoland(string Myexp)
{
    stack<char>Optr;
    string Tempdata;
    stringstream ss;
    double data;
    char theta;
    char c;
    int i=0;
    int tag=0;
    Optr.push('#');
    c=Myexp[0];
    while(c!='#'||Optr.top()!='#')
    {
        if(in(c,opset)==0)
        {
            Tempdata+=c;
            c=Myexp[++i];///讀取下一個字符
            if(in(c,opset)!=0)
            {
                ///如果c是運算符,表明前面讀入了一個完整的操作數
                ss.clear();
                if(Tempdata.size()!=0)
                {
                    ss<<Tempdata;
                    ss>>data;
                    if(tag==0)
                    {
                        cout<<data;
                        tag=1;
                    }
                    else
                    {
                        cout<<" "<<data;
                    }
                    Tempdata.clear();
                }
            }
        }
        else
        {
            ///是運算符,開始計算
            switch(precede(Optr.top(),c))
            {
                case'<':///棧頂的優先級低,即Op1<Op2,壓入新的運算符
                    Optr.push(c);
                    c=Myexp[++i];
                    break;
                case'=':///脫括號和脫#號,壓入新的運算符
                    Optr.pop();
                    c=Myexp[++i];
                    break;
                case'>':///退棧,暫時先保留該運算符,用來繼續判斷
                    theta=Optr.top();
                    Optr.pop();
                    cout<<" "<<theta;
                    break;
            }
        }
    }
    cout<<endl;
}
int main()
{
    string exp;
    int T;
    cin>>T;
    while(T--)
    {
        cin>>exp;
        string myexp=exp;
        reverse(myexp.begin(),myexp.end());
        myexp+="#";
        reverse(myexp.begin(),myexp.end());
        Poland(myexp);
        exp+="#";
        rePoland(exp);
        if(T)
            cout<<endl;
    }
    return 0;
}


免責聲明!

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



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