자료구조 정리 - 트리(Tree)의 개념과 이진 트리
2025. 10. 3. 20:37

트리 (Tree)

핵심 개념:

  • 계층 구조 (부모-자식 관계)
  • 하나의 루트(root)에서 시작
  • 사이클 없음 (순환 안 함)

 

트리의 기본 용어

        1          ← 루트 (Root)
       / \
      2   3        ← 자식 (Children), 1의 자식
     / \   \
    4   5   6      ← 리프 (Leaf, 자식 없는 노드)

 

트리 용어 - 완전판

 

깊이 (Depth)

  • 루트부터 그 노드까지의 거리
  • 노드 1의 깊이: 0
  • 노드 2의 깊이: 1
  • 노드 4의 깊이: 2

 

높이 (Height)

  • 그 노드부터 가장 깊은 리프까지의 거리
  • 노드 4의 높이: 0 (리프니까)
  • 노드 2의 높이: 1 (자식까지 1칸)
  • 노드 1의 높이: 2 (가장 깊은 리프까지 2칸)

트리의 높이 = 루트의 높이

 

레벨 (Level)

  • 깊이랑 같은 말
  • 노드 1: 레벨 0
  • 노드 2, 3: 레벨 1
  • 노드 4, 5, 6: 레벨 2

 

차수 (Degree)

  • 자식의 개수
  • 노드 1의 차수: 2 (자식 2개)
  • 노드 2의 차수: 2 (자식 2개)
  • 노드 3의 차수: 1 (자식 1개)
  • 노드 4의 차수: 0 (리프)

 

형제 (Sibling)

  • 같은 부모를 가진 노드
  • 노드 2와 3: 형제
  • 노드 4와 5: 형제

 

조상 (Ancestor)

  • 그 노드의 부모, 부모의 부모, ...
  • 노드 4의 조상: 2, 1

 

자손 (Descendant)

  • 그 노드의 자식, 자식의 자식, ...
  • 노드 1의 자손: 2, 3, 4, 5, 6

 

서브트리 (Subtree)

  • 어떤 노드를 루트로 하는 트리
 
노드 2를 루트로 하는 서브트리:
      2
     / \
    4   5
  •  

용어 정리

 

용어 의미 예시 (노드 4 기준)
깊이 (Depth) 루트부터 그 노드까지 2
높이 (Height) 그 노드부터 가장 깊은 리프까지 0
레벨 (Level) 깊이랑 같음 2
차수 (Degree) 자식 개수 0
부모 (Parent) 위 노드 2
자식 (Children) 아래 노드 없음
형제 (Sibling) 같은 부모 5
조상 (Ancestor) 부모, 부모의 부모... 2, 1
자손 (Descendant) 자식, 자식의 자식... 없음

 

트리의 특징

  1. 노드 N개 → 간선 N-1개
    • 위 예시: 노드 6개, 간선 5개
  2. 루트는 하나
  3. 사이클 없음
 
   1 → 2 → 3 → 1  ← 이런 순환 없음!
  1. 모든 노드는 연결됨

 

이진 트리 (Binary Tree)

핵심: 자식이 최대 2개

        1
       / \
      2   3
     / \
    4   5
  • 노드 2: 자식 2개 (4, 5)
  • 노드 3: 자식 0개
  • 노드 1: 자식 2개 (2, 3)

자식이 3개면? → 이진 트리 아님!

 

이진 트리 종류

1. 포화 이진 트리 (Full Binary Tree)

        1
       / \
      2   3
     / \ / \
    4  5 6  7
  • 모든 레벨이 꽉 참
  • 리프가 모두 같은 레벨

 

2. 완전 이진 트리 (Complete Binary Tree)

        1
       / \
      2   3
     / \ /
    4  5 6
  • 왼쪽부터 차례로 채워짐
  • 마지막 레벨만 오른쪽이 비어있을 수 있음

힙(Heap)이 이것!

 

3. 편향 트리 (Skewed Tree)

    1
     \
      2
       \
        3
         \
          4
  • 한쪽으로만 치우침
  • 사실상 연결 리스트

 

이진 트리 구현

class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left = None   # 왼쪽 자식
        self.right = None  # 오른쪽 자식

# 트리 만들기
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)

#       1
#      / \
#     2   3
#    / \
#   4   5

 

트리 순회 (Traversal)

 

방문 순서에 따라 3가지:

 

1. 전위 순회 (Preorder) - Root → Left → Right

        1
       / \
      2   3
     / \
    4   5

순서: 1 → 2 → 4 → 5 → 3
(루트 먼저!)
 
def preorder(node):
    if node is None:
        return
    
    print(node.val)      # 루트
    preorder(node.left)   # 왼쪽
    preorder(node.right)  # 오른쪽

 

2. 중위 순회 (Inorder) - Left → Root → Right

        1
       / \
      2   3
     / \
    4   5

순서: 4 → 2 → 5 → 1 → 3
(왼쪽 → 루트 → 오른쪽)
 
def inorder(node):
    if node is None:
        return
    
    inorder(node.left)   # 왼쪽
    print(node.val)      # 루트
    inorder(node.right)  # 오른쪽

 

이진 탐색 트리에서 중위 순회 → 정렬된 순서!

 

3. 후위 순회 (Postorder) - Left → Right → Root

        1
       / \
      2   3
     / \
    4   5

순서: 4 → 5 → 2 → 3 → 1
(루트를 마지막에!)
 
def postorder(node):
    if node is None:
        return
    
    postorder(node.left)   # 왼쪽
    postorder(node.right)  # 오른쪽
    print(node.val)        # 루트

용도: 트리 삭제 (자식부터 지워야 함)

 

 

레벨 순회 (Level Order) - BFS

        1
       / \
      2   3
     / \
    4   5

순서: 1 → 2 → 3 → 4 → 5
(레벨별로!)
 
from collections import deque

def levelorder(root):
    if root is None:
        return
    
    queue = deque([root])
    
    while queue:
        node = queue.popleft()
        print(node.val)
        
        if node.left:
            queue.append(node.left)
        if node.right:
            queue.append(node.right)

 

정리

트리:

  • 계층 구조
  • 사이클 없음
  • 루트 하나

이진 트리:

  • 자식 최대 2개

순회:

  • 전위: Root → Left → Right
  • 중위: Left → Root → Right (정렬 순서)
  • 후위: Left → Right → Root (삭제)
  • 레벨: BFS (큐 사용)

 

이진 트리 vs 이진 탐색 트리

이진 트리 (Binary Tree)

  • 그냥 자식이 최대 2개인 트리
  • 순서 규칙 없음
 
 
      5
     / \
    8   3
   / \
  2   9

→ 아무렇게나 배치 가능

 

이진 탐색 트리 (BST - Binary Search Tree)

  • 자식이 최대 2개 + 순서 규칙 있음

규칙:

  • 왼쪽 자식 < 부모 < 오른쪽 자식
 
 
      5
     / \
    3   8
   / \   \
  2   4   9

확인:

  • 5의 왼쪽(3) < 5 < 5의 오른쪽(8) ✓
  • 3의 왼쪽(2) < 3 < 3의 오른쪽(4) ✓
  • 8의 오른쪽(9) > 8 ✓

 

BST의 핵심 특징

1. 중위 순회하면 정렬된 순서!

 
 
      5
     / \
    3   8
   / \   \
  2   4   9

중위 순회 (Left → Root → Right):
2 → 3 → 4 → 5 → 8 → 9

→ 오름차순 정렬!

 

2. 탐색이 빠름

 
 
      5
     / \
    3   8
   / \   \
  2   4   9

8을 찾는다면?
1. 5와 비교 → 8 > 5 → 오른쪽으로
2. 8 발견!

2단계만에 찾음!

시간복잡도:

  • 평균: O(log n)
  • 최악: O(n) (편향 트리일 때)

 

BST 연산

1. 탐색 (Search)

 
 
      5
     / \
    3   8
   / \   \
  2   4   9

4를 찾는다:
1. 5와 비교 → 4 < 5 → 왼쪽
2. 3과 비교 → 4 > 3 → 오른쪽
3. 4 발견!

과정:

  • 찾는 값 < 현재 노드 → 왼쪽
  • 찾는 값 > 현재 노드 → 오른쪽
  • 찾는 값 = 현재 노드 → 찾음!

 

2. 삽입 (Insert)

 
 
      5
     / \
    3   8
   / \
  2   4

6을 추가한다:
1. 5와 비교 → 6 > 5 → 오른쪽
2. 8과 비교 → 6 < 8 → 왼쪽
3. 빈 자리 → 여기 삽입!

결과:
      5
     / \
    3   8
   / \ /
  2  4 6

규칙:

  • 리프까지 내려가서 삽입
  • BST 규칙 유지

 

3. 삭제 (Delete)

3가지 경우:

Case 1: 자식 없음 (리프)

 
 
      5
     / \
    3   8
   / \
  2   4

2를 삭제:
→ 그냥 제거

      5
     / \
    3   8
     \
      4

 

Case 2: 자식 1개

 
 
      5
     / \
    3   8
     \   \
      4   9

3을 삭제:
→ 자식(4)을 3 자리로

      5
     / \
    4   8
         \
          9

 

Case 3: 자식 2개 (복잡!)

 
 
      5
     / \
    3   8
   / \   \
  2   4   9

5를 삭제:

방법 1: 왼쪽 서브트리의 최대값(4)으로 대체
      4
     / \
    3   8
   /     \
  2       9

방법 2: 오른쪽 서브트리의 최소값(8)으로 대체
      8
     / \
    3   9
   / \
  2   4

이유:

  • BST 규칙 유지해야 함
  • 왼쪽 최대값 또는 오른쪽 최소값만 가능

 

시간복잡도

연산평균최악

탐색 O(log n) O(n)
삽입 O(log n) O(n)
삭제 O(log n) O(n)

 

최악의 경우 - 편향 트리

 
 
삽입 순서: 1, 2, 3, 4, 5

결과:
1
 \
  2
   \
    3
     \
      4
       \
        5

→ 사실상 연결 리스트!
→ 탐색 O(n)

문제:

  • BST인데 느림
  • 균형이 안 맞음

해결:

  • 균형 이진 탐색 트리 (AVL, Red-Black Tree)

정리

이진 트리:

  • 자식 최대 2개
  • 규칙 없음

이진 탐색 트리 (BST):

  • 자식 최대 2개
  • 왼쪽 < 부모 < 오른쪽 (규칙 있음!)
  • 탐색/삽입/삭제 평균 O(log n)
  • 중위 순회 → 정렬됨

장점:

  • 탐색 빠름 (정렬된 배열처럼)
  • 삽입/삭제 가능 (배열보다 나음)

단점:

  • 편향되면 느림 (O(n))