X에 대해: 왼쪽 서브트리의 모든 값 < X < 오른쪽 서브트리의 모든 값struct Node {
int key;
Node* left = nullptr;
Node* right = nullptr;
};
BST 구조 예시
[10]
/ \
[5] [15]
/ \ / \
[3] [8][12][20]
In-Order(중위 순회): 3 -> 5 -> 8 -> 10 -> 12 -> 15 -> 20 (오름차순)
트리 높이를 h라고 하면 대부분 연산은 O(h)입니다.
| 연산 | 복잡도 |
|---|---|
| search | O(h) |
| insert | O(h) |
| delete | O(h) |
| min / max | O(h) |
h ~= log N -> O(log N)h ~= N -> O(N)Node* Search(Node* root, int key) {
Node* cur = root;
while (cur) {
if (key == cur->key) return cur;
if (key < cur->key) cur = cur->left;
else cur = cur->right;
}
return nullptr;
}
O(h).Node* Insert(Node* root, int key) {
if (!root) return new Node{key};
if (key < root->key) root->left = Insert(root->left, key);
else if (key > root->key) root->right = Insert(root->right, key);
// else: 중복 정책 처리
return root;
}
| 삭제 대상 노드 상태 | 처리 방식 |
|---|---|
| 자식 0개(리프) | 그냥 제거 |
| 자식 1개 | 자식을 부모와 직접 연결 |
| 자식 2개 | 후속자(successor) 또는 전임자(predecessor)로 대체 후 재삭제 |
자식 2개 케이스(가장 중요):
Node* FindMin(Node* x) {
while (x && x->left) x = x->left;
return x;
}
min: 왼쪽으로 끝까지 이동max: 오른쪽으로 끝까지 이동next(in-order successor):minprev(in-order predecessor)는 위 규칙의 좌우 반대next 찾기 직관
케이스 A) 오른쪽 있음
node=10, right=15 -> next = min(15-subtree) = 12
케이스 B) 오른쪽 없음
부모로 올라가며 "내가 왼쪽 자식이 되는 첫 조상"을 찾음
정렬된 값이 순서대로 들어오면 아래처럼 편향 트리가 됩니다.
1
\
2
\
3
\
4
N에 가까워져 탐색/삽입/삭제가 O(N)으로 악화됩니다.| 실수 | 문제 |
|---|---|
| BST 규칙을 "부모와 자식만" 비교로 이해 | 서브트리 전체 조건 위반 가능 |
| 삭제 2자식 케이스에서 후속자 노드 자체를 잘못 연결 | 트리 구조 깨짐/메모리 오류 |
| 중복 키 정책을 정하지 않고 구현 | 동작 불일치/버그 |
복잡도를 항상 O(log N)으로 단정 | 편향 트리에서 O(N) |
O(h)로 표현하는가?