백준 1991번 "트리순회"
Question:
이진 트리를 입력받아
전위 순회(preorder traversal),
중위 순회(inorder traversal),
후위 순회(postorder traversal)한 결과를
출력하는 프로그램을 작성하시오.
예를 들어 위와 같은 이진 트리가 입력되면,
- 전위 순회한 결과 : ABDCEFG // (루트) (왼쪽 자식) (오른쪽 자식)
- 중위 순회한 결과 : DBAECFG // (왼쪽 자식) (루트) (오른쪽 자식)
- 후위 순회한 결과 : DBEGFCA // (왼쪽 자식) (오른쪽 자식) (루트)
가 된다.
Input:
첫째 줄에는
이진 트리의 노드의 개수 N(1 ≤ N ≤ 26)이 주어진다.
둘째 줄부터
N개의 줄에 걸쳐
각 노드와 그의 왼쪽 자식 노드, 오른쪽 자식 노드가 주어진다.
노드의 이름은 A부터 차례대로 알파벳 대문자로 매겨지며,
항상 A가 루트 노드가 된다.
자식 노드가 없는 경우에는 .으로 표현한다.
Output:
첫째 줄에 전위 순회,
둘째 줄에 중위 순회,
셋째 줄에 후위 순회한 결과를 출력한다.
각 줄에 N개의 알파벳을 공백 없이 출력하면 된다.
Restriction:
시간제한:
2 초
Example Case:
Input case 1:
7
A B C
B D .
C E F
E . .
F . G
D . .
G . .
Output case 1:
ABDCEFG
DBAECFG
DBEGFCA
풀이 과정:
크리스마스날에 다루는 “트리” 순회이다.
애인이 없어서 슬프지만 대신 재밌는 트리순회를 살펴보자…
이 문제는 기본적인 트리 순회를 구현하는 문제이다.
트리를 순회하는 방식에는
- 전위 순회[preorder] (NLR)
- 중위 순회[inorder] (LNR)
- 후위 순회[postorder] (LRN)
이 존재한다.
위에는 등장하지 않지만, 트리의 레벨별로 순회하는 레벨 순회도 존재한다(BFS).
각 순회의 이름에 걸맞게,
루트 노드를 방문하는 것의 순서를 나타냈다고 생각하면 된다.
예를 들어, 전위순회란,
루트노트를 방문 한 뒤 => 왼쪽 서브 트리 탐색 => 오른쪽 서브 트리 탐색
순서의 순회방법이다.
여기서는 이진트리를 c++ stl중 하나인 map을 사용하여 표현하였다.
트리를 배열이나 연결리스트 형태로 나타낼 수 있지만,
이 문제에선 map을 사용하였다.
특히, 배열로 이진트리를 나타내는 경우는
힙(우선순위 큐,힙 정렬)을 이용할 때 사용한다.
C++의 STL중 map 이란,
key , value 값 한 쌍을 한 노드안에 저장하는 트리라고 생각하면 된다.
따라서, pair로 저장이 되는데,
first = key / second = value 라고 생각하면 된다.
특히 map STL에서 주목해야할 점은
map이란 헤더를 포함시켜야하고(#include <map>),
자동으로 오름차순으로 내부에서 정렬이 진행되고,
키들의 중복을 허락하지 않는다.
이 문제에서는 트리를 표현하기 위해,
map <char, pair<char,char» tree; 로 선언한 뒤
입력 받은 노드들의 관계를
tree[node].first = 왼쪽 자식 노드,
tree[node].second = 오른쪽 자식 노드로 표현하였다.
즉, 한 Node = key라고 생각하게 되면,
value 값 자체를 pair로 두어 이진트리를 표현한 것이다.
아래는 소스코드이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <map>
using namespace std;
map <char,pair<char,char>> tree; //tree => map
// pre,in,postorder are showing node's order
void preorder(char node) {
cout << node << "";
if(tree[node].first != '.') {
preorder(tree[node].first);
}
if(tree[node].second != '.') {
preorder(tree[node].second);
}
}
void inorder(char node) {
if(tree[node].first != '.') {
inorder(tree[node].first);
}
cout << node << "";
if(tree[node].second != '.') {
inorder(tree[node].second);
}
}
void postorder(char node) {
if(tree[node].first != '.') {
postorder(tree[node].first);
}
if(tree[node].second != '.') {
postorder(tree[node].second);
}
cout << node << "";
}
int main() {
int N;
cin >> N;
char a,b,c; //tree[a].first = b tree[a].second = c (left/right node)
for(int i = 0;i<N;i++) {
cin >> a >> b >> c;
tree[a] = make_pair(b,c); //tree node input
}
preorder('A');
cout << endl;
inorder('A');
cout << endl;
postorder('A');
}