题解 P1175 【表达式的转换】

· · 题解

全真模拟AC 不要问我怎么有毅力这样做出来 (至今为止我写过的最长的代码就这题了)

1.中转后 数字直接输出 每在表达式中插入一个算符就输出他(记得加空格) 最后记得栈中算符全部出栈并依次输出

2.预先计算出需要运算的次数(即算符个数)

3.从前往后扫 扫到一个算符就从他前面找两个数运算并将找过的位置置为空,再将得出的结果写回去(这里比较复杂,具体看代码)

然后输出;(还要注意负数的处理,我写的也很麻烦)

4.继续从原来的位置扫描,重复操作;

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
char sz[100001];
char hz[100001];
char stack[100001];
int top=0;
inline int doit(int x,int y,char how); 
inline bool cmp(char ch,char cr)
{
    if(ch==')'&&cr!='(') return 0;//右括号在没有遇到左括号时优先度最低;
    else if(ch==')'&&cr=='(') return 1;//为括号的情况优先考虑 (两括号相遇要删除) 
    if(cr=='(') return 1;//在没有找到右括号之前左括号不能动; 
    if(ch=='+'||ch=='-') return 0;//加减法优先度一定不比之前的任何算符高; 
    if(ch=='^') return 1; 
    if(cr=='^') return 0;//'^'在所有除括号外的算符中优先度最高;
    if((ch=='*'||ch=='/'||ch=='^')&&(cr=='+'||cr=='-')) return 1;//剩下的就只有当 ch (要入栈的算符)为乘除时  cr 为加减时 ch 优先度才比cr(top指向的算符)高 
    return 0;
}
void push(char ch,int &l)
{
    if(ch=='(')
    {
        stack[++top]=ch;
    }
    else {
        while(!cmp(ch,stack[top])&&stack[top]!='@')//未成功匹配到合适位置且未到栈底则top减1出栈 
        {
            if(stack[top]!='('&&stack[top]!=')')
            {hz[++l]=stack[top];cout<<stack[top]<<" ";}//每从栈中取出一个算符 就要输出(也可以最后再扫一遍,这样可能更方便) 
            top--;
        }
        stack[++top]=ch;//找到合适的位置放置运算符 
        if(stack[top]==')'&&stack[top-1]=='(')
        top-=2;//抵消;
    }
}
int main()
{
    scanf("%s",sz);
    stack[top]='@';
    int len=strlen(sz);int j=0;
    //hz[++j]='.';hz[++j]='.';hz[++j]='.';//防止出错多加几个空格 
    for(int i=0;i<len;i++)
    {
        if(sz[i]>='0'&&sz[i]<='9')
        {
            hz[j]=sz[i];cout<<sz[i]<<" ";
        }
        else if(sz[i]=='-'||sz[i]=='+'||sz[i]=='*'||sz[i]=='^'||sz[i]=='/')
        {
            hz[j]='.';//标记 (后缀表达式中)
            hz[++j]='.';
            hz[++j]='.';hz[++j]='.';
            push(sz[i],j);
        }
        else if(sz[i]=='('||sz[i]==')')//括号不输出 
        {
            hz[j]='.';
            hz[++j]='.';
            hz[++j]='.';hz[++j]='.';//多放几个空格 
            push(sz[i],j);    
        }
        j++; 
    }
    while(top!=0){
        if(stack[top]!='('&&stack[top]!=')') 
        {hz[j++]=stack[top];cout<<stack[top]<<" ";}//输出算符
        top--;//剩余算符全部出栈
    }
    top=0;len=strlen(hz);
    int tot=0;
    for(int i=0;i<len;i++) {
        if(hz[i]=='+'||hz[i]=='*'||hz[i]=='-'||hz[i]=='^'||hz[i]=='/') tot++;//计算算符个数,确定计算次数; 
    }
    int head=0;j=0;
    cout<<endl;
    while(tot)
    {
        tot--;
        for(;head<len;head++)//头指针,指向算符,进行运算 (注意不要初始化,之后可以接着用)
        {
            if(hz[head]=='+'||hz[head]=='*'||hz[head]=='-'||hz[head]=='^'||hz[head]=='/')
            {
                int a=0,b=0;//寻找两个运算数
                int p=head-1;while(hz[p]=='.') p--;//找到第一个数字 
                int l=1;//存储一个数有多少位; 
                while(233&&p>=0)
                {
                    if(hz[p]=='.') break;//找到了退出
                    if(hz[p]=='-')
                    {a=-a;hz[p]='.';p--;break;}
                    a+=(hz[p]-'0')*l;
                    l*=10;
                    hz[p]='.';//使用过的标为空(就不往前挪了,浪费时间,也没必要) 
                    p--;
                }
                l=1;
                while(hz[p]=='.') p--;//找第二个数; 
                while(233&&p>=0)
                {
                    if(hz[p]=='.') break;
                    if(hz[p]=='-')
                    {b=-b;hz[p]='.';p--;break;}
                    b+=(hz[p]-'0')*l;l*=10;
                    hz[p]='.';
                    p--; 
                }
                int ans=doit(b,a,hz[head]);//后找到的数要放在前面!(因为是从后往前扫) 
                hz[head]='.';//标为空
                if(tot==0)
                {
                    cout<<ans<<endl;return 0;
                } 
                for(int q=0;q<len;q++)
                {
                    if(q==head) {cout<<ans<<" ";continue;}
                    if(hz[q]=='.') continue;
                    if(hz[q]=='-'&&q<=head) {
                        cout<<"-";continue;
                    }
                    if(hz[q]>='0'&&hz[q]<='9')
                    {
                        while(hz[q]>='0'&&hz[q]<='9'&&q<len)
                        {
                            cout<<hz[q];
                            q++;
                        }
                        cout<<" ";
                        q--;//for会加上去;
                    }
                    else cout<<hz[q]<<" ";
                }
                cout<<endl;

/*把数给填上去*****/

                bool fu=false;if(ans<0) {fu=true;ans*=-1;}
                if(ans==0){
                    hz[head-1]='0';
                }
                else
                {
                    int q;
                    for(q=head-1;hz[q-1]=='.'&&ans!=0;q--) 
                    {
                        hz[q]=ans%10+'0';
                        ans/=10;
                    }
                    if(fu==true){
                        hz[q]='-';
                    }
                }
                break;
            }
        }
    }
}
inline int doit(int x,int y,char how)//运算
{
    int sum=0;
    switch(how)
    {
        case '*':
            sum=x*y;return sum;
        case '-':
            sum=x-y;return sum;
        case '+':
            sum=x+y;return sum;
        case '/':
            sum=x/y;return sum;
        case '^':
            sum=1;
            for(int i=1;i<=y;i++)
            {
                sum*=x;
            }
            return sum;
        default: return 0;
    }
}