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;
}

猜你喜欢

转载自www.cnblogs.com/SZU-DS-wys/p/12177999.html
今日推荐