中缀式变前缀式后缀达式(文字加图解)

为了解释后缀表达式的好处,我们先来看看,计算机如何应用后缀表达式计算出最终的结果20的。

后缀表达式:9 3 1-3*+ 10 2/+

  • 规则:从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。

下面是详细的步骤:

1. 初始化一个空。此桟用来对要运算的数字进出使用。

2. 后缀表达式中前三个都是数字,所以9、3、1进栈。

3. 接下来是减号“-”,所以将栈中的1出栈作为减数,3出栈作为被减数,并运算3-1得到2,再将2进栈。

4. 接着是数字3进栈。

5. 后面是乘法“*”,也就意味着栈中3和2出栈,2与3相乘,得到6,并将6进栈。

6. 下面是加法“+”,所以找中6和9出找,9与6相加,得到15,将15进栈。

7. 接着是10与2两数字进栈。

8. 接下来是符号因此,栈顶的2与10出栈,10与2相除,得到5,将5进栈。

9. 最后一个是符号“+”,所以15与5出找并相加,得到20,将20进栈。

10. 结果是20出栈,栈变为空。

中缀变后缀:
#include <stdio.h>
#include <string.h>
char s[1000];
char a[1000];
int main()
{
    int i, n, len, e=0, j;
    memset(s, '\0', sizeof(s));
    scanf("%s", a);
    len = strlen(a);
    for(i=0; i<len-1; i++)
    {
        if(a[i]>='a'&&a[i]<='z')
            printf("%c", a[i]);
        else
        {
            if(e==0)
            {
                s[e++] = a[i];
            }
            else
            {
                if(a[i]=='(')
                {
                    s[e++] = a[i];
                }
                else if(a[i]=='+'||a[i]=='-')
                {
                    if(s[e-1]=='(')
                    {
                        s[e++] = a[i];
                    }
                    else if(s[e-1]=='*' || s[e-1]=='/' ||s[e-1]=='+' || s[e-1]=='-')
                    {
                        printf("%c", s[e-1]);
                        s[e-1] = a[i];
                    }
                }
                else if(a[i]=='*'||a[i]=='/')
                {
                    if(s[e-1]=='+' || s[e-1]=='-' || s[e-1]=='(')
                    {
                        s[e++] = a[i];
                    }
                    else if(s[e-1]=='*'||s[e-1]=='/')
                    {
                        printf("%c", s[e-1]);
                        s[e-1] = a[i];
                    }
                }
                else if(a[i]==')')
                {
                    for(j=e-1; j>=0; j--)
                    {
                        if(s[j]=='(')
                        {
                            e = j;
                            break;
                        }
                        printf("%c", s[j]);
                    }

                }
            }
        }
    }
    for(i=e-1; i>=0; i--)
    {
        printf("%c", s[i]);
    }
    printf("\n");
    return 0;
}

中缀表达式及后缀表达式图解

2015年08月13日 22:34:58

阅读数:3853

平常我们见到的四则运算表达式都是中缀表达式,这种表示方法适合人阅读,但是不适合计算机计算,因为乘除号出现在加减号的后面时可能要先计算后面的加减号,加上括号后就更加麻烦了。计算机可以通过逆波兰式来非常方便的实现计算。

计算机实现四则运算主要分两步进行:

  1. 将给定的中缀形式的表达式转换成后缀表达式形式
  2. 利用后缀表达式执行计算

下面是上面两个步骤的图解过程(这实际上是《大话数据结构》一书中的图解流程)

转载自:将中缀表达式转化为后缀表达式

                图解后缀表达式的计算过程

1、中缀表达式转后缀表达式

中缀表达式“9+(3-1)*3+10/2”转化为后缀表达式“9 3 1-3*+ 10 2/+”

规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于找顶符号(乘除优先加减)则栈顶元素依次出找并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。

下面我们来具体看看这个过程。

1. 初始化一空栈,用来对符号进出栈使用。

2. 第一个字符是数字9,输出9,后面是符号“+”,进栈。

3. 第三个字符是“(”,依然是符号,因其只是左括号,还未配对,故进栈。

4. 第四个字符是数字3,输出,总表达式为9 3,接着是“-”进栈。

5. 接下来是数字1,输出,总表达式为9 3 1,后面是符号“)”,此时,我们需要去匹配此前的“(”,所以栈顶依次出栈,并输出,直到“(”出栈为止。此时左括号上方只有“-”,因此输出“-”,总的输出表达式为9 3 1 -

6. 接着是数字3,输出,总的表达式为9 3 1 - 3 。紧接着是符号“*”,因为此时的栈顶符号为“+”号,优先级低于“*”,因此不输出,进栈。

7. 之后是符号“+”,此时当前栈顶元素比这个“+”的优先级高,因此栈中元素出栈并输出(没有比“+”号更低的优先级,所以全部出栈),总输出表达式为 9 3 1 - 3 * +.然后将当前这个符号“+”进栈。也就是说,前6张图的栈底的“+”是指中缀表达式中开头的9后面那个“+”,而下图中的栈底(也是栈顶)的“+”是指“9+(3-1)*3+”中的最后一个“+”。

8. 紧接着数字10,输出,总表达式变为9 3 1-3 * + 10。

9. 最后一个数字2,输出,总的表达式为 9 3 1-3*+ 10 2

10. 因已经到最后,所以将栈中符号全部出栈并输出。最终输出的后缀表达式结果为 9 3 1-3*+ 10 2/+

  • 从刚才的推导中你会发现,要想让计算机具有处理我们通常的标准(中缀)表达式的能力,最重要的就是两步:

  1. 将中缀表达式转化为后缀表达式(栈用来进出运算的符号)。
  2. 将后缀表达式进行运算得出结果(栈用来进出运算的数字)。

整个过程,都充分利用了找的后进先出特性来处理,理解好它其实也就理解好了栈这个数据结构。

2、后缀表达式求值

后缀表达式:9 3 1-3*+ 10 2/+

  • 规则:从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。

下面是详细的步骤:

1. 初始化一个空。此桟用来对要运算的数字进出使用。

2. 后缀表达式中前三个都是数字,所以9、3、1进栈。

3. 接下来是减号“-”,所以将栈中的1出栈作为减数,3出栈作为被减数,并运算3-1得到2,再将2进栈。

4. 接着是数字3进栈。

5. 后面是乘法“*”,也就意味着栈中3和2出栈,2与3相乘,得到6,并将6进栈。

6. 下面是加法“+”,所以找中6和9出找,9与6相加,得到15,将15进栈。

7. 接着是10与2两数字进栈。

8. 接下来是符号因此,栈顶的2与10出栈,10与2相除,得到5,将5进栈。

9. 最后一个是符号“+”,所以15与5出找并相加,得到20,将20进栈。

10. 结果是20出栈,栈变为空。

#include <stdio.h>
#include <string.h>
char s[1000];
char a[1000];
int main()
{
    int i, n, len, x, sum;
    scanf("%s", a);
    memset(s, '\0', sizeof(s));
    len = strlen(a);
    x = 0;
    sum = 0;
    for(i=0; i<len-1; i++)
    {
        if(a[i]>='0'&&a[i]<='9')
        {
            s[x++] = a[i]-48;
        }
        else
        {
            if(a[i]=='-')
            {
                sum = s[x-2] - s[x-1];
                s[x-2] = sum;
                x--;
            }
            else if(a[i]=='+')
            {
                sum = s[x-2] + s[x-1];
                s[x-2] = sum;
                x--;
            }
            else if(a[i]=='*')
            {
                sum = s[x-2] * s[x-1];
                s[x-2] = sum;
                x--;
            }
            else if(a[i]=='/')
            {
                sum = s[x-2]/s[x-1];
                s[x-2] = sum;
                x--;
            }
        }
    }
    printf("%d\n", sum);
    return 0;
}

3、中缀式转前缀式:

中缀转前缀

1+((2+3)×4)-5

遵循以下步骤:
(1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2;
(2) 从右至左扫描中缀表达式;


(3) 遇到操作数时,将其压入S2;


(4) 遇到运算符时,比较其与S1栈顶运算符的优先级:
(4-1) 如果S1为空,或栈顶运算符为右括号“)”,则直接将此运算符入栈;
(4-2) 否则,若优先级比栈顶运算符的较高或相等,也将运算符压入S1;
(4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;


(5) 遇到括号时:
(5-1) 如果是右括号“)”,则直接压入S1;
(5-2) 如果是左括号“(”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到右括号为止,此时将这一对括号丢弃;


(6) 重复步骤(2)至(5),直到表达式的最左边;


(7) 将S1中剩余的运算符依次弹出并压入S2;
(8) 依次弹出S2中的元素并输出,结果即为中缀表达式对应的前缀表达式。

#include <stdio.h>
#include <string.h>
char s[1000];
char s1[1000];
char s2[1000];
char s3[1000];
int main()
{
    int i, n, len, x1, x2, j;
    scanf("%s", s);
    len = strlen(s);
    memset(s1, 0, sizeof(s1));
    memset(s2, 0, sizeof(s2));
    x1 = 0;
    x2 = 0;
    for(i=len-2; i>=0; i--)
    {
        if(s[i]>='a'&&s[i]<='z')
        {
            s2[x2++] = s[i];
        }
        else if((s[i]=='+'||s[i]=='-')&&(s1[x1-1]=='*'||s1[x1-1]=='/'))
        {
            s2[x2++] = s1[x1-1];
            s1[x1-1] = s[i];
        }
        else if(s[i]=='(')
        {
            x1--;
            while(s1[x1]!=')')
            {
                s2[x2++] = s1[x1--];
            }
            s1[x1] = 0;
        }
        else
        {
            s1[x1++] = s[i];
        }
    }
    for(i=x1-1; i>=0; i--)
    {
        s2[x2++] = s1[i];
    }
    for(i=x2-1; i>=0; i--)
    {
        printf("%c", s2[i]);
    }
    printf("\n");

    for(i=0; i<len-1; i++)
    {
        if(s[i]!='('&&s[i]!=')')
            printf("%c", s[i]);
    }
    printf("\n");

    int e = 0;
    for(i=0; i<len-1; i++)
    {
        if(s[i]>='a'&&s[i]<='z')
            printf("%c", s[i]);
        else
        {
            if(e==0)
            {
                s3[e++] = s[i];
            }
            else
            {
                if(s[i]=='(')
                {
                    s3[e++] = s[i];
                }
                else if(s[i]=='+'||s[i]=='-')
                {
                    if(s3[e-1]=='(')
                    {
                        s3[e++] = s[i];
                    }
                    else if(s3[e-1]=='*' || s3[e-1]=='/' ||s3[e-1]=='+' || s3[e-1]=='-')
                    {
                        printf("%c", s3[e-1]);
                        s3[e-1] = s[i];
                    }
                }
                else if(s[i]=='*'||s[i]=='/')
                {
                    if(s3[e-1]=='+' || s3[e-1]=='-' || s3[e-1]=='(')
                    {
                        s3[e++] = s[i];
                    }
                    else if(s3[e-1]=='*'||s3[e-1]=='/')
                    {
                        printf("%c", s3[e-1]);
                        s3[e-1] = s[i];
                    }
                }
                else if(s[i]==')')
                {
                    for(j=e-1; j>=0; j--)
                    {
                        if(s3[j]=='(')
                        {
                            e = j;
                            break;
                        }
                        printf("%c", s3[j]);
                    }

                }
            }
        }
    }
    for(i=e-1; i>=0; i--)
    {
        printf("%c", s3[i]);
    }
    printf("\n");
    return 0;
}


 

猜你喜欢

转载自blog.csdn.net/weixin_42137874/article/details/81315522