21. 이진트리
이진트리란?
이진트리는 모든 노드가 최대 두 개의 자식 노드를 가지는 트리입니다. 각 노드는 왼쪽 자식과 오른쪽 자식을 가질 수 있으며, 이 구조는 많은 알고리즘의 기반이 됩니다.
이진트리의 특징
- 자식 노드가 최대 2개 (왼쪽, 오른쪽)
- 구조화된 탐색에 용이하여 재귀적 접근이 자연스럽다
- 다양한 트리 구조로 확장 가능 (이진 탐색 트리, 힙, 세그먼트 트리 등)
이진트리의 종류
- 편향 이진트리: 자식이 한쪽으로만 치우쳐 있는 트리
- 포화 이진트리: 모든 레벨이 꽉 찬 이진트리
- 완전 이진트리: 마지막 레벨을 제외하고 노드가 꽉 차 있으며, 왼쪽부터 채워진 트리 (코딩 테스트에서 선호)
이진트리의 순차 표현 (배열 기반)
이진트리는 배열로도 표현할 수 있습니다. 노드 위치에 따른 인덱스 관계는 다음과 같습니다:
- 루트 노드: index = 1
- 부모 노드: index // 2
- 왼쪽 자식: index * 2
- 오른쪽 자식: (index * 2) + 1
이 구조는 힙이나 완전 이진트리 구현에서 자주 사용됩니다.
예제: 백준 1991번 “트리 순회”
문제 설명
- 트리의 노드 수
N
과 루트 노드를 포함한 각 노드의 왼쪽, 오른쪽 자식 노드가 주어진다. - 이를 기반으로 전위 순회, 중위 순회, 후위 순회 결과를 출력하라.
코드 구현
import sys
N = int(sys.stdin.readline().strip())
tree = {}
# 트리 입력 저장
for n in range(N):
root, left, right = sys.stdin.readline().strip().split()
tree[root] = [left, right]
# 전위 순회 (Root - Left - Right)
def preorder(root):
if root != '.':
print(root, end='')
preorder(tree[root][0])
preorder(tree[root][1])
# 중위 순회 (Left - Root - Right)
def inorder(root):
if root != '.':
inorder(tree[root][0])
print(root, end='')
inorder(tree[root][1])
# 후위 순회 (Left - Right - Root)
def postorder(root):
if root != '.':
postorder(tree[root][0])
postorder(tree[root][1])
print(root, end='')
# 루트 노드 'A'부터 순회 시작
preorder('A')
print()
inorder('A')
print()
postorder('A')
코드 분석
1. 트리 저장 방식
tree = {}
for n in range(N):
root, left, right = sys.stdin.readline().strip().split()
tree[root] = [left, right]
→ 노드를 키로 하고, 자식 노드들을 값으로 저장하여 딕셔너리 기반 트리 구조를 생성합니다.
2. 전위 순회 (Preorder)
def preorder(root):
if root != '.':
print(root, end='')
preorder(tree[root][0])
preorder(tree[root][1])
→ 루트 → 왼쪽 → 오른쪽 순서로 순회. 연산을 먼저 수행하고 하위로 이동합니다.
3. 중위 순회 (Inorder)
def inorder(root):
if root != '.':
inorder(tree[root][0])
print(root, end='')
inorder(tree[root][1])
→ 왼쪽 → 루트 → 오른쪽 순서로 순회. 이진 탐색 트리에서는 오름차순 정렬된 결과를 얻을 수 있습니다.
4. 후위 순회 (Postorder)
def postorder(root):
if root != '.':
postorder(tree[root][0])
postorder(tree[root][1])
print(root, end='')
→ 왼쪽 → 오른쪽 → 루트 순서. 연산을 나중에 수행하며 삭제 연산 등에서 유용합니다.
5. 출력 결과
preorder('A')
print()
inorder('A')
print()
postorder('A')
→ 전위, 중위, 후위 순회 결과를 각각 출력합니다.
정리
항목 | 설명 |
---|---|
알고리즘 유형 | 이진트리 기반 순회 |
주요 조건 | 루트 노드에서 재귀적 순회 진행 |
핵심 자료구조 | 딕셔너리 기반 트리 저장, 순회 함수 |
시간 복잡도 | O(N) - 노드 수만큼 탐색 |
응용 예시 | 연산 순서 제어, 삭제 연산, 이진 탐색 트리 정렬 등 |