문제
사칙연산으로 구성되어 있는 식은 이진 트리로 표현할 수 있다. 아래는 식 “(9/(6-4))*3”을 이진 트리로 표현한 것이다.
임의의 정점에 연산자가 있으면 해당 연산자의 왼쪽 서브 트리의 결과와 오른쪽 서브 트리의 결과를 사용해서 해당 연산자를 적용한다.
사칙연산 “+, -, *, /”와 양의 정수로만 구성된 임의의 이진트리가 주어질 때, 이를 계산한 결과를 출력하는 프로그램을 작성하라.
단, 중간 과정에서의 연산은 실수 연산으로 하되, 최종 결과값이 정수로 떨어지지 않으면 정수부만 출력한다.
위의 예에서는 최종 결과값이 13.5이므로 13을 출력하면 된다.
[제약 사항]
정점의 총 수 N은 1≤N≤1000.
[입력]
각 테스트 케이스의 첫 줄에는 각 케이스의 트리가 갖는 정점의 총 수 N(1≤N≤1000)이 주어진다. 그 다음 N줄에 걸쳐 각각의 정점 정보가 주어진다.
정점이 단순한 수이면 정점번호와 해당 양의 정수가 주어지고, 정점이 연산자이면 정점번호, 연산자, 해당 정점의 왼쪽 자식, 오른쪽 자식의 정점번호가 차례대로 주어진다.
정점번호는 1부터 N까지의 정수로 구분된다. 입력에서 정점 번호를 매기는 특별한 규칙은 없으나, 루트 정점의 번호는 반드시 1이다.
입력에서 이웃한 수나 연산자는 모두 공백으로 구분된다.
위의 예시에서, 숫자 4가 7번 정점에 해당하면 “7 4”으로 주어지고, 연산자 ‘/’가 2번 정점에 해당하면 두 자식이 각각 숫자 9인 4번 정점과 연산자 ‘-’인 5번 정점이므로 “2 / 4 5”로 주어진다.
총 10개의 테스트 케이스가 주어진다.
[출력]
#부호와 함께 테스트 케이스의 번호를 출력하고, 공백 문자 후 테스트 케이스에 대한 답을 출력한다. 답은 항상 정수값으로 기록한다.
#include <iostream>
using namespace std;
// 경우의 수 2가지
// 1. 피연산자인 경우
// 2. 연산자인 경우
struct node {
int data;
int num;
char a;
node* left;
node* right;
};
constexpr size_t MAXSIZE = 9999;
int node_count = 0;
node node_pool[MAXSIZE];
node* parent_new_node(int s,char a)
{
node_pool[node_count].a = a;
node_pool[node_count].num = 0;
node_pool[node_count].data = s;
node_pool[node_count].left = nullptr;
node_pool[node_count].right = nullptr;
return &node_pool[node_count++];
}
node* child_new_node(int s, int num)
{
node_pool[node_count].a = ' ';
node_pool[node_count].num = num;
node_pool[node_count].data = s;
node_pool[node_count].left = nullptr;
node_pool[node_count].right = nullptr;
return &node_pool[node_count++];
}
void postorder(node* cur)
{
if (cur != 0)
{
postorder(cur->left);
postorder(cur->right);
if (cur->left != 0 && cur->right != 0)
{
if (cur->a == '+')
{
cur->num=cur->left->num + cur->right->num;
}
else if (cur->a == '-')
{
cur->num = cur->left->num - cur->right->num;
}
else if (cur->a == '/')
{
if(cur->left->num!=0&&cur->right->num!=0)
{
cur->num = cur->left->num / cur->right->num;
}
}
else if (cur->a == '*')
{
cur->num = cur->left->num * cur->right->num;
}
}
}
}
int main()
{
int n, s, left, right;
char a;
for (int i = 0; i < 10; i++)
{
cin >> n;
for (int q = 0; q < n; q++)
{
int num = 0;
char b[10];
cin >> s;
cin >> b;
if (b[0]>='0'&&b[0]<='9')
{
for (int w = 0; b[w]; w++)
{
num *= 10;
num += b[w] - '0';
}
node* node_new_child = child_new_node(s, num);
}
else
{
cin >> left >> right;
a = b[0];
node* node_new_parent = parent_new_node(s, a);
node_new_parent->left = &node_pool[left - 1];
node_new_parent->right = &node_pool[right - 1];
}
}
postorder(&node_pool[0]);
cout << "#" << i + 1 <<' '<< node_pool[0].num << endl;
node_count = 0;
}
return 0;
}
우선 가장 중요한 것은 피연산자인지 연산자인지 확인을 하는 것이다.
두 가지 경우에서 입력받을 변수들이 달라지며 그에 따른 트리 연결도 해주어야한다.
if (b[0]>='0'&&b[0]<='9') 는 1번에 해당한다.
이 때 char 형으로 숫자 하나씩 입력받을 때 - '0'을 해주여 int형 변수로 바꾸어 주고
*10을 해주면서 자릿수를 증가시킨다.
else 는 2번에 해당한다.
연산자를 입력받았으며 해당하는 left, right 자식들이 누군지 입력을 받는다.
순회는 후위순회로 하였다. left->right->자신
트리는 로직만 잘 생각하면 쉽게 구현할 수 있을 것 같다.
그치만 그게 어렵다. -_-