ν‹°μŠ€ν† λ¦¬ λ·°

728x90
λ°˜μ‘ν˜•
μ»΄ν“¨ν„°μ—μ„œ κ΄„ν˜Έκ°€ ν¬ν•¨λœ 연산을 μ‰½κ²Œ μ²˜λ¦¬ν•˜κΈ° μœ„ν•΄μ„œλŠ”, μ€‘μœ„ ν‘œν˜„μ‹(Infix)보닀 ν›„μœ„ ν‘œν˜„μ‹(Postfix)을 톡해 κ³„μ‚°ν•˜λ©΄ μ‰½κ²Œ μ²˜λ¦¬ν•  수 μžˆλ‹€. μ΄λŠ” Stack을 톡해 μ‰½κ²Œ κ΅¬ν˜„ν•  수 있으며, λ³€ν™˜ν•œ 식을 κ³„μ‚°ν•˜λŠ” 것은 어렡지 μ•Šλ‹€.

Stack을 μ‚¬μš©ν•˜μ—¬ κ΅¬ν˜„

ν›„μœ„ ν‘œν˜„μ‹ λ³€ν™˜

int priority(char c)
{
    if (c == '(')
        return 0;
    else if (c == '+' || c == '-')
        return 1;
    // *, / 인 경우
    return 2;
}

string changePostfix(string target)
{
    stack<char> s;
    string prefix;

    for (int i = 0; target[i]; i++) {
        if (target[i] == '(')
            s.push('(');
        else if (target[i] == ')') {
            while (s.top() != '(') {
                prefix += s.top();
                s.pop();
            }
            s.pop();
        }
        else if (target[i] == '+' || target[i] == '/' || target[i] == '*' || target[i] == '-') {
            while (!s.empty() && priority(target[i]) <= priority(s.top())) {
                prefix += s.top();
                s.pop();
            }
            s.push(target[i]);
        }
        else { // ν”Όμ—°μ‚°μž.
            prefix += target[i];
        }
    }

    while (!s.empty()) {
        prefix += s.top();
        s.pop();
    }

    return prefix;
}

 ν›„μœ„ ν‘œν˜„μ‹μ„ μŠ€νƒμ„ μ‚¬μš©ν•˜μ—¬ λ³€ν™˜ν•  λ•Œ 쑰건은 λ‹€μŒκ³Ό κ°™λ‹€.

  • `ν”Όμ—°μ‚°μž`인 경우 λ°”λ‘œ 좜λ ₯ν•œλ‹€.
  • μ—°μ‚°μžκ°€ λ“€μ–΄μ˜€λ©΄ `μš°μ„ μˆœμœ„κ°€ λ†’κ±°λ‚˜ 같은 것은 μ œμ™Έ`ν•˜κ³  μŠ€νƒμ— push ν•œλ‹€.
  • `μ—¬λŠ” κ΄„ν˜Έ'('`κ°€ λ“€μ–΄μ˜¨ μ΄ν›„λ‘œλŠ” λ¬΄μ‘°κ±΄ μŠ€νƒμ— push ν•œλ‹€.
  • `λ‹«λŠ” κ΄„ν˜Έ')'`κ°€ λ“€μ–΄μ˜€λ©΄ `'('`일 λ•ŒκΉŒμ§€ μŠ€νƒμ—μ„œ pop ν•œλ‹€.

 

ν›„μœ„ ν‘œν˜„μ‹ 계산

int vars[26];

int calcPostfix(string target) {
    stack<int> s;

    for (int i = 0; target[i]; i++) {
        if (isdigit(target[i]) || isalpha(target[i])) {
            int curNum = !isalpha(target[i]) ? target[i] - '0' : vars[target[i] - 'A'];
            s.push(curNum);
        }
        else {
            int op2 = s.top();
            s.pop();

            int op1 = s.top();
            s.pop();

            switch (target[i]) {
            case '+': s.push(op1 + op2); break;
            case '-': s.push(op1 - op2); break;
            case '*': s.push(op1 * op2); break;
            case '/': s.push(op1 / op2); break;
            }
        }
    }

    return s.top();
}

 ν›„μœ„ ν‘œν˜„μ‹μ„ κ³„μ‚°ν•˜λŠ” 데 μžˆμ–΄, μ—°μ‚°μž 말고 μ‹μ—μ„œ `A, B, C`와 같은 λ³€μˆ˜λ“€κ³Ό 일반적인 μˆ«μžκ°€ μžˆλŠ” κ²½μš°μ—λ„ 계산할 수 μžˆλ„λ‘ ν•˜μ˜€λ‹€. μš°μ„  값을 κ³„μ‚°ν•˜κΈ° μœ„ν•΄μ„œ μ€‘μš”ν•œ 것은 stack을 intν˜•μœΌλ‘œ μ„ μ–Έν•˜μ—¬μ•Ό ν•œλ‹€λŠ” 것이닀. λ˜ν•œ `cctype`에 μ„ μ–Έλœ `isdigit`, `isalpha`, `isalpha`λ₯Ό μ‚¬μš©ν•˜μ—¬μ„œ λ³€μˆ˜μΈμ§€, μˆ«μžμΈμ§€ κ΅¬λΆ„ν•˜μ—¬μ„œ μ²˜λ¦¬ν•˜λ©΄ λœλ‹€.

 varsλŠ” A ~ ZκΉŒμ§€μ˜ λ³€μˆ˜λ“€μ˜ 값을 μ €μž₯ν•˜κΈ° μœ„ν•œ λ³€μˆ˜μ΄λ‹€. 이에 λŒ€ν•œ 인덱슀 접근은 `vars[문자 - 'A']`와 같이 μ ‘κ·Όν•˜λ©΄ λœλ‹€. 숫자의 경우 intν˜•μœΌλ‘œ λ³€ν™˜ν•˜κ³ μž ν•  λ•Œ, `문자 - '0'`을 톡해 λ³€ν™˜ν•  수 μžˆλ‹€.

 

// 숫자인 경우.
if ('0' <= target[i] && target[i] <= '9) {
    // Do something.
}
// A ~ Z인 경우
else if ('A' <= target[i] && target[i] <= 'Z') {
    // Do something
} 
// μ—°μ‚°μžμΈ 경우
else {
    // Do something
}

 λ³„λ„μ˜ `include` 없이, string을 index λ³„λ‘œ μ ‘κ·Όν•˜κ²Œ 되면 charμ΄λ―€λ‘œ, μœ„μ™€ 같이 숫자, 문자, μ—°μ‚°μž ꡬ뢄도 κ°€λŠ₯ν•˜λ‹€.

 

 λ³€ν™˜ν•œ ν›„μœ„ ν‘œν˜„μ‹μ„ κ³„μ‚°ν•˜λŠ” 과정은 κ°„λ‹¨ν•˜λ‹€.

  • `ν”Όμ—°μ‚°μž`인 경우 stack에 push ν•œλ‹€.
  • `μ—°μ‚°μž`인 경우 stackμ—μ„œ 2개의 수λ₯Ό pop ν•˜μ—¬ κ³„μ‚°ν•œλ‹€.
    • κ³„μ‚°λœ 값을 stack에 push ν•œλ‹€.
  • λ§ˆμ§€λ§‰μ— stack에 λ‚¨λŠ” 값이 μ΅œμ’… 계산 값이닀.

 

전체 μ½”λ“œ

#include <stack>
#include <string>
#include <cctype>
#include <sstream>
#include <iostream>

using namespace std;

int vars[26];

int priority(char c)
{
    if (c == '(')
        return 0;
    else if (c == '+' || c == '-')
        return 1;
    // *, / 인 경우
    return 2;
}

string changePostfix(string target)
{
    stack<char> s;
    string prefix;

    for (int i = 0; target[i]; i++) {
        if (target[i] == '(')
            s.push('(');
        else if (target[i] == ')') {
            while (s.top() != '(') {
                prefix += s.top();
                s.pop();
            }
            s.pop();
        }
        else if (target[i] == '+' || target[i] == '/' || target[i] == '*' || target[i] == '-') {
            while (!s.empty() && priority(target[i]) <= priority(s.top())) {
                prefix += s.top();
                s.pop();
            }
            s.push(target[i]);
        }
        else { // ν”Όμ—°μ‚°μž.
            prefix += target[i];
        }
    }

    while (!s.empty()) {
        prefix += s.top();
        s.pop();
    }

    return prefix;
}

int calcPostfix(string target) {
    stack<int> s;

    for (int i = 0; target[i]; i++) {
        if (isdigit(target[i]) || isalpha(target[i])) {
            int curNum = !isalpha(target[i]) ? target[i] - '0' : vars[target[i] - 'A'];
            s.push(curNum);
        }
        else {
            int op2 = s.top();
            s.pop();

            int op1 = s.top();
            s.pop();

            switch (target[i]) {
            case '+': s.push(op1 + op2); break;
            case '-': s.push(op1 - op2); break;
            case '*': s.push(op1 * op2); break;
            case '/': s.push(op1 / op2); break;
            }
        }
    }

    return s.top();
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    string test = "5+A*(B+C)";

    vars[0] = 7; // A = 7
    vars[1] = 10; // B = 10
    vars[2] = 15; // C = 15

    string post = changePostfix(test);
    cout << post << endl;
    cout << calcPostfix(post) << endl;
}

 

망각 μ†λ„λŠ” 생각보닀 λΉ λ₯΄λ‹€..

 μ•½, 2λ…„ 전쯀에 문제 풀이λ₯Ό μœ„ν•΄ 곡뢀λ₯Ό ν–ˆλ‹€... 망각 속도가 λΉ¨λΌμ„œ μžŠμ–΄λ²„λ¦¬κ³  λ‹€μ‹œ κ³΅λΆ€ν•˜κ²Œ λ˜λŠ” 것을 λ°˜λ³΅ν•˜κ³  μžˆλ‹€.

728x90
λ°˜μ‘ν˜•
λŒ“κΈ€
κΈ€ 보관함
μ΅œκ·Όμ— 올라온 κΈ€
μ΅œκ·Όμ— 달린 λŒ“κΈ€