题解 P1175 【表达式的转换】

· · 题解

这个题其实是个很麻烦的栈,坑点不多,但不坑点也很难搞。大体思路其实都懂,中序转后序,然后后序再慢慢算。第一部分我其实没怎么看懂楼下大佬,就简单讲讲吧。

第一部分:

由于保证输入数据数字是单位数所以可以用字符数组。

设有一个中序式:a+b*(c+d^e)/f-g

我们的原则是:如果栈顶符号优先级>=此时的符号,就弹出,(优先级最低

我们的栈,主要是用来储存符号的,为了方便,以下所指的输出,均为放入结果字符数组中。

首先读入a,可以直接输出。

其次读入+,放入栈(栈内:+)

在读入b,直接输出。

再读入,放入栈内,因为+优先级<(栈内:+*)

读入(,放入栈中,不进行任何操作,栈内:(+*()

读入c,直接输出

读入+,放入栈内(栈内:+*(+)

读入d,直接输出

读入^,放入栈内(注意:到目前为止,我们还未弹出栈内任何元素)(栈内:+*(^))

读入e,输出

读入(,原则:一直弹顺便输出,弹到(,(不输出 栈内:+*

后面如前面所示,最后将栈内所有元素,逆序输出(即由top到1)

好的,一直到这,我的想法都和楼下大佬一样,但是在计算过程中,我的会有所差异。

第二部分:

这时候,我们还需要一个栈,但不是储存符号了,而是运算结果(注意,并非输入的数据,而是结果)

如样例,我们的后序式是:8 3 2 6 * + 5 / - 4 + ,我们的储存方式是字符。

栈内一直读到第4位,已经变成了:8 3 2 6

但是到了*,我们需要对后两位进行运算,于是栈内变成了:8 3 12

请读者观察,我们需要输出时,一定是在运算时,对不对?很明显,我们此时进行了运算。那么输出的内容,首先,应当是栈内的内容,然后6和*已经运算完了,不需要输出,那么应该跳过这两个,然后把原先式子输出出来。那么这个2,并非意思跳过这两个,而是在6所跳的基础上,再跳两个。但是,如果这个位置需要多次跳跃,前面的跳跃格数已经不能满足他了,就必须自增2,那么式子,留给作者思考(其实程序会有qaq),那么如果他已经过去了这些东西,就需要从后面再计算了(此处表述可能不是太清楚),直到到了最后面。可能这样看不太明晰,那么画一个图可能就明白了。

输出必要性:1 1 1 1 1 1 1

运算完一遍后,一个可能的结果:

0 0 0 1 1 1 1

那么需要把栈内的输出一边(因为不可能有符号了),然后再把下面的输出一遍,即把必要性为1的输出一遍。

一直到全部为零为止。

表述不清,请见谅。 AC代码:

#include <iostream>
#include <cmath>
using namespace std;
char out[200],stac[200],ch;
int top,outsize,skip[200];
struct st{
    int num,mem;
}sta[200];
int main(){
    while(cin >> ch)
    {
        if(ch<='9'&&ch>='0')//num
        {
            outsize++;
            out[outsize]=ch;
        }
        if(ch=='+'||ch=='-')//+||-
        {
            while(top>0&&stac[top]!='(')
            {
                outsize++;
                out[outsize]=stac[top];
                top--;
            }
            top++;
            stac[top]=ch;
        }
        if(ch=='*'||ch=='/')
        {
            while(top>0&&stac[top]!='('&&stac[top]!='+'&&stac[top]!='-')//*||/
            {
                outsize++;
                out[outsize]=stac[top];
                top--;
            }
            top++;
            stac[top]=ch;
        }
        if(ch=='^')
        {
            while(top>0&&stac[top]=='^')
            {
                outsize++;
                out[outsize]=stac[top];
                top--;
            }
            top++;
            stac[top]=ch;
        }
        if(ch=='(')
        {
            top++;
            stac[top]=ch;
        }
        if(ch==')')
        {
            while(top>0&&stac[top]!='(')
            {
                outsize++;
                out[outsize]=stac[top];
                top--;
            }
            top--;
        }
    }
    while(top>0)
    {
        outsize++;
        out[outsize]=stac[top];
        top--;
    }
    for(int i=1;i<=outsize;i++)
    {
        cout << out[i] << " ";
        skip[i]=1;
    }
    cout << endl;
    int st=1;
    top=0;
    while(st<=outsize)
    {
        if(out[st]<='9'&&out[st]>='0')
        {
            top++;
            sta[top].mem=out[st]-'0';
            sta[top].num=st;
        }
        if(out[st]=='+')
        {
            sta[top-1].mem+=sta[top].mem;
            if(skip[top-1]-skip[top]>=2)
            {
                skip[top-1]+=2; 
            }
            else
            {
                skip[top-1]=skip[top]+2;
            }
            top--;
            for(int i=1;i<=top;i++)
            {
                cout << sta[i].mem << " ";
            }
            int j;
            for(j=st+1;j<=outsize;j++)
            {
                cout << out[j] << " ";
            }
            cout << endl;
        }
        if(out[st]=='-')
        {
            sta[top-1].mem-=sta[top].mem;
            if(skip[top-1]-skip[top]>=2)
            {
                skip[top-1]+=2; 
            }
            else
            {
                skip[top-1]=skip[top]+2;
            }
            top--;
            for(int i=1;i<=top;i++)
            {
                cout << sta[i].mem << " ";
            }
            int j;
            for(j=st+1;j<=outsize;j++)
            {
                cout << out[j] << " ";
            }
            cout << endl;
        }
        if(out[st]=='*')
        {
            sta[top-1].mem*=sta[top].mem;
            if(skip[top-1]-skip[top]>=2)
            {
                skip[top-1]+=2; 
            }
            else
            {
                skip[top-1]=skip[top]+2;
            }
            top--;
            for(int i=1;i<=top;i++)
            {
                cout << sta[i].mem << " ";
            }
            int j;
            for(j=st+1;j<=outsize;j++)
            {
                cout << out[j] << " ";
            }
            cout << endl;
        }
        if(out[st]=='/')
        {
            sta[top-1].mem/=sta[top].mem;
            if(skip[top-1]-skip[top]>=2)
            {
                skip[top-1]+=2; 
            }
            else
            {
                skip[top-1]=skip[top]+2;
            }
            top--;
            for(int i=1;i<=top;i++)
            {
                cout << sta[i].mem << " ";
            }
            int j;
            for(j=st+1;j<=outsize;j++)
            {
                cout << out[j] << " ";
            }
            cout << endl;
        }
        if(out[st]=='^')
        {
            sta[top-1].mem=pow(sta[top-1].mem,sta[top].mem);
            if(skip[top-1]-skip[top]>=2)
            {
                skip[top-1]+=2; 
            }
            else
            {
                skip[top-1]=skip[top]+2;
            }
            top--;
            for(int i=1;i<=top;i++)
            {
                cout << sta[i].mem << " ";
            }
            int j;
            for(j=st+1;j<=outsize;j++)
            {
                cout << out[j] << " ";
            }
            cout << endl;
        }
        st++;
    }
    return 0;
}

码量蛮大的,要有耐心