zoukankan      html  css  js  c++  java
  • 中国大学MOOC数据结构基础习题集、023、求前缀表达式的值

    首先粘一下题目:

    算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。前缀表达式指二元运算符位于两个运算数之前,例如2+3*(7-4)+8/4的前缀表达式是:+ + 2 * 3 - 7 4 / 8 4。请设计程序计算前缀表达式的结果值。

    输入格式说明:

    输入在一行内给出不超过30个字符的前缀表达式,只包含+、-、*、\以及运算数,不同对象(运算数、运算符号)之间以空格分隔。

    输出格式说明:

    输出前缀表达式的运算结果,精确到小数点后1位,或错误信息“ERROR”。

    样例输入与输出:

    序号 输入 输出
    1
    + + 2 * 3 - 7 4 / 8 4
    
    13.0
    
    2
    / -25 + * - 2 3 4 / 8 4
    
    12.5
    
    3
    / 5 + * - 2 3 4 / 8 2
    
    ERROR
    
    4
    +10.23
    
    10.2

    这里就不按照惯例给出建议的测试用例了,直接用题目中给的4个就可以了。

    先说一下我的解题思路吧:

    1. 首先要处理输入的数据,这里用到的数据结构有string data和stack<double>myStack,stack<int>intStack。string data要用getline()函数读入一整行字符串,如果直接用cin的话遇到空格读入会停止的。myStack用来存放中间结果,intStack用来存放读入“数字”字符。len是输入字符串的长度,dotPos记录了小数点的位置。

    1     string data;
    2     stack<double> myStack;
    3     stack<int> intStack;
    4     int len = data.size();
    5     int dotPos = 0;
    6     getline(cin, data);

    2. 接下来要用到for循环,从后向前的处理每一个字符。

    1    for (int i=len-1; i!=-1; i--)
    2     {

    3. 第一个if语句,用来判断是不是小数点,并且更新小数点位置dotPos。

    1         if(data[i]=='.')
    2         {
    3             dotPos = intStack.size();
    4             continue;
    5         }

    4. 第二个if语句,用来判断是不是+ - * /,并且如果要是+ -还要考虑他们是一元运算符(表示正负),还是二元运算符(表示加减)。

    1         if(data[i]=='+' || data[i]=='-' || data[i]=='*' || data[i]=='/')
    2         {

    4.1 如果是一元运算符-(表示负),首先要从intStack中弹出全部的数字,把它们“拼接”成一个完整的整数(见while循环)。同时还要考虑这个数是整数,还是小数,那么之前的dotPos就用到了(见if语句)。只需要判断dotPos是不是0就可以了:如果是0,说明它是一个整数。如果不是0,说明它是一个浮点数。将小数点向前移动dotPos位,也就是除以10的dotPos次方。同时把这个数字乘以-1,压入myStack栈中。具体的代码如下:

     1             if(data[i]=='-' && intStack.size()!=0)
     2             {
     3                 int icount = 0;
     4                 double itemp = 0;
     5                 int ilen = intStack.size();
     6                 while(intStack.size() != 0)
     7                 {
     8                     int inttemp = intStack.top();
     9                     intStack.pop();
    10                     itemp += pow(10, ilen - 1 - icount) * inttemp;
    11                     icount ++;
    12                 }
    13                 itemp *= -1;
    14                 if(dotPos == 0)
    15                     myStack.push(itemp);
    16                 else
    17                 {
    18                     myStack.push(itemp / pow(10, dotPos));
    19                     dotPos = 0;
    20                 }
    21                 continue;
    22             }

    4.2 判断是一元运算符+(表示正),方法和上面几乎完全相同,只不过是少乘以一个-1就可以了,代码如下:

     1             else if(data[i]=='+' && intStack.size()!=0)
     2             {
     3                 int icount = 0;
     4                 double itemp = 0;
     5                 int ilen = intStack.size();
     6                 while(intStack.size() != 0)
     7                 {
     8                     int inttemp = intStack.top();
     9                     intStack.pop();
    10                     itemp += pow(10, ilen - 1 - icount) * inttemp;
    11                     icount ++;
    12                 }
    13                 if(dotPos == 0)
    14                     myStack.push(itemp);
    15                 else
    16                 {
    17                     myStack.push(itemp / pow(10, dotPos));
    18                     dotPos = 0;
    19                 }
    20                 continue;
    21             }

      Tips:这里鼓励大家,尝试把两段代码捏在一起,这样能节约代码的行数。不妨试试看。

    4.3 接下来就是判断二元运算符了,因为二元运算符必须要两个操作数,因此如果myStack栈中的数字少于两个,那么肯定就是ERROR了。同样,如果除法运算的除数是0,那肯定也是ERROR。进行+ - * /之后,不要忘记把结果压入myStack栈中。这部分比较简单,代码如下:

     1             else if(myStack.size() < 2)
     2             {
     3                 cout << "ERROR" << endl;
     4                 return 0;
     5             }
     6             double a = myStack.top();
     7             myStack.pop();
     8             double b = myStack.top();
     9             myStack.pop();
    10             double r = 0;
    11             switch(data[i])
    12             {
    13             case '+':
    14                 r = a + b;
    15                 break;
    16             case '-':
    17                 r = a - b;
    18                 break;
    19             case '*':
    20                 r = a * b;
    21                 break;
    22             case '/':
    23                 r = a / b;
    24                 {
    25                     if (b != 0)
    26                         r = a / b;
    27                     else
    28                     {
    29                         cout << "ERROR" << endl;
    30                         return 0;
    31                     }
    32                 }
    33                 break;
    34             }
    35             myStack.push(r);
    36             continue;
    37         }            

    5. 第3个if语句,用来判断是不是空格,即' ',如果是空格的话,之前intStack栈中的数字,要全部弹出,组成一个新的数字,压入myStack栈中。方法其实上面已经有了。可以自己尝试写一下。代码如下:

     1         if(data[i]==' ')
     2         {
     3             int icount = 0;
     4             double itemp = 0;
     5             int ilen = intStack.size();
     6             while(intStack.size() != 0)
     7             {
     8                 int inttemp = intStack.top();
     9                 intStack.pop();
    10                 itemp += pow(10, ilen - 1 - icount) * inttemp;
    11                 icount ++;
    12             }
    13             if(ilen != 0)
    14             {
    15                 if(dotPos == 0)
    16                     myStack.push(itemp);
    17                 else
    18                 {
    19                     myStack.push(itemp / pow(10, dotPos));
    20                     dotPos = 0;
    21                 }
    22             }
    23             continue;
    24         }

    6. 第4个if语句,用来判断是不是'0'到'9',如果是的话,压入intStack栈中。注意压栈的时候要减掉'0'哦。因为data[i]可是字符。

    1         if(data[i]>='0' && data[i]<='9')
    2         {
    3             intStack.push(data[i]-'0');
    4             continue;
    5         }
    6     }

    7. 输出结果,就是myStack栈中的那一个元素了。

    1     printf("%.1lf", myStack.top());
    2     return 0;
    3 }

    8. 完整代码如下:

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <iostream>
      4 #include <iomanip>
      5 #include <stack>
      6 #include <cmath>
      7 
      8 using namespace std;
      9 int main()
     10 {
     11     string data;
     12     stack<double> myStack;
     13     stack<int> intStack;
     14     int len = data.size();
     15     int dotPos = 0;
     16     getline(cin, data);
     17     for (int i=len-1; i!=-1; i--)
     18     {
     19         if(data[i]=='.')
     20         {
     21             dotPos = intStack.size();
     22             continue;
     23         }
     24         if(data[i]=='+' || data[i]=='-' || data[i]=='*' || data[i]=='/')
     25         {
     26             if(data[i]=='-' && intStack.size()!=0)
     27             {
     28                 int icount = 0;
     29                 double itemp = 0;
     30                 int ilen = intStack.size();
     31                 while(intStack.size() != 0)
     32                 {
     33                     int inttemp = intStack.top();
     34                     intStack.pop();
     35                     itemp += pow(10, ilen - 1 - icount) * inttemp;
     36                     icount ++;
     37                 }
     38                 itemp *= -1;
     39                 if(dotPos == 0)
     40                     myStack.push(itemp);
     41                 else
     42                 {
     43                     myStack.push(itemp / pow(10, dotPos));
     44                     dotPos = 0;
     45                 }
     46                 continue;
     47             }
     48             else if(data[i]=='+' && intStack.size()!=0)
     49             {
     50                 int icount = 0;
     51                 double itemp = 0;
     52                 int ilen = intStack.size();
     53                 while(intStack.size() != 0)
     54                 {
     55                     int inttemp = intStack.top();
     56                     intStack.pop();
     57                     itemp += pow(10, ilen - 1 - icount) * inttemp;
     58                     icount ++;
     59                 }
     60                 if(dotPos == 0)
     61                     myStack.push(itemp);
     62                 else
     63                 {
     64                     myStack.push(itemp / pow(10, dotPos));
     65                     dotPos = 0;
     66                 }
     67                 continue;
     68             }
     69             else if(myStack.size() < 2)
     70             {
     71                 cout << "ERROR" << endl;
     72                 return 0;
     73             }
     74             double a = myStack.top();
     75             myStack.pop();
     76             double b = myStack.top();
     77             myStack.pop();
     78             double r = 0;
     79             switch(data[i])
     80             {
     81             case '+':
     82                 r = a + b;
     83                 break;
     84             case '-':
     85                 r = a - b;
     86                 break;
     87             case '*':
     88                 r = a * b;
     89                 break;
     90             case '/':
     91                 r = a / b;
     92                 {
     93                     if (b != 0)
     94                         r = a / b;
     95                     else
     96                     {
     97                         cout << "ERROR" << endl;
     98                         return 0;
     99                     }
    100                 }
    101                 break;
    102             }
    103             myStack.push(r);
    104             continue;
    105         }
    106         if(data[i]==' ')
    107         {
    108             int icount = 0;
    109             double itemp = 0;
    110             int ilen = intStack.size();
    111             while(intStack.size() != 0)
    112             {
    113                 int inttemp = intStack.top();
    114                 intStack.pop();
    115                 itemp += pow(10, ilen - 1 - icount) * inttemp;
    116                 icount ++;
    117             }
    118             if(ilen != 0)
    119             {
    120                 if(dotPos == 0)
    121                     myStack.push(itemp);
    122                 else
    123                 {
    124                     myStack.push(itemp / pow(10, dotPos));
    125                     dotPos = 0;
    126                 }
    127             }
    128             continue;
    129         }
    130         if(data[i]>='0' && data[i]<='9')
    131         {
    132             intStack.push(data[i]-'0');
    133             continue;
    134         }
    135     }
    136     printf("%.1lf", myStack.top());
    137     return 0;
    138 }

    个人分析:

      按照老师的说法,这是一道可以尝试挑战一下自己的题。测试用例还是比较简单的,基本上给的4个都能过的话,肯定能AC。毕竟限制了30个字符的大小,不像PAT1074(即MOOC作业2-1)数据量那么大。

    最后粘一下AC的结果:

  • 相关阅读:
    maven安装以及eclipse配置maven
    jquery 图片文件转base64 显示
    Java 解析Excel文件为JSON
    Dropwizard框架入门
    使用Spring Security和OAuth2实现RESTful服务安全认证
    SQL语句大小写是否区分的问题,批量修改整个数据库所有表所有字段大小写
    13个可实现超棒数据可视化效果的Javascript框架
    C#创建数字证书并导出为pfx,并使用pfx进行非对称加解密
    C#使用RSA证书文件加密和解密示例
    C# 中使用 RSA加解密算法
  • 原文地址:https://www.cnblogs.com/clevercong/p/4171910.html
Copyright © 2011-2022 走看看