zoukankan      html  css  js  c++  java
  • HDU1237 简单计算器 栈

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1237
    题目大意:读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。
    题目分析:
    我们可以利用栈来解决这道问题。
    首先,对于我们来说,这道题目比较简单,没有用到小括号。
    对于遇到小括号的情况,我们可能会用递归来实现“有小括号先求小括号里面的”的效果。
    但是因为这里没有,所以我们只需要处理“加减乘除”就可以了,
    可以发现,“加减”是一类的;“乘除”是一类的。
    所以我们可以这么做:
    我们开两个栈:stack1和stack2,stack1用于存放数字,stack2用于存放符号(+或-),
    首先,我们把公式中的第一个数字放入stack1中,
    接下来我们每次处理一个符号c和一个数字a,
    如果c是乘号或者除号,那么我们只需要取出stack1中的栈顶元素b,然后将 a*b 或者 a/b 的结果在放入stack中即可。
    如果c是加号或者减号,那么我们要判断一下此时stack1中的元素个数,
    如果stack1中只有一个元素,那么我们将a放入stack1中,将c放入stack2中,因为对于a来说,他的下一步运算很有可能是乘除运算,
    所以还是需要将此时的a留在栈顶以北接下来的运算的。
    如果stack1中有两个元素,而此时的符号是加号或者减号,那就是说,我新加进来的以a开头的部分,最终是要和他前面的这两个stack1中的元素做加减运算的。
    那么我们就可以先将stack1中的两个元素先合并了,那么我们假设:
    先从stack1中出来的是num1(这个num1是表达式中靠后的元素,因为栈是“后进先出”),
    后从stack1中出来的是num2(这个num2是表达式中靠前的元素),
    而stack2中取出的元素是c的话,
    如果c是+,则我们将num2+num1重新放入stack1中;
    如果c是-,则我们将num2-num1重新放入stack1中。
    我们按照这样的方式一直进行到遍历完整个表达式。
    此时stack1中可能存在一个元素,也可能还存在两个元素,
    那么在存在两个元素的情况下,我们可以知道,这两个元素肯定是加减运算的,因为我们不将乘除号放入stack2中,只将加减号放入stack2中。所以我们只需要进行一下上述的过程就可以将stack1中的元素变成一个了。
    那么最终的结果就是stack1中剩余的这唯一一个元素。
    其他
    这道题目有一个要注意的地方就是他是以0为单独一行结尾就算输入结束了。
    但是表达式的第一个元素也有可能是0,所以我就是因为没有处理这个导致WA了两次,所以对于输入数据的处理请注意避坑。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    stack<double> stk1, stk2;
    // stk1用于存放数字,stk2用于存放符号,
    // 因为stk2里面的符号只可能是+或-,所以用1表示+,用-1表示-
    
    double a;
    char c;
    
    int main() {
        while (~scanf("%lf", &a)) {
            // if (a == 0) break;
            while (!stk1.empty()) stk1.pop();
            while (!stk2.empty()) stk2.pop();
            stk1.push(a);
            bool eofFlag = true;
            while ((c = getchar()) != '
    ') {
                eofFlag = false;
                scanf("%c %lf", &c, &a);
                double b;
                switch (c) {
                    case '*':
                        b = stk1.top();
                        stk1.pop();
                        stk1.push(b * a);
                        break;
                    case '/':
                        b = stk1.top();
                        stk1.pop();
                        stk1.push(b / a);
                        break;
                    default:
                        if (stk1.size() == 2) { // 其实是==2就行
                            double num1 = stk1.top();
                            stk1.pop();
                            double num2 = stk1.top();
                            stk1.pop();
                            double flag = stk2.top();
                            stk2.pop();
                            stk1.push(num2 + flag * num1);
                        }
                        stk1.push(a);
                        stk2.push( c == '+' ? 1 : -1 );
                        break;
                }
            }
            if (eofFlag) { return 0; }
            if (stk1.size() == 2) {
                double num1 = stk1.top();
                stk1.pop();
                double num2 = stk1.top();
                stk1.pop();
                double flag = stk2.top();
                stk2.pop();
                stk1.push( num2 + flag * num1 );
            }
            double res = stk1.top();
            printf("%.2lf
    ", res);
        }
        return 0;
    }
    

    另外,我还碰到一道除了加减乘除还有小括号的题目,这道题目就是递归处理一下,每一个子部分还是不带小括号的,下面是样例代码。
    不过下面的样例代码在输入部分是没有空格的,比如下面是一组样例数据:

    样例输入:

    1.000+2/4=
    

    样例输出:

    1.50
    

    实现代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    string finalHandle(string s) {
        stringstream ss(s);
        double a;
        char c;
        stack<double> stk1, stk2;
        ss >> a;
        stk1.push(a);
        while (ss >> c) {
            if (c == '=') break;
            ss >> a;
            double b;
            switch (c) {
                case '*':
                    b = stk1.top();
                    stk1.pop();
                    stk1.push(b * a);
                    break;
                case '/':
                    b = stk1.top();
                    stk1.pop();
                    stk1.push(b / a);
                    break;
                default:
                    if (stk1.size() == 2) { // 其实是==2就行
                        double num1 = stk1.top();
                        stk1.pop();
                        double num2 = stk1.top();
                        stk1.pop();
                        double flag = stk2.top();
                        stk2.pop();
                        stk1.push(num2 + flag * num1);
                    }
                    stk1.push(a);
                    stk2.push( c == '+' ? 1 : -1 );
                    break;
            }
        }
        if (stk1.size() == 2) {
            double num1 = stk1.top();
            stk1.pop();
            double num2 = stk1.top();
            stk1.pop();
            double flag = stk2.top();
            stk2.pop();
            stk1.push( num2 + flag * num1 );
        }
        double res = stk1.top();
        stringstream sss;
        sss << res;
        string resString;
        sss >> resString;
        return resString;
    }
    
    string handle(string s) {
        // cout << s << endl;
        int idx1 = -1, idx2 = -1;
        for (int i = 0; i < s.length(); i ++) {
            if (s[i] == '(') idx1 = i;
            else if (s[i] == ')') {
                idx2 = i;
                break;
            }
        }
        if (idx1 != -1 && idx2 != -1)
            return handle(s.substr(0, idx1) + finalHandle(s.substr(idx1+1, idx2-idx1-1) + '=') + s.substr(idx2+1));
        else
            return finalHandle(s);
    }
    
    string s;
    
    int main() {
        cin >> s;
        string resString = handle(s);
        stringstream ss(resString);
        double res;
        ss >> res;
        printf("%.2lf
    ", res);
        // test
        // finalHandle(s);
        return 0;
    }
    /*
    1+2/3*(1+3)+(3*2+5-(1+8*3-7))
    */
    
    
  • 相关阅读:
    第七十四节,css边框与背景
    php中strlen和{}的效率对比
    for循环++i效率
    php优化技巧
    mysql中group_concat函数用法
    mysql引擎互转问题
    array_column php 函数
    php-mysql结果集函数比较
    javaweb 要学习的东西
    Java 泛型和类型安全的容器
  • 原文地址:https://www.cnblogs.com/zifeiy/p/10839036.html
Copyright © 2011-2022 走看看