개발/👾 PS
[ 이진 트리 ] 알고리즘
정소은
2023. 7. 26. 18:41
1. 개념
이진 트리 : 각 노드의 자식 노드의 개수가 2개 이하로 구성되어 있는 트리
이진 트리의 종류
- 편향 이진 트리 : 노드가 한쪽 방향으로 몰려 있는 트리
* 탐색 속도 느림 / 공간 복잡도 큼
- 포화 이진 트리 : 트리의 높이가 일정하며 노드가 꽉 찬 트리
* 포화 이진 트리의 노드의 개수 : 2^(높이+1) - 1 개
- 완전 이진 트리 : 노드가 순차적으로(왼 -> 오) 채워져 있는 트리
완전 이진 트리가 가장 자주 쓰이는 이진 트리!
2. 구현
이진 트리를 가장 직관적으로 표현할 수 있는 자료 구조는 '리스트'
이진 트리는 1차원 리스트로 표현한다
인덱스 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
노드 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
노드 간의 상관관계는 아래의 표에 따라 표현한다
이동 목표 노드 | 인덱스 연산 | 제약 조건 ( n : 노드 개수 ) |
루트 노드 | index = 1 | |
부모 노드 | index = index / 2 | 현재 노드가 루트 노드가 아님 |
왼쪽 자식 노드 | index = index * 2 | index * 2 <= n |
오른쪽 자식 노드 | index = index * 2 + 1 | index * 2 + 1 <= n |
3. 문제
# 1 트리 순회하기 - 백준 1991번
https://www.acmicpc.net/problem/1991
1991번: 트리 순회
첫째 줄에는 이진 트리의 노드의 개수 N(1 ≤ N ≤ 26)이 주어진다. 둘째 줄부터 N개의 줄에 걸쳐 각 노드와 그의 왼쪽 자식 노드, 오른쪽 자식 노드가 주어진다. 노드의 이름은 A부터 차례대로 알파
www.acmicpc.net
트리 순환
- 전위 순환 : 루트 -> 왼쪽 자식 -> 오른쪽 자식
- 중위 순환 : 왼쪽 자식 -> 루트 -> 오른쪽 자식
- 후위 순환 : 왼쪽 자식 -> 오른쪽 자식 -> 루트
import sys
input = sys.stdin.readline
n = int(input())
# 딕셔너리로 이진 트리 구현
tree = {}
for i in range(n):
root, left, right = map(str, input().split())
tree[root] = [left, right]
# 전위 순환 : 루트 -> 왼쪽 자식 -> 오른쪽 자식
def preorder(v):
# 가지의 마지막 노드 도달하면 return -> 재귀 스택에서 pop된 재귀 함수 발동
if v == ".":
return
print(v, end='') # 루트
preorder(tree[v][0]) # 왼쪽 자식
preorder(tree[v][1]) # 오른쪽 자식
# 중위 순환 : 왼쪽 자식 -> 루트 -> 오른쪽 자식
def inorder(v):
# 가지의 마지막 노드 도달하면 return -> 재귀 스택에서 pop된 재귀 함수 발동
if v == ".":
return
inorder(tree[v][0]) # 왼쪽 자식
print(v, end='') # 루트
inorder(tree[v][1]) # 오른쪽 자식
# 후위 순환 : 왼쪽 자식 -> 오른쪽 자식 -> 루트
def postorder(v):
# 가지의 마지막 노드 도달하면 return -> 재귀 스택에서 pop된 재귀 함수 발동
if v == '.':
return
postorder(tree[v][0]) # 왼쪽 자식
postorder(tree[v][1]) # 오른쪽 자식
print(v, end='') # 루트
# 루트 노드 각 함수에 삽입
preorder('A')
print()
inorder('A')
print()
postorder('A')