2018数据结构期末考试·2·后缀表达式计算并且转化为中缀表达式

【问题描述】

        从控制台输入一合法的后缀表达式,其中的运算符只包括+、-、*、/,运算数都是 大于等于 0 的整数(除数不为零),按要求输出计算结果,或输出计算结果和相对 应的中缀表达式。输出中缀表达式时只包含最少数目的圆括号(即在生成的中缀表 达式中若去掉一对括号,则其将不能够转换回输入的后缀表达式)。

        输出计算结果时,小数点后保留两位,例如:10/3 的结果为 3.33。假如输入的后缀表达式为: 100 25 + 27 25 - / 248 + 201 - 其相对应的中缀表达式为: (100+25)/(27-25)+248-201 计算结果为 109.50。

【输入形式】

        首先从控制台输入一个合法的后缀表达式(长度不超过 200 个字符),其中的运算 符、运算数之间都以一个空格分隔。然后在下一行输入一个整数 1 或 2 表示计算要 求(1 表示只输出计算结果;2 表示输出对应的中缀表达式和计算结果)。

【输出形式】

        若输入的计算要求为 1,则只将计算结果输出到控制台,小数点后保留两位;若输 入的计算要求为 2,则先将后缀表达式对应的中缀表达式输出到控制台(其中添加 的小括号都为英文小括号,表达式中不包含任何空白符),然后在下一行输出计算 结果,小数点后保留两位。

【样例 1 输入】

        100 25 + 27 25 - / 248 + 201 - 1

【样例 1 输出】

        109.50

【样例 2 输入】

        100 25 + 27 25 - / 248 + 201 - 2

【样例 2 输出】

         (100+25)/(27-25)+248-201109.50

【样例 1 和 2 说明】

        两样例输入了相同的后缀表达式。按计算要求,样例 1 只输出 了计算结果;样例 2 输出了转换后的(包含最少括号的)中缀表达式和计算结果。 按照后缀表达式的计算语义,当转换为中缀表达式时,前两个运算符连成的表达式 100+25 和 27-25 都要加上小括号。 【样例 3 输入】 100 25 + 2 58 42 + * / 2

【样例 3 输出】

        (100+25)/(2*(58+42)) 0.63

【样例 3 说明】

        按照后缀表达式的计算语义,生成中缀表达时表达式 2*(58+42)外 应该加上小括号,否则两个表达式计算顺序不一致。

        后缀转中缀算法提示: 1、每步进行后缀表达式计算时,除了要保存计算结果外, 还应保存对应的(以字符串形式表示的)运算符和中缀表达式。 2、在进行后缀表达式计算时,当前运算符的优先级大于左运算对象运算符优先级, 则生成对应的中缀表达式时左运算对象对应的中缀表达式应加括号;当前运算符的 优先级大于或等于右运算对象运算符优先级时,则生成对应的中缀表达式时右运算 对象对应的中缀表达式应加括号。其它情况则不用加括号。

        以样例 2 为例,在进行 后缀表达式计算时:

         • 第一次进行'+'运算时,左运算对象为 100,右为 25,运算结果为 125、运 算符为'+'、对应中缀表达式为 100+25;

         • 第二次进行'-'运算时,左运算对象为 27,右为 25,运算结果为 2、运算符 为'-'、对应中缀表达式为 27-25;

         • 第三次进行'/'运算时,左运算对象为 125、对应运算符为'+'、对应中缀表 达式为 100+25,由于'/'优先级高于'+',因此生成对应中缀表达式时 100+25 应加括号;右运算对象为 2、对应运算符为'-'、对应中缀表达式为 27-25, 由于'/'优先级高于'-',因此生成对应中缀表达式时 27-25 也应加括号。 该步运算结果为 62.5、运算符为'/'、对应中缀表达式为(100+25)/(27-25);

        • 以此类推

这题放在第二题属实是有点不当人,yysy比第三题难多了。 

不过这题的评分标准是能够计算出结果给2/3的分,转化中缀之占1/3。考试的时候,如果不是足够佬的话,建议写完2/3赶紧跑(反正是我这种蒟蒻就跑了

1·长篇大论的算法分析

我写这道题的代码风格极其差劲,全在main函数里面,写了两百行,所以可读性极其差,也不能够分段给出步骤,所以就用自然语言描述一下过程。

首先,这个题目要用栈(废话),而且是两个:一个double类型,记录表达式的值,一个用char*类型,记录表达式内容。而且这两个栈的操作是完全一致的:遇到数字入栈;遇到运算符,pop两次,进行对应的运算/表达式组合,再将结果push。所以选择把两个一起处理。

我们先不讨论加括号(反正我的多线程能力是不支持自己一次弄这么多的),来一个又臭又长的分情况讨论:

一个一个从缓冲区读取字符:

        ·空格跳过

        ·数字:继续读取完整的数字,然后入栈

        ·符号:a出栈,b出栈,然后运算b op a(op是符号类型对应的运算)注意是后出栈的b在前。

处理完以后,输入栈顶(0号)即可。

然后是括号的处理:

注意到题中所说的:如果运算符优先级大于左边运算符的优先级,大于等于右边运算符的优先级,就需要加括号,举个例子:

组合 a+b   *   c的时候就需要变成(a+b)*c

组合a  *  b+c和a   *    b*c的时候,都要加括号。

所以一开始我的想法是,搜索左边有没有+ -出现,如果有就加括号;搜索右边有没有+ - * /出现,有的话也加括号。然后写完一溜烟滚回去洗澡了

然鹅就在洗澡的时候我突然发现)这样不能处理一种情况:如果是(a+b)*(c+d)    *     e,其实前面并不要加括号,但是这种处理方式却给他加了括号。所以还要在寻找+号的时候添加一个条件:不考虑括号里面的符号,也就是说遇到括号直接跳过去。这样就可以处理了。

其实仔细一想,还是不该偷懒,在处理上一步的时候,用一个结构体记录一下这个表达式的计算类型也不会麻烦到哪去,出错的概率就比这个小多了,因为是严格按照规则来的。所以说:不是算法大佬,不要偷懒!!!

2·更臭更长的代码^ ^

yysy,虽然长,但是重复部分多,都是面向(ctrl)CV编程。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

double num_stack[100];
int ntop = -1;
char exp_stack[100][100];
int etop = -1;

int main()
{
    char c;
    while (~scanf("%c", &c))
    {
        if (c == ' ')
            continue;
        else if (c >= '0' && c <= '9')
        {
            char tmp[10];
            int num = 0;
            int tcnt = 0;
            tmp[tcnt++] = c;
            num = c - '0';
            scanf("%c", &c);
            while (c >= '0' && c <= '9')
            {
                tmp[tcnt++] = c;
                //tcnt++;
                num = num * 10 + c - '0';
                scanf("%c", &c);
            }
            tmp[tcnt] = '\0';
            num_stack[++ntop] = (double)num;
            strcpy(exp_stack[++etop], tmp);
            continue;
        }
        else if (c == '+')
        {

            double a = num_stack[ntop--];
            double b = num_stack[ntop--];
            double tn = b + a;
            num_stack[++ntop] = tn;

            char ea[100], eb[100], et[100];
            strcpy(ea, exp_stack[etop--]);
            strcpy(eb, exp_stack[etop--]);
            int i = 0;
            for (int j = 0; j < strlen(eb); j++)
            {
                et[i++] = eb[j];
            }
            et[i++] = '+';
            for (int j = 0; j < strlen(ea); j++)
            {
                et[i++] = ea[j];
            }
            et[i] = '\0';
            strcpy(exp_stack[++etop], et);
        }
        else if (c == '-')
        {
            double a = num_stack[ntop--];
            double b = num_stack[ntop--];
            double tn = b - a;
            num_stack[++ntop] = tn;

            char ea[100], eb[100], et[100];
            strcpy(ea, exp_stack[etop--]);
            strcpy(eb, exp_stack[etop--]);
            int i = 0;
            for (int j = 0; j < strlen(eb); j++)
            {
                et[i++] = eb[j];
            }
            et[i++] = '-';
            for (int j = 0; j < strlen(ea); j++)
            {
                et[i++] = ea[j];
            }
            et[i] = '\0';
            strcpy(exp_stack[++etop], et);
        }
        else if (c == '*')
        {
            double a = num_stack[ntop--];
            double b = num_stack[ntop--];
            double tn = b * a;
            num_stack[++ntop] = tn;

            char ea[100], eb[100], et[100];
            strcpy(ea, exp_stack[etop--]);
            strcpy(eb, exp_stack[etop--]);

            int flagb = 0;
            for (int k = 0; k < strlen(eb); k++)
            {
                if (eb[k] == '(')
                {
                    while (eb[k] != ')')
                    {
                        k++;
                    }
                }
                if (eb[k] == '+' || eb[k] == '-')
                {
                    flagb = 1;
                    break;
                }
            }

            int i = 0;

            if (flagb == 1)
                et[i++] = '(';

            for (int j = 0; j < strlen(eb); j++)
            {
                et[i++] = eb[j];
            }

            if (flagb == 1)
                et[i++] = ')';

            et[i++] = '*';

            int flaga = 0;
            for (int k = 0; k < strlen(ea); k++)
            {
                if (ea[k] == '(')
                {
                    while (ea[k] != ')')
                    {
                        k++;
                    }
                }
                if (ea[k] == '+' || ea[k] == '-' || ea[k] == '*' || ea[k] == '/')
                {
                    flaga = 1;
                    break;
                }
            }

            if (flaga == 1)
                et[i++] = '(';
            for (int j = 0; j < strlen(ea); j++)
            {
                et[i++] = ea[j];
            }
            if (flaga == 1)
                et[i++] = ')';
            et[i] = '\0';
            strcpy(exp_stack[++etop], et);
        }
        else if (c == '/')
        {
            double a = num_stack[ntop--];
            double b = num_stack[ntop--];
            double tn = b / a;
            num_stack[++ntop] = tn;

            char ea[100], eb[100], et[100];
            strcpy(ea, exp_stack[etop--]);
            strcpy(eb, exp_stack[etop--]);

            int flagb = 0;
            for (int k = 0; k < strlen(eb); k++)
            {
                if (eb[k] == '(')
                {
                    while (eb[k] != ')')
                    {
                        k++;
                    }
                }
                if (eb[k] == '+' || eb[k] == '-')
                {
                    flagb = 1;
                    break;
                }
            }

            int i = 0;

            if (flagb == 1)
                et[i++] = '(';

            for (int j = 0; j < strlen(eb); j++)
            {
                et[i++] = eb[j];
            }

            if (flagb == 1)
                et[i++] = ')';

            et[i++] = '/';

            int flaga = 0;
            for (int k = 0; k < strlen(ea); k++)
            {
                if (ea[k] == '(')
                {
                    while (ea[k] != ')')
                    {
                        k++;
                    }
                }
                if (ea[k] == '+' || ea[k] == '-' || ea[k] == '*' || ea[k] == '/')
                {
                    flaga = 1;
                    break;
                }
            }

            if (flaga == 1)
                et[i++] = '(';
            for (int j = 0; j < strlen(ea); j++)
            {
                et[i++] = ea[j];
            }
            if (flaga == 1)
                et[i++] = ')';
            et[i] = '\0';
            strcpy(exp_stack[++etop], et);
        }
    }
    printf("%.2f\n%s", num_stack[0], exp_stack[0]);
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值