Ch.6 트리 기초

BST — 정렬된 트리, 탐색/삽입

이진 탐색 트리(BST)의 정의와 속성을 이해한다BST에서 탐색과 삽입 연산을 구현한다

배열의 이진탐색을 트리에 담았다

이진 탐색 트리(BST)는 왼쪽 < 루트 < 오른쪽 규칙을 따르는 트리입니다. 이 단순한 규칙 하나가 O(log n) 탐색을 가능하게 합니다.

배열은 삽입이 느리고, 해시맵은 순서가 없다. BST는 둘 다 해결한다?

정렬 + 빠른 탐색 + 빠른 삽입 — BST가 왜 자료구조의 핵심인지 알아봅시다.

lightbulb

핵심 개념

BST(Binary Search Tree)

모든 노드에서 왼쪽 < 노드 < 오른쪽을 만족하는 이진 트리

BST 속성

중위 순회 시 오름차순으로 정렬된 결과를 얻는다


article

핵심 내용

이진 탐색 트리의 규칙은 딱 하나입니다

왼쪽 서브트리의 모든 값 < 루트 < 오른쪽 서브트리의 모든 값 이 규칙이 모든 서브트리에서 재귀적으로 성립합니다

BST 예시 8 / \ 3 10 / \ \ 1 6 14 / \ 4 7 중위 순회: [1, 3, 4, 6, 7, 8, 10, 14] ← 정렬!

찾고자 하는 값이 현재 노드보다 작으면 왼쪽, 크면 오른쪽으로 이동

def search_bst(root, target):
    # Base case: 못 찾았거나 찾았거나
    if not root:
        return None
    
    if target == root.val:
        return root          # 찾았다!
    elif target < root.val:
        return search_bst(root.left, target)   # 왼쪽으로
    else:
        return search_bst(root.right, target)  # 오른쪽으로

# 8에서 6을 찾는 과정:
# 8 → 6<8이니 왼쪽 → 3 → 6>3이니 오른쪽 → 6 찾았다!

매 단계에서 탐색 범위가 절반으로 줄어듭니다. 이진탐색과 똑같은 원리! O(log n)

# 반복(iterative) 버전 — 면접에서 이걸 선호하는 경우도 있음
def search_bst_iter(root, target):
    node = root
    while node:
        if target == node.val:
            return node
        elif target < node.val:
            node = node.left
        else:
            node = node.right
    return None  # 못 찾음

삽입도 탐색과 같은 경로를 따라갑니다. 빈 자리를 찾으면 거기에 넣으면 됩니다

def insert_bst(root, val):
    # 빈 자리를 찾으면 새 노드 생성
    if not root:
        return TreeNode(val)
    
    if val < root.val:
        root.left = insert_bst(root.left, val)
    elif val > root.val:
        root.right = insert_bst(root.right, val)
    # val == root.val 이면 중복 → 무시
    
    return root

# BST에 5를 삽입:
# 8 → 5<8 왼쪽 → 3 → 5>3 오른쪽 → 6 → 5<6 왼쪽 → 빈 자리! 삽입

삽입 후에도 BST 속성이 유지됩니다. 새 노드는 항상 리프 위치에 들어갑니다

BST의 성능은 트리의 모양에 달려 있습니다

균형 BST (Best/Average) • 탐색: O(log n) • 삽입: O(log n) • 삭제: O(log n) 편향 BST (Worst) • 탐색: O(n) • 삽입: O(n) • 삭제: O(n)

[1, 2, 3, 4, 5]를 순서대로 삽입하면? 오른쪽으로만 치우친 연결 리스트가 됩니다! 이것이 BST의 치명적 약점

# 편향 트리 예시 — 정렬된 데이터를 순서대로 삽입
# 1
#  \
#   2
#    \
#     3
#      \
#       4
#        \
#         5
# 높이 = n-1, 탐색 = O(n) ← 최악!

이 문제를 해결하는 것이 다음 레슨의 주제 — 균형 트리(AVL)입니다

면접 단골 문제: 주어진 트리가 올바른 BST인지 검증하라

def isValidBST(root, lo=float('-inf'), hi=float('inf')):
    if not root:
        return True
    
    # 현재 노드가 범위 밖이면 BST 아님
    if root.val <= lo or root.val >= hi:
        return False
    
    # 왼쪽은 상한을 root.val로,
    # 오른쪽은 하한을 root.val로 좁힘
    return (isValidBST(root.left, lo, root.val) and
            isValidBST(root.right, root.val, hi))

함정 주의! 단순히 `left.val < node.val < right.val`만 확인하면 안 됩니다. 서브트리의 모든 값이 범위 안에 있어야 합니다

Validate BST — 핵심 아이디어 • 각 노드에 허용 범위 (lo, hi) 전달 • 왼쪽으로 가면 상한(hi) = 현재 값 • 오른쪽으로 가면 하한(lo) = 현재 값 • 시간: O(n), 공간: O(h)

BST에서 탐색의 평균 시간 복잡도는?

정렬된 배열 [1,2,3,4,5]를 순서대로 BST에 삽입하면 어떻게 되는가?

BST에 새로운 값을 삽입하면 항상 리프 위치에 들어간다

edit_note

정리 노트

BST — 정렬된 트리

BST 핵심

규칙
왼쪽 < 루트 < 오른쪽 (모든 서브트리)
탐색/삽입
균형: O(log n), 편향: O(n)
중위 순회
오름차순 정렬 결과

면접 포인트

Validate BST
(lo, hi) 범위 전달 방식
편향 트리 문제
→ AVL/Red-Black으로 해결
image

시각 자료

다이어그램: ds-d47
다이어그램: ds-d48

퀴즈와 인터랙션으로 더 깊이 학습하세요

play_circle인터랙티브 레슨 시작