AVL 트리와 레드 블랙 트리 (AVL Tree & Red-Black Tree)
한눈에 보기
자가 균형 이진 탐색 트리인 AVL 트리와 레드 블랙 트리를 비교한다. 균형 인수와 회전, 탐색과 삽입 비용, TreeMap이 레드 블랙 트리를 쓰는 이유를 정리했다.
최종 업데이트 2026.09.17
AVL 트리(AVL Tree)와 레드 블랙 트리(Red-Black Tree)는 삽입과 삭제가 일어나도 트리의 높이를 O(log n)으로 유지하는 자가 균형 이진 탐색 트리(Self-Balancing Binary Search Tree)다. AVL 트리는 모든 노드에서 좌우 서브트리의 높이 차이를 1 이하로 엄격하게 유지하고, 레드 블랙 트리는 노드 색상 규칙으로 더 느슨한 균형을 유지한다. 그 결과 AVL 트리는 탐색이 빠르고, 레드 블랙 트리는 삽입과 삭제 비용이 적어 자바(Java)의 TreeMap 같은 표준 라이브러리에 널리 채택되었다.
왜 자가 균형 트리가 필요한가
이진 탐색 트리(Binary Search Tree)는 왼쪽 서브트리에는 작은 값, 오른쪽 서브트리에는 큰 값을 두어 평균 O(log n)에 탐색한다. 그러나 이 성능은 트리가 균형 잡혀 있을 때만 성립한다. 예를 들어 1, 2, 3, 4, 5를 순서대로 삽입하면 트리는 오른쪽으로만 뻗은 연결 리스트 형태가 되고, 탐색과 삽입이 모두 O(n)으로 퇴화한다.
자가 균형 트리는 삽입이나 삭제로 균형이 깨질 때마다 회전(Rotation) 연산으로 구조를 재조정해 높이를 O(log n)으로 보장한다. 회전은 이진 탐색 트리의 정렬 순서를 깨뜨리지 않으면서 부모와 자식의 위치를 바꾸는 O(1) 연산이다.
AVL 트리: 균형 인수와 네 가지 회전
AVL 트리는 모든 노드에 대해 균형 인수(Balance Factor), 즉 왼쪽 서브트리 높이에서 오른쪽 서브트리 높이를 뺀 값이 -1, 0, 1 중 하나여야 한다. 삽입이나 삭제 후 어떤 노드의 균형 인수가 2 또는 -2가 되면 불균형이 발생한 모양에 따라 네 가지 회전으로 복구한다.
- LL 불균형: 왼쪽 자식의 왼쪽에 삽입되어 무너진 경우로, 오른쪽 회전 한 번으로 해결한다.
- RR 불균형: 오른쪽 자식의 오른쪽에 삽입된 경우로, 왼쪽 회전 한 번으로 해결한다.
- LR 불균형: 왼쪽 자식의 오른쪽에 삽입된 경우로, 자식을 먼저 왼쪽 회전한 뒤 자신을 오른쪽 회전한다.
- RL 불균형: 오른쪽 자식의 왼쪽에 삽입된 경우로, 자식을 오른쪽 회전한 뒤 자신을 왼쪽 회전한다.
오른쪽 회전의 핵심 로직을 코드로 표현하면 다음과 같다. y의 왼쪽 자식 x가 새로운 루트가 되고, x의 오른쪽 서브트리는 y의 왼쪽으로 옮겨진다.
def rotate_right(y):
x = y.left
t = x.right # x와 y 사이에 끼어 있던 서브트리
x.right = y
y.left = t
y.height = 1 + max(height(y.left), height(y.right))
x.height = 1 + max(height(x.left), height(x.right))
return x # 이 서브트리의 새 루트
레드 블랙 트리: 색상 규칙으로 유지하는 균형
레드 블랙 트리는 노드를 빨강 또는 검정으로 칠하고 다음 규칙을 항상 만족시킨다.
- 모든 노드는 빨강 아니면 검정이다.
- 루트(Root)는 검정이다.
- 모든 리프, 즉 NIL 노드는 검정으로 취급한다.
- 빨강 노드의 자식은 반드시 검정이다. 즉 빨강이 연속으로 나올 수 없다.
- 임의의 노드에서 그 아래 모든 리프까지의 경로에 있는 검정 노드 수는 같다.
규칙 4와 5를 함께 만족하면 가장 긴 경로가 가장 짧은 경로의 2배를 넘을 수 없다. 검정 노드 수가 같은 상태에서 빨강을 최대한 끼워 넣어도 길이가 2배까지만 늘어나기 때문이다. 따라서 높이는 최대 2 log(n+1)로 억제된다. 삽입 시 새 노드는 빨강으로 넣고, 규칙 위반이 생기면 삼촌 노드의 색에 따라 색 변경(Recoloring) 또는 회전으로 복구한다. 색 변경은 회전보다 저렴하므로 재조정 비용이 AVL 트리보다 평균적으로 적다.
두 트리 비교와 실제 사용처
| 항목 | AVL 트리 | 레드 블랙 트리 |
|---|---|---|
| 균형 조건 | 높이 차이 1 이하로 엄격 | 색상 규칙으로 느슨 |
| 최대 높이 | 약 1.44 log n | 약 2 log n |
| 탐색 | 더 빠름 (높이가 낮음) | 상대적으로 느림 |
| 삽입, 삭제 | 회전이 잦아 비용 큼 | 재조정이 적어 비용 작음 |
| 추가 저장 정보 | 높이 또는 균형 인수 | 색상 1비트 |
| 적합한 상황 | 조회 위주 워크로드 | 삽입과 삭제가 잦은 워크로드 |
모든 연산의 시간 복잡도는 두 트리 모두 최악 기준 O(log n)으로 같다. 차이는 상수 계수와 재조정 빈도에서 나온다. 실무 라이브러리는 삽입과 삭제가 섞인 범용 워크로드를 가정하므로 대부분 레드 블랙 트리를 선택했다. 자바의 TreeMap과 TreeSet, C++ 표준 라이브러리의 map과 set이 레드 블랙 트리로 구현되어 있고, 자바 8부터는 HashMap의 한 버킷에 노드가 8개를 넘으면 연결 리스트를 레드 블랙 트리로 바꿔 최악 성능을 O(log n)으로 방어한다. 리눅스(Linux) 커널도 CFS 스케줄러와 가상 메모리 영역 관리에 레드 블랙 트리를 사용한다.
면접에서 이렇게 물어본다
- 이진 탐색 트리가 O(n)으로 퇴화하는 경우를 예로 들고, 자가 균형 트리가 이를 어떻게 막는지 설명해 보라.
- AVL 트리의 LR 불균형은 회전 한 번으로 해결되지 않는 이유가 무엇인지 설명해 보라.
- 레드 블랙 트리의 다섯 가지 규칙을 말하고, 이 규칙이 높이를 어떻게 O(log n)으로 보장하는지 설명해 보라.
- 탐색과 삽입 삭제 각각의 관점에서 AVL 트리와 레드 블랙 트리 중 무엇을 선택할지 근거를 들어 보라.
- 자바의 HashMap이 내부적으로 레드 블랙 트리를 사용하는 시점과 그 이유를 설명해 보라.
자료구조에서 같이 읽기
- 배열 (Array)같은 타입의 데이터를 연속 메모리에 저장하는 기본 선형 자료구조인 배열을 다룬다. O(1) 인덱스 접근의 원리, 연산별 시간 복잡도, 동적 배열의 확장과 분할 상환 분석, 캐시 지역성까지 정리했다.
- Array vs ArrayList vs LinkedList배열, ArrayList, LinkedList의 내부 저장 방식과 연산별 시간 복잡도를 비교한다. 캐시 지역성 때문에 실무에서 ArrayList가 유리한 이유와 상황별 선택 기준을 정리했다.
- B 트리와 B+ 트리 (B-Tree & B+ Tree)한 노드에 여러 키를 담아 높이를 낮춘 B 트리와 리프에 데이터를 모아 연결한 B+ 트리를 다룬다. 디스크 I/O 최소화 원리와 데이터베이스 인덱스가 B+ 트리를 쓰는 이유를 정리했다.
- 이진 탐색 트리 (Binary Search Tree)왼쪽은 작은 값, 오른쪽은 큰 값이라는 규칙으로 평균 O(log n) 탐색을 만드는 이진 탐색 트리를 다룬다. 삽입과 삭제 과정, 편향 시 퇴화 문제와 자가 균형 트리, 해시 테이블과의 선택 기준을 정리했다.
이 개념, 내 코드에서는 어떻게 물어볼까요
데브핏(DevFit)에 채용공고 URL을 붙여 넣고 레포지토리를 연결하면, 내가 쓴 커밋에서 예상 질문과 어필 포인트를 만듭니다. 하루 10회까지 무료입니다. 합불 판정이나 지원자 랭킹은 만들지 않고, 최종 판단은 사람이 합니다.
공고 넣고 시작하기