201903-2二十四点


前言

这是一道表达式求值的题目,而且还是简单类型的,上学期老师也有给我们不知过这样的作业,要求比这题还要难一点。但是,在我做的时候,我却傻傻分不清四种运算符的优先级,总是搞乱了。所以,我觉得,我还是有必要写写这一道题的。

题目(带测试样例)

题目链接附上:二十四点

这里同样给出题目的截图:

image-20211204193010243

测试样例

10
9+3+4x3
5+4x5x5
7-9-9+8
5x6/5x4
3+5+7+9
1x1+9-9
1x9-5/9
8/5+6x9
6x7-3x6
6x4+4/5

思路

这个题目是用来做的,我的做法是建立一个数字栈和一个符号栈。然后下面我来讲讲我的思路

首先,我们得到的是一个字符串,那么我们要怎样对它就行计算呢?那肯定就要进行转换呀!数字字符就转成我们的数字类型,符号字符就转成我们能操作的运算符类型,这个应该是不用讲的了。那么,我们来关心一下,我们要怎样进行运算呢?

我们回想一下,我们小时候学加减乘除时是不是有一个优先级?比如说先乘除再加减,同级运算从左到右进行·······

好,我们只有四种运算,这两条规则就够了。

我们先把字符串读进来,然后对它进行分析,是数字的话就压进数字栈,是符号的话就压进符号栈,不过,在压符号的时候,我们要注意些什么?没错,注意它的优先级。如果当前的字符的优先级比栈顶元素的低,那我是不是要先把前面的运算执行完了才能压入该符号?为什么?

举个例子,2*3+1,此时,我们判断+该不该压进堆栈,显然不能,因为如果压进堆栈的话,那么我们进行运算的时候是不是会先算3+1?那这就不是我们的正确运算法则了。我们的法则是先乘除,后加减,同级运算从左到右进行,也就是说,就算是同级,我们前面压进的字符也要比你后面压进的字符优先级要高,所以你后面的字符要压进来的话,你要先等我前面的运算完才可以进栈。

好,这样子,我们可以整出一个优先级的表,这个表应该还有更多的符号,我这里只是为了解这一道题,只给出以下四种,等我有时间了在补充写一写表达式求值的内容,到时后再将他们补全吧。

a\b + - * /
+ > > < <
- > > < <
* > > > >
/ > > > >

表格中的a代表栈顶符号,b代表当前要压入的符号

这样,我们观察表格就会知道,只有到要压进的符号为*或者/的时候,它才能直接压进去,否则都要将里面有的符号先弹出计算才能压进去。这是一个很好的规律,帮助我们减少代码量。

好,既然已经分析到这里了,我想我们可以动手写代码了。代码里也有相应的注释,不懂的朋友可以看一看代码。

代码

/* 二十四点 */
#include 
using namespace std;
/* 运算操作 */
int operate(int a, char b, int c) {
    if (b == '+') return a + c;
    if (b == '-') return a - c;
    if (b == 'x') return a * c;
    if (b == '/') return a / c;
}

int n;
int main() {
    cin >> n;
    stack a;
    stack b;
    while (n--) {
        string str;
        cin >> str;
        int len = str.length();
        for (int i = 0; i < len; i++) {
            if (isdigit(str[i])) {                                    //如果是数字,压进数字栈
                a.push(str[i] - '0');
            } else {
                if (b.empty())       //字符栈为空的话直接压栈
                    b.push(str[i]);
                else if ((b.top() == '+' || b.top() == '-') &&        //如果是字符,判断优先级,如果是特殊的那种情况,直接压栈
                         (str[i] == 'x' || str[i] == '/')) {
                    b.push(str[i]);

                } else {                                              //否则先计算前面的
                    int num2 = a.top();
                    a.pop();
                    int num1 = a.top();
                    a.pop();
                    char c = b.top();
                    b.pop();
                    int num = operate(num1, c, num2);
                    a.push(num);
                    b.push(str[i]);
                }
            }
        }
        while (!b.empty()) {                                      //将堆栈里面的符号全部拿出来计算
            int num2 = a.top();
            a.pop();
            int num1 = a.top();
            a.pop();
            char c = b.top();
            b.pop();
            int num = operate(num1, c, num2);
            a.push(num);
        }
        if (a.top() == 24)
            cout << "Yes" << endl;
        else
            cout << "No" << endl;
        a.pop();
    }
    return 0;
}

写在最后

这道题的表达式求值还是很简单的一种形式,推荐大家去把全部的符号都考虑进去,比如括号这些,博主因为时间有限,就不写了(明天就要考试了,五五)。以后有时间的话再来补充表达式求值的内容吧。好,那这道题就到这里,谢谢您的阅读哦。