solved_ac[Class4][이진 검색 트리](https://www.acmicpc.net/problem/5639)
이진 검색 트리는 다음과 같은 세 가지 조건을 만족하는 이진 트리이다.
전위 순회 (루트-왼쪽-오른쪽)은 루트를 방문하고, 왼쪽 서브트리, 오른쪽 서브 트리를 순서대로 방문하면서 노드의 키를 출력한다. 후위 순회 (왼쪽-오른쪽-루트)는 왼쪽 서브트리, 오른쪽 서브트리, 루트 노드 순서대로 키를 출력한다. 예를 들어, 위의 이진 검색 트리의 전위 순회 결과는 50 30 24 5 28 45 98 52 60 이고, 후위 순회 결과는 5 28 24 45 30 60 52 98 50 이다.
이진 검색 트리를 전위 순회한 결과가 주어졌을 때, 이 트리를 후위 순회한 결과를 구하는 프로그램을 작성하시오.
트리를 전위 순회한 결과가 주어진다. 노드에 들어있는 키의 값은 106보다 작은 양의 정수이다. 모든 값은 한 줄에 하나씩 주어지며, 노드의 수는 10,000개 이하이다. 같은 키를 가지는 노드는 없다.
입력으로 주어진 이진 검색 트리를 후위 순회한 결과를 한 줄에 하나씩 출력한다.
50
30
24
5
28
45
98
52
60
5
28
24
45
30
60
52
98
50
이진 트리의 전위 순회로 입력을 받아서 후위 순회로 출력을 하는 것이다. 입력을 list에 차례대로 입력을 받고 해당 list[i + 1]이 list[i]보다 크다면 오른쪽 자식 노드, 그게 아니라면 왼쪽 자식 노드로 설정을 해주면서 풀어야한다. 전위 순회는 재귀 함수의 호출 순서와 같다.
base case
root node : list[start]
left node : 함수(start + 1, right_node - 1)
right node : 함수(right_node, end)
print(root node)
전위순회는 재귀함수의 호출 순서와 같다.
예시 문제를 보자.
1.
start = 0
end = len(list) - 1
root = list[start] = 50
루프
right_node_index = 6 = 98의 index
함수(start = start + 1, end = right_node_index - 1)
2.
start = 1
end = 5
root = list[start] = 30
루프
right_node_index = 5 = 45의 index
함수(start = start + 1, end = right_node_index - 1)
3.
start = 2
end = 4
root = list[start] = 24
루프
right_node_index = 4 = 28의 index
함수(start = start + 1, end = right_node_index - 1)
4.
start = 3
end = 3
root = list[start] = 5
start와 end가 같아서 루프를 돌지 못함.
그래서 right_node_index가 업데이트 되지 않음.
그렇기 때문에 루프를 돌기 전에
right-node_index를 end + 1로 업데이트를 시켜주는것.
왜 굳이 end + 1이냐면 계속 함수를 호출하면서 end 범위를 r
right_node_index에서 1개씩 줄여줌.
그러면 start는 1개씩 늘어나는데 end 범위는 계속 그 자리에서 기다림.
그러다가 start값이 end값을 역전하는 순간 재귀를 return해주면 됨.
start가 end를 역전하는 경우는 더이상 작은 노드가 없을 때 일어남.
함수(start = start + 1, end = right_node_index - 1)
5.
start = 4
end = 3
start가 end 역전. 더이상 작은 노드가 없다는 뜻.
함수(right_node_index, end)
6.
start = 4
end = 3
return
5번과 6번은 뭘 의미하냐면 가장 작은 노드 5가 추려졌고
5의 자식노드 왼쪽, 오른쪽 둘다 없다는 뜻
함수(right_node_index, end)
7.
start = 4
end = 4
root = list[start] = 28
루프돌지 않고(start와 end가 같기 때문)
그 전에 right_node_index = end + 1 = 5로 됨.
함수(start = start + 1, end = right_node_index - 1)
8.
start = 5
end = 4
return
함수(right_node_index, end)
9.
start = 5
end = 4
reuturn
함수(right_node_index, end)
10.
start = 5
end = 5
root = list[start] = 45
루프돌지 않음
right_node_index = end + 1 = 6
함수(start = start + 1, end = right_node_index - 1)
11.
start = 6
end = 5
return
함수(right_node_index, end)
12.
start = 6
end = 5
return
함수(right_node_index, end)
13.
start = 6
end = 8
root = list[start] = 98
루프
right_node_index = 98보다 큰 수가 없기 때문에 그 전에 end + 1로 잡아놓은 값 = 9
함수(start = start + 1, end = right_node_index - 1)
14.
start = 7
end = 8
root = list[start] = 52
루프
right_node_index = 60의 index 값 = 8
함수(start = start + 1, end = right_node_index - 1)
15.
start = 8
end = 7
return
함수(right_node_index, end)
16.
start = 8
end = 8
root = list[start] = 60
루프 안돔
right_node_index = 9
함수(start = start + 1, end = right_node_index - 1)
17.
start = 9
end = 8
return
함수(right_node_index, end)
18.
start = 9
end = 8
return
함수(right_node_index, end)
19.
start = 9
end = 8
return
import sys
sys.setrecursionlimit(10**9)
list = []
while True:
try:
n = sys.stdin.readline()
list.append(int(n))
except:
break
def binary(start, end):
if start > end:
return
right_node = end + 1
root = list[start]
for i in range(start + 1, end + 1):
if list[i] > root:
right_node = i
break
binary(start + 1, right_node - 1)
binary(right_node , end)
print(root)
binary(0, len(list) - 1)
tree에 대해서 잘 모르는 상태로 접근을 해서 많이 힘들었다. 디버깅도 많이 해보고 최대한 답지를 보지 말자는 식으로 풀다가 총 5시간이 걸렸다... 그래도 이진 탐색 트리에 대해서 전위 순회, 중위 순회, 후위 순회를 알게 되어서 다행이라고 생각한다.