スタックを用いた中置・後置数式の評価

中置表現の評価(括弧付き)

中置表現を直接評価するには、演算子の優先順位と括弧の処理を正しく扱う必要がある。以下の実装では、2つのスタック(数値用と演算子用)を用いて、入力文字列を1パスで処理する。

#include <bits/stdc++.h>
using namespace std;

stack<int> nums;
stack<char> ops;
unordered_map<char, int> precedence = {{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}};

void calculate() {
    int right = nums.top(); nums.pop();
    int left = nums.top(); nums.pop();
    char op = ops.top(); ops.pop();

    switch (op) {
        case '+': nums.push(left + right); break;
        case '-': nums.push(left - right); break;
        case '*': nums.push(left * right); break;
        case '/': nums.push(left / right); break;
    }
}

int main() {
    string expr;
    cin >> expr;

    for (int i = 0; i < expr.size(); ++i) {
        char ch = expr[i];

        if (isdigit(ch)) {
            int value = 0;
            while (i < expr.size() && isdigit(expr[i])) {
                value = value * 10 + (expr[i++] - '0');
            }
            --i;
            nums.push(value);
        } else if (ch == '(') {
            ops.push(ch);
        } else if (ch == ')') {
            while (ops.top() != '(') calculate();
            ops.pop(); // '(' を削除
        } else {
            while (!ops.empty() && ops.top() != '(' &&
                   precedence[ops.top()] >= precedence[ch]) {
                calculate();
            }
            ops.push(ch);
        }
    }

    while (!ops.empty()) calculate();
    cout << nums.top() << endl;
    return 0;
}

後置表現(逆ポーランド記法)の評価

後置表現では括弧が不要で、左から右に単純に処理できるため、実装が容易である。数字はスタックに積み、演算子が現れたら直近の2つの値を取り出して計算し、結果を再びスタックに格納する。

#include <bits/stdc++.h>
using namespace std;

int main() {
    stack<int> stk;
    string token;
    
    while (cin >> token) {
        if (token == "@") break;

        if (token.back() == '.') {
            // 数字トークン(末尾に '.')
            int num = stoi(token.substr(0, token.size() - 1));
            stk.push(num);
        } else {
            // 演算子
            int b = stk.top(); stk.pop();
            int a = stk.top(); stk.pop();
            int result;

            switch (token[0]) {
                case '+': result = a + b; break;
                case '-': result = a - b; break;
                case '*': result = a * b; break;
                case '/': result = a / b; break;
                default: result = 0;
            }
            stk.push(result);
        }
    }

    cout << stk.top() << endl;
    return 0;
}

タグ: C++ スタック 数式評価 中置表現 後置表現

6月6日 21:06 投稿