본문으로 건너뛰기
자료구조 · 알고리즘 기초집LESSON 17

이진 탐색 트리: 삽입·검색·삭제의 원리

난이도초급 → 중급 입문
예상 시간40분
선수지식이전 강의

17강. 이진 탐색 트리: 삽입·검색·삭제의 원리

1. 이번 강의에서 해결할 문제

정렬된 순서를 유지하면서 점수를 계속 추가하고 찾고 싶지만 배열 중간 삽입은 원소 이동이 필요합니다.

2. 학습 목표

3. 핵심 개념

이진 탐색 트리(BST)는 각 노드보다 작은 키를 왼쪽, 큰 키를 오른쪽에 둡니다. 중복 정책은 개수 저장, 한쪽 배치, 거부 중 하나를 명시해야 합니다. 삭제는 리프, 자식 하나, 자식 둘의 경우로 나뉘며 자식 둘이면 오른쪽 하위 트리의 최솟값 같은 후계자로 대체합니다. 이 구조 자체는 균형을 보장하지 않습니다.

4. 단계별 실습

1. 예제 파일 작성

실행 환경: 코드 편집기

실행 위치: C:\dev\game-ranking-algorithms

실행 전 확인: 같은 이름의 파일이 있다면 덮어쓰기 전에 Git diff로 변경 범위를 확인합니다. 선택한 LTS JDK의 java -versionjavac -version이 모두 실행되어야 합니다.

대상 파일: src/ScoreSearchTree.java

src/ScoreSearchTree.java
public class ScoreSearchTree {
static final class Node {
int score, count = 1;
Node left, right;
Node(int score) { this.score = score; }
}
private Node root;

void add(int score) { root = add(root, score); }
Node add(Node node, int score) {
if (node == null) return new Node(score);
if (score < node.score) node.left = add(node.left, score);
else if (score > node.score) node.right = add(node.right, score);
else node.count++;
return node;
}
int count(int score) {
Node node = root;
while (node != null) {
if (score == node.score) return node.count;
node = score < node.score ? node.left : node.right;
}
return 0;
}

void remove(int score) { root = remove(root, score); }
Node remove(Node node, int score) {
if (node == null) return null;
if (score < node.score) node.left = remove(node.left, score);
else if (score > node.score) node.right = remove(node.right, score);
else if (node.count > 1) node.count--;
else if (node.left == null) return node.right;
else if (node.right == null) return node.left;
else {
Node successor = min(node.right);
node.score = successor.score;
node.count = successor.count;
node.right = removeAll(node.right, successor.score);
}
return node;
}
Node removeAll(Node node, int score) {
if (score < node.score) node.left = removeAll(node.left, score);
else if (score > node.score) node.right = removeAll(node.right, score);
else return node.right;
return node;
}
Node min(Node node) {
while (node.left != null) node = node.left;
return node;
}

public static void main(String[] args) {
ScoreSearchTree tree = new ScoreSearchTree();
for (int score : new int[]{1000, 700, 1300, 1000}) tree.add(score);
System.out.println("1000점 개수: " + tree.count(1000));
tree.remove(1000);
tree.remove(700);
System.out.println("삭제 후 1000점 개수: " + tree.count(1000));
System.out.println("삭제 후 700점 개수: " + tree.count(700));
System.out.println("900점 개수: " + tree.count(900));
}
}

2. PowerShell에서 컴파일·실행

실행 환경: Windows PowerShell

실행 위치: C:\dev\game-ranking-algorithms

실행 전 확인: src/ScoreSearchTree.java가 저장되었고 out 폴더에는 삭제해도 되는 컴파일 결과만 있는지 확인합니다.

대상: src/ScoreSearchTree.javaout 아래 생성되는 class 파일

Windows PowerShell
Set-Location C:\dev\game-ranking-algorithms
New-Item -ItemType Directory -Force .\out | Out-Null
javac -Xlint:all -d .\out .\src\ScoreSearchTree.java
java -cp .\out ScoreSearchTree

예상 결과: 1000점 개수는 2에서 한 번 삭제 후 1이 되고, 삭제한 700점과 존재하지 않는 900점 개수는 0이 출력됩니다.

실행 시간은 PC의 CPU·메모리, JDK 버전, JVM 워밍업, 백그라운드 작업과 입력 분포에 따라 달라질 수 있습니다. 측정값은 같은 조건에서 여러 번 비교하고 Big-O 분석과 함께 해석합니다.

5. 코드와 알고리즘이 동작하는 이유

비교할 때마다 왼쪽 또는 오른쪽 하위 트리 하나만 선택합니다. 삭제는 중복 개수를 줄이거나 자식 0·1개를 바로 연결하고, 자식 둘이면 오른쪽의 최소 후계자와 그 중복 개수를 옮겨 순서 불변식을 지킵니다. 높이 h에 대해 삽입·검색·삭제는 O(h)입니다. 균형에 가까우면 평균 O(log n)이지만 정렬 순서로 삽입해 편향되면 최악 O(n)입니다. 노드는 O(n) 공간을 사용합니다.

6. 자주 하는 실수와 해결법

7. 직접 실습

8. 이해 점검 질문 3개

9. 핵심 요약

MINI QUIZ

이진 탐색 트리: 삽입·검색·삭제의 원리 미니 퀴즈

선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.

0 / 2
  1. 문제 1“이진 탐색 트리: 삽입·검색·삭제의 원리”의 위험한 선택을 피하려면 어떤 원칙을 적용해야 하나요?
  2. 문제 2‘중복 키 정책 없이 한쪽에 계속 넣기’ 상태에 관한 “이진 탐색 트리: 삽입·검색·삭제의 원리” 본문의 설명으로 가장 알맞은 것은 무엇인가요?
LESSON STATUS

학습을 마쳤나요?

직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.

17강. 이진 탐색 트리: 삽입·검색·삭제의 원리 미완료 상태