1232. 사칙연산
Code Battle (`23 동계 대학생 S/W 알고리즘 특강 기초학습 문제)
본 게시글은 개인 학습 용도로 작성한 게시글입니다.
(문제 출처: SW Expert Academy)
- 이진 트리의 post order 순회 문제
- “No. 9 사칙연산 유효성 검사” 문제와 유사하나, 이번엔 식이 유효한 지를 검사하는 것이 아닌 계산을 하는 것이다. 저번과 마찬가지로 post order 순회를 통해 답을 구한다.
- 최대 노드의 개수가 $1,000$ 이하라서 재귀적으로 풀이해도 Stack 영역 메모리 사용량이 크지 않을 것이라 생각하였다.
- 사칙 연산 트리가 완전 이진 트리가 아니기 때문에, 자식 노드의 유무 혹은 그 번호를 예측할 수 없다. 즉,
stdin
에서 입력 받아 사용해야 한다. - 자식 노드 번호가 항상 주어지는 것이 아니어서
std::cin
의>>
연산자로 입력 받기에는 다소 번거로움이 있다. 해결책으로 Java 언어의BufferedReader
+StringTokenizer
의 조합과 유사한 동작을 하는 코드를 작성하였다.이진 트리 문제 보다는 문자열 처리 문제로 기억에 남는 느낌이다.
#include <iostream>
#define MAX_N 1000
#define BUFFER_CAPACITY 32
using namespace std;
int stoi(char *str) {
int retval = 0;
int d = 0;
while (str[d] != '\0') {
retval *= 10;
retval += str[d] - '0';
d++;
}
return retval;
}
struct Node {
char data[BUFFER_CAPACITY];
Node* left;
Node* right;
void setData(char* src) {
char *dst = data;
while (*src != '\0') {
*dst = *src;
src++;
dst++;
}
*dst = '\0';
};
void init() {
left = nullptr;
right = nullptr;
data[0] = '\0';
}
double calc() {
switch (data[0])
{
case '+':
return left->calc() + right->calc();
case '-':
return left->calc() - right->calc();
case '*':
return left->calc() * right->calc();
case '/':
return left->calc() / right->calc();
default:
return (double) stoi(data);
}
};
};
struct BinaryTree {
Node nodes[MAX_N+1];
Node *root;
void init(int size) {
root = nodes + 1;
for (int i = 1; i <= size; i++) {
nodes[i].init();
}
};
Node *getNode(int at) {
return nodes + at;
};
} tree;
struct StringTokenizer {
char buffer[BUFFER_CAPACITY];
char *pointer;
void init() {
pointer = buffer;
};
char *nextToken() {
char *retval = pointer;
while (*pointer != ' ' && *pointer != '\0') {
pointer++;
}
*pointer = '\0';
pointer++;
return retval;
};
bool hasNext() {
return *pointer != '\0';
};
} stringTokenizer;
static int solve()
{
int size;
Node *node;
cin >> size;
cin.ignore();
tree.init(size);
for (int i = 0; i < size; i++)
{
cin.getline(stringTokenizer.buffer, BUFFER_CAPACITY, '\n');
stringTokenizer.init();
node = tree.getNode(stoi(stringTokenizer.nextToken()));
node->setData(stringTokenizer.nextToken());
if (stringTokenizer.hasNext()) {
node->left = tree.getNode(stoi(stringTokenizer.nextToken()));
node->right = tree.getNode(stoi(stringTokenizer.nextToken()));
}
}
return tree.root->calc();
}
int main(int argc, char **argv)
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
for (int test_case = 1; test_case <= 10; ++test_case)
{
printf("#%d %.0d\n", test_case, solve());
}
return 0;
}