맨위로가기

레드-블랙 트리

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.

1. 개요

레드-블랙 트리는 컴퓨터 과학에서 비교 가능한 데이터를 효율적으로 정렬하는 데 사용되는 이진 탐색 트리의 한 종류이다. 각 노드는 '레드' 또는 '블랙'의 색상 속성을 가지며, 이진 탐색 트리의 조건과 함께 특정 규칙을 만족해야 한다. 이러한 규칙은 트리의 균형을 유지하여 삽입, 삭제, 검색 연산의 시간 복잡도를 O(log n)으로 보장한다. 1972년 루돌프 바이어가 B-트리의 특별한 경우로 개발했으며, 1978년 레오니다스 J. 기바스와 로버트 세지윅에 의해 레드-블랙 트리로 발전했다. 레드-블랙 트리는 실시간 처리, 계산 기하학, 리눅스 커널의 스케줄러 등 다양한 분야에 활용되며, 함수형 프로그래밍에서도 유용하게 사용된다.

더 읽어볼만한 페이지

  • 1972년 컴퓨팅 - 프롤로그 (프로그래밍 언어)
    프롤로그는 알랭 콜메로에르가 개발한 논리 프로그래밍 언어로, 사실과 규칙 기반 데이터베이스에 대한 질의를 통해 프로그램을 실행하며, 단일화, 백트래킹, 논리 변수 바인딩을 핵심 특징으로 인공지능, 자연어 처리 등에 활용된다.
  • 1972년 컴퓨팅 - SAP SE
    SAP SE는 독일의 다국적 소프트웨어 기업으로, 전사적 자원 관리(ERP) 소프트웨어를 주력으로 다양한 소프트웨어 제품 및 서비스를 제공하며, 클라우드 기반 기술로의 전환과 사업 확장, 그리고 사회적 책임 관련 논란이 있다.
  • 탐색 트리 - AA 트리
    AA 트리는 컴퓨터 과학의 자료 구조 중 하나이며, 학술 연구 및 특정 기술 분야에서 활용된다.
  • 탐색 트리 - 스플레이 트리
    스플레이 트리는 스플레이 연산을 통해 자가 균형을 유지하며 최근 접근 노드의 빠른 접근을 가능하게 하는 이진 탐색 트리로, 분할 상환 분석 시 평균적으로 O(log n)의 시간 복잡도를 가진다.
  • 분할 상환 자료 구조 - 스플레이 트리
    스플레이 트리는 스플레이 연산을 통해 자가 균형을 유지하며 최근 접근 노드의 빠른 접근을 가능하게 하는 이진 탐색 트리로, 분할 상환 분석 시 평균적으로 O(log n)의 시간 복잡도를 가진다.
  • 분할 상환 자료 구조 - 피보나치 힙
    피보나치 힙은 최소 힙 속성을 가진 트리들의 집합으로, 각 노드의 차수를 특정 로그 값 이하로 유지하여 효율적인 삽입, 병합, 최소값 검색 연산을 지원하며, 다익스트라 알고리즘과 같은 그래프 알고리즘의 성능 향상에 활용된다.
레드-블랙 트리
개요
유형트리
고안자레오니다스 J. 기바스와 로버트 세지윅
고안 연도1978년
성능
공간 (평균)O(n)
탐색 (평균)O(log n)
탐색 (최악)O(log n)
삽입 (평균)O(log n)
삽입 (최악)O(log n)
삭제 (평균)O(log n)
삭제 (최악)O(log n)

2. 용어

레드-블랙 트리는 이진 탐색 트리의 특수한 형태로서, 컴퓨터 과학에서 숫자 등의 비교 가능한 자료를 정리하는 데 쓰이는 자료 구조이다. 레드-블랙 트리에서 사용되는 용어는 다음과 같다.


  • '''노드(node, 분기점)''': 이진 트리에서 각각의 자료가 저장되는 곳이다.
  • '''루트 노드(root node)''': 트리 구조에서 최상위에 있는 노드이다.
  • '''리프 노드(leaf node)''': 자식 노드가 없는 노드로, 트리의 가장자리에 위치한다. 레드-블랙 트리에서는 자료를 가지고 있지 않은 빈 노드(NIL)이다.
  • '''부분 트리(sub-tree)''': 트리의 노드 중 하나를 루트 노드로 하고 그 자신과 자식 노드들로 이루어진 트리이다.
  • '''내부 노드''': 키 및/또는 데이터를 가지고 있는 노드이다. 이 문서에서는 비-NIL 노드라고도 부른다.
  • '''NIL 노드''': 자식이 존재하지 않음을 나타내는 노드로, 실제 노드가 아니고 데이터를 포함하지 않는다. 널 포인터 또는 센티넬 노드를 가리킨다. 이 문서에서는 `NIL` 값을 갖는 상수로 표현한다.
  • '''블랙 깊이''': 루트에서 해당 노드까지의 검은색 노드 수(즉, 검은색 조상 수)이다.
  • '''블랙 높이''': 루트에서 리프까지의 모든 경로에서 검은색 노드의 수이다. 또는 모든 리프 노드의 블랙 깊이로 정의할 수 있다. NIL 노드의 블랙 높이는 0으로 설정된다.


레드-블랙 트리를 포함한 이진 탐색 트리는, 모든 노드에 대해 다음 조건을 만족한다.

  • 자신이 가진 자료는 자신보다 오른쪽에 위치한 부분트리가 가지고 있는 모든 자료보다 작거나 같다.
  • 자신이 가진 자료는 자신보다 왼쪽에 위치한 부분트리가 가지고 있는 모든 자료보다 크거나 같다.


이러한 특성 때문에 특정 값을 빠르게 찾아 낼 수 있으며, 각 구성원소(elements)간의 효율적인 in-order traversal이 가능하다.

3. 역사

1972년, 루돌프 바이어[4]는 B-트리의 특별한 4차 정렬 사례인 자료 구조를 발명했다. 이 트리들은 루트에서 리프까지의 모든 경로를 동일한 노드 수로 유지하여 완벽하게 균형 잡힌 트리를 만들었다. 그러나, 이것들은 ''이진'' 검색 트리가 아니었다. 바이어는 그의 논문에서 그것들을 "대칭 이진 B-트리"라고 불렀고, 나중에는 2–3–4 트리 또는 2-3 트리로 대중화되었다.[5]

1978년 논문 "균형 트리를 위한 이색 프레임워크"에서[6] 레오니다스 J. 기바스와 로버트 세지윅은 대칭 이진 B-트리에서 레드-블랙 트리를 파생시켰다.[7] "빨간색" 색상은 저자들이 제록스 PARC에서 일하면서 사용 가능한 컬러 레이저 프린터가 생성한 가장 보기 좋은 색상이었기 때문에 선택되었다.[8] 기바스는 또한 그들이 트리를 그리는 데 사용할 수 있는 빨간색과 검은색 펜 때문이라고 언급했다.[9]

1993년, 아르네 안데르손은 삽입 및 삭제 연산을 단순화하기 위해 오른쪽으로 기울어진 트리의 아이디어를 도입했다.[10]

1999년, 크리스 오카사키는 삽입 연산을 순수하게 기능적으로 만드는 방법을 보여주었다. 그의 균형 함수는 4가지 불균형 경우와 하나의 기본 균형 경우만 처리하면 되었다.[11]

원래 알고리즘은 8가지 불균형 경우를 사용했지만, 6가지 불균형 경우로 줄였다.[1] 세지윅은 삽입 연산이 단 46줄의 자바 코드로 구현될 수 있음을 보여주었다.[12][13] 2008년, 세지윅은 삽입 및 삭제 연산을 단순화하는 안데르손의 아이디어를 활용하여 왼쪽으로 기울어진 레드-블랙 트리를 제안했다. 세지윅은 원래 두 자녀가 빨간색인 노드를 허용하여 그의 트리를 2-3-4 트리와 더 가깝게 만들었지만, 나중에 이 제약 조건이 추가되어 새로운 트리를 2-3 트리와 더 가깝게 만들었다. 세지윅은 삽입 알고리즘을 단 33줄로 구현하여 원래의 46줄 코드를 상당히 단축했다.[14][15]

2-노드는 단일 검은색 노드에 매핑됩니다. 3-노드는 빨간색 자식을 가진 검은색 노드에 매핑됩니다. 4-노드는 두 개의 빨간색 자식을 가진 검은색 노드에 매핑됩니다.
2–3–4 트리와 레드-블랙 트리의 유사점


레드-블랙 트리는 차수 4의 B-트리인 2–3–4 트리와 구조적으로 유사하다.[18] 2-3-4 트리에서 각 노드는 1개에서 3개의 값을 포함할 수 있으며 2개에서 4개의 자식을 가질 수 있다. 이 2-3-4 노드는 위 그림에 표시된 것처럼 레드-블랙 트리에서 검은색 노드 – 빨간색 자식 그룹에 해당한다. 이것은 1대1 대응이 아닌데, 3-노드는 두 가지 표현을 가지기 때문이다. 빨간색 자식은 왼쪽에 있을 수도 있고 오른쪽에 있을 수도 있다. 왼쪽 편향 레드-블랙 트리 변형은 왼쪽 자식 표현만 허용하여 이 관계를 정확히 1대1로 만든다. 모든 2-3-4 노드는 해당 검은색 노드를 가지므로 레드-블랙 트리의 불변성 4는 2-3-4 트리의 모든 잎이 같은 레벨에 있다는 것을 의미하는 것과 같다.

구조적 유사성에도 불구하고 레드-블랙 트리에 대한 연산은 B-트리보다 더 경제적이다. B-트리는 가변 길이 벡터 관리가 필요하지만 레드-블랙 트리는 단순히 이진 트리이다.[19]

4. 특성

레드-블랙 트리는 각 노드가 ''레드''나 ''블랙''이라는 ''색상'' 속성을 가진 이진 탐색 트리이다. 일반적인 이진 탐색 트리의 조건에 다음의 추가 조건을 만족해야 유효한 레드-블랙 트리가 된다.[49]

# 노드는 레드 혹은 블랙 중 하나이다.

# 루트 노드는 블랙이다.

# 모든 리프 노드(NIL)는 블랙이다.

# 레드 노드의 자식 노드는 모두 블랙이다. (즉, 레드 노드는 연달아 나타날 수 없으며, 블랙 노드만이 레드 노드의 부모 노드가 될 수 있다)

# 어떤 노드에서 시작하여 그 노드의 하위 리프 노드에 도달하는 모든 경로에는 리프 노드를 제외하고 모두 같은 개수의 블랙 노드가 있다.

위 조건들을 만족하면, 레드-블랙 트리는 다음과 같은 중요한 특성을 갖는다. 루트 노드에서 가장 먼 잎 노드 경로까지의 거리가, 가장 가까운 잎 노드 경로까지의 거리의 두 배보다 항상 작다. 즉, 레드-블랙 트리는 개략적으로 균형이 잡혀 있다. 따라서 삽입, 삭제, 검색 시 최악의 경우 시간 복잡도가 트리의 높이에 따라 결정되기 때문에 일반적인 이진 탐색 트리에 비해 효율적이다.

이러한 특성을 가지는 이유는 네 번째 속성에 따라 어떤 경로에도 레드 노드가 연이어 나타날 수 없기 때문이다. 최단 경로는 모두 블랙 노드로만 구성되며, 최장 경로는 블랙 노드와 레드 노드가 번갈아 나타난다. 다섯 번째 속성에 따라 모든 경로에서 블랙 노드의 수가 같으므로, 최장 경로의 거리는 최단 경로 거리의 두 배를 넘을 수 없다.

이진 탐색 트리에 추가되는 요구 사항은 다음과 같다.

# 모든 노드는 빨간색 또는 검은색이다.

# 모든 NIL 노드(그림 1)는 검은색으로 간주한다.

# 빨간색 노드는 빨간색 자식을 가질 수 없다.

# 주어진 노드에서 자손 NIL 노드까지의 모든 경로는 동일한 수의 검은색 노드를 통과한다.

# (결론) 노드 '''N'''이 정확히 하나의 자식만 갖는 경우, 그 자식은 빨간색이어야 한다. 자식이 검은색이면, 자식의 NIL 후손이 '''N'''의 NIL 자식과 다른 검은색 깊이에 위치하여 요구 사항 4를 위반하기 때문이다.

Cormen & al.[17] 등 일부 저자는 "루트는 검은색"을 다섯 번째 요구 사항으로 주장하지만, Mehlhorn & Sanders[16]나 Sedgewick & Wayne[15]은 그렇게 주장하지 않는다. 루트는 항상 빨간색에서 검은색으로 변경할 수 있으므로 이 규칙은 분석에 거의 영향을 미치지 않는다. 이 문서에서도 재귀 알고리즘과 증명을 약간 방해하기 때문에 이 규칙을 생략한다.

예를 들어, 검은색 노드로만 구성된 모든 완전 이진 트리는 레드-블랙 트리이다.

레드-블랙 트리의 중요한 속성은 ''루트에서 가장 먼 리프까지의 경로는 루트에서 가장 가까운 리프까지의 경로보다 두 배 이상 길지 않다''는 것이다. 그 결과 트리는 높이 균형을 이루게 된다. 삽입, 삭제 및 값 찾기와 같은 작업은 트리의 높이 h에 비례하는 최악의 경우 시간을 필요로 하므로, 이 높이에 대한 상한은 레드-블랙 트리가 최악의 경우, 즉 항목 수 n에 대해 로그가 되도록 허용한다. 이는 일반적인 이진 탐색 트리와는 다른 점이다. 수학적 증명은 경계의 증명 섹션을 참조하면 된다.

5. 동작

레드-블랙 트리의 읽기 전용 동작(탐색 등)은 이진 탐색 트리의 읽기 전용 동작의 구현을 변경하지 않아도 되는데, 이는 레드-블랙 트리가 이진 탐색 트리의 특수한 한 형태이기 때문이다. 그러나 삽입(insertion)과 삭제(removal)의 경우 이진 탐색 트리의 구현에 따른 동작만으로는 레드-블랙 트리의 특성을 만족하지 못한다. 다시 레드-블랙 트리의 특성을 만족하게 만들기 위해서는 O(log ''n'') 또는 amortized O(1)번의 색 변환과(실제로는 매우 빨리 이루어진다) 최대 3회의 트리 회전(tree rotation)이 필요하다(삽입의 경우 2회). 삽입과 삭제는 복잡한 동작이지만, 그 복잡도는 여전히 O(log ''n'')이다.[29]

아래는 삽입 및 삭제 연산의 세부 사항을 설명하는 예제 C++ 코드이다.

```c

// 기본 형식 정의:

enum color_t { BLACK, RED };

struct RBnode { // 레드-블랙 트리의 노드

RBnode* parent; // 루트 노드인 경우 == NIL

RBnode* child[2]; // 자식이 비어있는 경우 == NIL

// 인덱스는 다음과 같다:

// LEFT := 0, if (key < parent->key)

// RIGHT := 1, if (key > parent->key)

enum color_t color;

int key;

};

#define NIL NULL // null pointer or pointer to sentinel node

#define LEFT 0

#define RIGHT 1

#define left child[LEFT]

#define right child[RIGHT]

struct RBtree { // 레드-블랙 트리

RBnode* root; // 트리가 비어있는 경우 == NIL

};

// 자식 방향 얻기 (∈ { LEFT, RIGHT })

// non-root non-NIL RBnode* N:

#define childDir(N) ( N == (N->parent)->right ? RIGHT : LEFT )

```

왼쪽 회전 및 오른쪽 회전, 애니메이션


```c

RBnode* RotateDirRoot(

RBtree* T, // 레드-블랙 트리

RBnode* P, // subtree의 루트 (T의 루트일 수 있음)

int dir) { // dir ∈ { LEFT, RIGHT }

RBnode* G = P->parent;

RBnode* S = P->child[1-dir];

RBnode* C;

assert(S != NIL); // pointer to true node required

C = S->child[dir];

P->child[1-dir] = C; if (C != NIL) C->parent = P;

S->child[ dir] = P; P->parent = S;

S->parent = G;

if (G != NULL)

G->child[ P == G->right ? RIGHT : LEFT ] = S;

else

T->root = S;

return S; // subtree의 새로운 루트

}

#define RotateDir(N,dir) RotateDirRoot(T,N,dir)

#define RotateLeft(N) RotateDirRoot(T,N,LEFT)

#define RotateRight(N) RotateDirRoot(T,N,RIGHT)

```

삽입과 삭제는 몇 가지 경우로 나뉘어 처리된다. 각 경우는 특정 노드, 에지, 색상의 조합으로 이루어지며, 재균형 조정을 통해 레드-블랙 트리의 속성을 유지한다.

  • baseline
    은 빨간색 노드를,
    baseline
    은 검은색 노드를,
    baseline
    는 빨간색 또는 검은색 노드를 나타낸다.
  • 변수 '''N'''은 현재 노드를 나타낸다.
  • 삼각형은 서브트리를 나타낸다.


삽입과 삭제의 자세한 과정은 복잡하지만, 핵심은 회전과 색 변환을 통해 트리의 균형을 유지하는 것이다.

5. 1. 검색

레드-블랙 트리의 읽기 전용 동작(탐색 등)은 이진 탐색 트리의 읽기 전용 동작의 구현을 변경하지 않아도 되는데, 이는 레드-블랙 트리가 이진 탐색 트리의 특수한 한 형태이기 때문이다. 그러나 삽입과 삭제의 경우 이진 탐색 트리의 구현에 따른 동작만으로는 레드-블랙 트리의 특성을 만족하지 못한다.

5. 2. 삽입

레드-블랙 트리의 삽입은 단순 이진 탐색 트리에서 노드를 삽입하는 것과 같이 노드를 삽입하고, 색을 붉은색으로 정하는 것으로 시작한다. 이진 탐색 트리에서와 같이, 항상 리프 노드에 새로운 노드가 삽입되며, 새로운 노드의 색은 붉은색이다. 그 다음 단계는 주위 노드의 색에 따라 달라지는데, '삼촌 노드(uncle node)'는 같은 높이에 있는 옆 노드(사촌)의 부모 노드(삼촌)를 의미한다. 레드-블랙 트리의 특성은 다음과 같이 추가된다.

  • 특성 3(모든 리프 노드는 검은색이다)은 언제나 변하지 않는다.
  • 특성 4(적색 노드의 모든(두) 자식은 검은색이다)는 적색 노드의 추가, 검은색 노드의 적색 노드로의 전환, 회전에 의해 위반될 수 있다.
  • 특성 5(어떤 노드로부터 시작되어 리프 노드에 도달하는 모든 경로에는 모두 같은 개수의 블랙 노드가 있다)는 검은색 노드의 추가, 적색 노드의 검은색 노드로의 전환, 회전에 의해 위반될 수 있다.


삽입하는 원소를 '''N''', '''N'''의 부모 노드를 '''P''', '''P'''의 부모를 '''G''' ('''N'''의 할아버지 노드), '''N'''의 삼촌 노드를 '''U'''로 나타낸다. 각 노드의 역할과 이름은 바뀔 수 있지만, 각 경우에 노드에 붙은 이름(label)은 최초 상황에서의 이름을 나타낸다.

삽입 과정에서 다음과 같은 경우들이 발생할 수 있다.
경우 1: '''N'''이 트리의 루트(root)에 위치하는 경우새로운 노드 '''N'''이 트리의 시작(root)에 위치한다. 이 경우, 레드-블랙 트리의 첫 번째 속성(트리의 시작은 검은색이다)을 만족하기 위해 '''N'''을 검은색으로 표시한다. 시작점으로부터 뻗어나가는 모든 경로에 검은색 노드를 하나 추가한 셈이 되므로 레드-블랙 트리의 다섯 번째 속성(한 노드에서부터 뻗어나가는 모든 경로에 대해 검은색 노드의 수는 같다)은 여전히 유효하다.
경우 2: '''N'''의 부모 노드 '''P'''가 검은색인 경우새로운 노드의 부모 노드 '''P'''가 검은색이라면, 레드-블랙 트리의 네 번째 속성(붉은색 노드의 모든 자식 노드는 검은색이다)은 유효하다. 이 경우 트리는 적절한 레드-블랙 트리이다. 레드-블랙 트리의 다섯 번째 속성도 문제가 없는데, 새로운 노드 '''N'''은 두개의 검은색 리프 노드를 자식으로 가지기 때문이다. 비록 '''N'''이 붉은색 노드라고 해도 '''N'''이 들어간 자리에 원래 위치했던 노드의 색이 검은색이었으므로, '''N'''의 자식 노드에게서 시작되는 경로는 모두 같은 수의 검은색 노드를 가지게 되고, 결과적으로 다섯 번째 속성은 유지된다.
경우 3: '''P'''와 '''U'''가 모두 붉은색인 경우
세 번째 경우의 도식


만약 부모 노드 '''P'''와 삼촌 노드 '''U'''가 모두 붉은색 노드라면, 레드-블랙 트리의 다섯 번째 속성을 유지하기 위해 '''P'''와 '''U'''를 모두 검은색으로 바꾸고 할아버지 노드 '''G'''를 붉은색으로 바꾼다. 이렇게 함으로써 붉은색 노드인 '''N'''은 검은색 부모 노드를 가지게 된다. 그런데 이번에는 할아버지 노드 '''G'''가 레드 블랙 트리의 두 번째 속성(root node는 검은색이다)이나 네 번째 속성(붉은색 노드의 두 자식 노드는 검은색이다)을 만족하지 않을 수 있다. 이를 해결하기 위해 '''G'''에 대해 첫 번째 경우부터 세 번째 경우까지를 재귀적으로 적용한다.
경우 4: '''P'''는 붉은색, '''U'''는 검은색, '''N'''은 '''P'''의 오른쪽 자식, '''P'''는 '''G'''의 왼쪽 자식인 경우
네 번째 경우의 도식


부모 노드 '''P'''가 붉은색인데, 삼촌 노드 '''U'''는 검은색이다; 또한 새로운 노드 '''N'''은 '''P'''의 오른쪽 자식 노드이며, '''P'''는 할아버지 노드 '''G'''의 왼쪽 자식 노드이다. 이 경우, '''N'''과 '''P'''의 역할을 변경하기 위해서 왼쪽 회전을 한다; 그 후, 부모 노드였던 '''P'''를 다섯 번째 경우에서 처리하게 되는데, 이는 레드-블랙 트리의 네 번째 속성을 아직 만족하지 않기 때문이다. 회전 작업은 몇몇 경로들이 이전에는 지나지 않았던 노드를 지나게 하지만, 양쪽 노드가 모두 붉은색이므로, 레드-블랙 트리의 다섯 번째 속성은 위반하지 않는다.[50]
경우 5: '''P'''는 붉은색, '''U'''는 검은색, '''N'''은 '''P'''의 왼쪽 자식, '''P'''는 '''G'''의 왼쪽 자식인 경우
다섯 번째 경우의 도식


부모 노드 '''P'''는 붉은색이지만 삼촌 노드 '''U'''는 검은색이고, 새로운 노드 '''N'''이 '''P'''의 왼쪽 자식 노드이고, '''P'''가 할아버지 노드 '''G'''의 왼쪽 자식 노드인 상황에서는 '''G'''에 대해 오른쪽 회전을 한다. 회전의 결과 이전의 부모 노드였던 '''P'''는 새로운 노드 '''N'''과 할아버지 노드 '''G'''를 자식 노드로 갖는다. '''G'''가 이전에 검은색이었고, '''P'''는 붉은색일 수밖에 없기 때문에, '''P'''와 '''G'''의 색을 반대로 바꾸면 레드-블랙 트리의 네 번째 속성을 만족한다. 레드-블랙 트리의 다섯 번째 속성은 계속 유지되는데, 이는 이전에 '''P'''를 포함하는 경로는 모두 '''G'''를 지나게 되고, 바뀐 후 '''G'''를 포함하는 경로는 모두 '''P'''를 지나기 때문이다. 바뀌기 전에는 '''G'''가, 바뀐 후에는 '''P'''가 '''P''', '''G''', '''N'''중 유일한 검은색 노드이다.

결론적으로, 삽입 동작은 치환 작업이며, 모든 호출(call)이 tail recursion이기 때문에, 복잡도는 여전히 O(log ''n'')이다.

5. 3. 삭제

레드-블랙 트리에서 탐색과 같은 읽기 전용 동작은 이진 탐색 트리의 구현을 변경하지 않아도 된다. 레드-블랙 트리가 이진 탐색 트리의 특수한 형태이기 때문이다. 그러나 삽입 및 삭제는 이진 탐색 트리의 구현만으로는 레드-블랙 트리의 특성을 만족시킬 수 없다. 이를 위해 O(log ''n'') 또는 분할 상환(amortized) O(1)번의 색 변환과 최대 3회의 트리 회전(삽입의 경우 2회)이 필요하다. 삽입과 삭제는 복잡하지만, 그 복잡도는 여전히 O(log ''n'')이다.

이진 탐색 트리에서 두 개의 non-leaf 자식 노드를 가진 노드 X를 삭제할 때, X의 왼쪽 서브트리에서 최댓값 또는 오른쪽 서브트리에서 최솟값을 갖는 노드 Y를 찾아 X에 Y의 값을 복사하고 Y를 지운다. 이때 Y는 최대 한 개의 non-leaf 자식을 갖는다. 따라서 삭제는 최대 한 개의 non-leaf 자식을 가진 노드를 삭제하는 문제로 단순화할 수 있다.

삭제할 노드를 '''M''', '''M'''의 선택된 자식 노드를 '''C'''라고 하자. '''M'''이 붉은 노드라면 '''C'''로 대체하면 된다. '''M'''이 검은 노드이고 '''C'''가 붉은 노드라면 '''C'''를 검은색으로 바꿔주면 된다.

'''M'''과 '''C'''가 모두 검은색일 때가 복잡하다. '''M'''을 '''C'''로 치환하고, '''C'''를 '''N''', '''C'''의 형제 노드를 '''S''', '''N'''의 새로운 부모를 '''P''', '''S'''의 왼쪽/오른쪽 자식을 각각 '''SL''', '''SR'''이라고 하자.

형제 노드는 다음 함수로 찾을 수 있다.

```c

struct node *sibling(struct node *n)

{

if (n == n->parent->left)

return n->parent->right;

else

return n->parent->left;

}

```

'''N'''과 '''N'''의 원래 부모가 모두 검정이라면, '''N'''을 지나는 경로에서 검은 노드가 하나 부족하게 되므로 트리의 재균형이 필요하다. 고려해야 할 경우는 다음과 같다.

  • '''Case 1:''' '''N'''이 새로운 루트가 되는 경우. 추가 작업은 필요없다.
  • '''Case 2:''' '''S'''가 빨강일 경우. '''P'''와 '''S'''의 색을 바꾸고 '''P'''에서 왼쪽으로 회전한다.
  • '''Case 3:''' '''P''', '''S''', '''S'''의 자식들이 검은색인 경우. '''S'''를 빨강으로 칠하고, '''P'''에서 case 1부터 다시 시작한다.
  • '''Case 4:''' '''S'''와 '''S'''의 자식들은 검은색이지만, '''P'''는 빨강인 경우. '''S'''와 '''P'''의 색을 바꾼다.
  • '''Case 5:''' '''S'''가 검정, '''S'''의 왼쪽 자식이 빨강, '''S'''의 오른쪽 자식이 검정이며, '''N'''이 부모의 왼쪽 자식인 경우. '''S'''를 오른쪽으로 회전하고, '''S'''와 '''S'''의 부모 노드 색깔을 바꾼다.
  • '''Case 6:''' '''S'''가 검은색, '''S'''의 오른쪽 자식이 빨강이며, '''N'''이 '''P'''의 왼쪽 자식인 경우. '''P'''를 왼쪽으로 회전하고, '''P'''와 '''S'''의 색을 바꾸고, '''S'''의 오른쪽 자식을 검은색으로 만든다.


이러한 과정을 통해 레드-블랙 트리의 특성을 유지하면서 노드를 삭제할 수 있다.

6. 응용

레드-블랙 트리는 자료의 삽입, 삭제, 검색에서 최악의 경우에도 일정한 실행 시간(O(\log n))을 보장한다.[20][21] 이는 실시간 처리와 같이 실행 시간이 중요한 경우뿐만 아니라, 일정한 실행 시간을 보장하는 다른 자료 구조를 만드는 데에도 유용하다. 예를 들어, 계산 기하학에 사용되는 많은 자료 구조들이 레드-블랙 트리를 기반으로 하며, 리눅스 커널의 완전 공정 스케줄러(CFS)와 epoll 시스템 호출은 레드-블랙 트리를 사용한다.[20][21]

AVL 트리는 레드-블랙 트리보다 더 엄격하게 균형이 잡혀 있어 삽입과 삭제 시 더 많은 회전이 필요할 수 있지만, 검색 속도는 더 빠르다. 이러한 특성 때문에 AVL 트리는 한 번 구축하고 재구성할 필요가 없는 데이터 구조(예: 언어 사전)에 적합하다.

레드-블랙 트리는 함수형 프로그래밍에서 특히 유용하며, 연관 배열이나 집합 등을 구현하는 데 사용된다. 이러한 구현에는 삽입, 삭제 시 O(\log n)만큼의 시간과 공간이 필요하다.

레드-블랙 트리는 2-3-4 트리와 등장변환이 가능하다.[18] 즉, 모든 2-3-4 트리에는 구성 원소와 그 순서가 같은 레드-블랙 트리가 최소한 하나 이상 존재한다. 2-3-4 트리에서의 삽입, 삭제 과정은 레드-블랙 트리에서의 색 전환(color-flipping)과 회전(rotation)과 같은 개념이므로, 2-3-4 트리는 레드-블랙 트리의 동작 과정을 이해하는 데 도움을 준다.

아이템 수에 비례하여 컴퓨터 프로세서를 이용할 수 있다면, 정렬된 아이템을 가지고 레드-블랙 트리를 만드는 병렬 알고리즘은 상수 시간이나 O(\log \log n)시간으로 구현될 수 있다. 빠른 검색, 삽입, 삭제를 위한 병렬 알고리즘도 알려져 있다.[51]

7. 유사 자료 구조

레드-블랙 트리는 차수 4의 B-트리인 2–3–4 트리와 구조적으로 유사하다.[18] 2–3–4 트리에서 각 노드는 1개에서 3개의 값을 포함할 수 있으며 2개에서 4개의 자식을 가질 수 있다. 모든 2-3-4 노드는 해당 검은색 노드를 가지므로 레드-블랙 트리의 불변성 4는 2-3-4 트리의 모든 잎이 같은 레벨에 있다는 것을 의미하는 것과 같다.

구조적 유사성에도 불구하고 레드-블랙 트리에 대한 연산은 B-트리보다 더 경제적이다. B-트리는 가변 길이 벡터 관리가 필요하지만 레드-블랙 트리는 단순히 이진 트리이다.[19]

AVL 트리O(\log n) 검색, 삽입 및 제거를 지원하는 또 다른 구조이다. AVL 트리는 레드-블랙으로 색칠될 수 있으며, 따라서 레드-블랙 트리의 부분 집합이다. AVL의 최악의 높이는 레드-블랙 트리의 최악의 높이의 0.720배이므로 AVL 트리가 더 엄격하게 균형을 이룬다. 79번의 실행에서 현실적인 테스트 사례를 사용한 Ben Pfaff의 성능 측정 결과 AVL과 RB 비율은 0.677과 1.077 사이, 중앙값은 0.947, 기하 평균은 0.910이다.[22]

2008년, 세지윅은 왼쪽 경사 레드-블랙 트리[23]라고 하는 레드-블랙 트리의 더 간단한 버전을 소개했다. LLRB는 모든 빨간색 링크가 삽입 및 삭제를 제외하고 왼쪽으로 기울어지는 추가 불변성을 유지한다.

빠른 검색을 위해 최적화된 트리 유형인 탱고 트리의 원래 설명은 데이터 구조의 일부로 특별히 레드-블랙 트리를 사용한다.[25]

참조

[1] 서적 Introduction to Algorithms MIT Press
[2] 웹사이트 Red–Black Trees http://pages.cs.wisc[...]
[3] 웹사이트 Red–Black Trees https://www.cs.auckl[...] 1998
[4] 간행물 Symmetric binary B-Trees: Data structure and maintenance algorithms
[5] 서적 Data Structures and Algorithms in Java Sams Publishing
[6] 간행물 A Dichromatic Framework for Balanced Trees
[7] 웹사이트 Red Black Trees http://eternallyconf[...] 2015-09-02
[8] AV media Red–Black BSTs https://www.coursera[...] Coursera
[9] 웹사이트 Where does the term "Red/Black Tree" come from? http://programmers.s[...] 2015-09-02
[10] 서적 Algorithms and Data Structures http://user.it.uu.se[...] Springer-Verlag Berlin Heidelberg 1993-08-11
[11] 간행물 Red–black trees in a functional setting 1999-01-01
[12] 서적 Algorithms https://archive.org/[...] Addison-Wesley
[13] 웹사이트 RedBlackBST.java http://algs4.cs.prin[...] 2018-04-07
[14] 웹사이트 Left-leaning Red–Black Trees https://sedgewick.io[...] 2008
[15] 서적 Algorithms http://algs4.cs.prin[...] Addison-Wesley Professional
[16] 서적 Algorithms and Data Structures: The Basic Toolbox http://people.mpi-in[...] Springer
[17] 서적 Introduction to Algorithms MIT Press
[18] 문서 Using Knuth’s definition of order: the maximum number of children
[19] 서적 Algorithms in C++ https://archive.org/[...] Addison-Wesley Professional
[20] 웹사이트 IBM Developer https://developer.ib[...] 2024-05-25
[21] 웹사이트 The Implementation of epoll (1) https://idndx.com/20[...] 2014-09
[22] 문서 Pfaff 2004
[23] 웹사이트 Robert Sedgewick http://www.cs.prince[...] 2020-06-04
[24] 웹사이트 Balanced Trees http://www.cs.prince[...] 2022-03-26
[25] 간행물 Dynamic Optimality—Almost http://erikdemaine.o[...]
[26] 웹사이트 How does a HashMap work in JAVA http://coding-geek.c[...] coding-geek.com
[27] 간행물 Amortized Computational Complexity http://www.cs.duke.e[...] 1985-04
[28] 문서 The important thing about these tree rotations is that they preserve the in-order sequence of the tree’s nodes.
[29] 웹사이트 Ben Pfaff (2007): Online HTML version of a well-documented collection of binary search tree and balanced tree library routines https://mirrors.suns[...]
[30] 문서 The left columns contain far less nodes than the right ones, especially for removal. This indicates that some efficiency can be gained by pulling the first iteration out of the rebalancing loops of insertion and deletion, because many of the named nodes are NIL nodes in the first iteration and definitively non-NIL later. (See also this remark.)
[31] 문서 Rotations have been placed before recoloring for reasons of clarity. But the two commute, so that it is free choice to move the rotation to the tail.
[32] 문서 The same partitioning is found in Ben Pfaff.
[33] 문서 Dinesh P. Mehta, Sartaj Sahni (Ed.) ''Handbook of Data Structures and Applications'' 10.4.2
[34] 문서 Equality at the upper bound holds for the minimal RB trees RB2k of even height 2 \cdot k with n = 2 \cdot 2^k-2 nodes and only for those. So the inequality is marginally more precise than the widespread h < 2 \log_2(n+1) , e.g. in Cormen p. 264.
Moreover, these trees are binary trees that admit one and only one coloring conforming to the RB requirements 1 to 4. But there are further such trees, e.g. appending a child node to a black leaf always forces it to red. (A minimal RB tree of odd height allows to flip the root’s color from red to black.)

[35] 간행물 Symposium on Parallel Algorithms and Architectures, Proc. of 28th ACM Symp. Parallel Algorithms and Architectures (SPAA 2016) ACM
[36] 논문 Parallel algorithms for red–black trees
[37] 서적 Sequential and Parallel Algorithms and Data Structures : The Basic Toolbox Springer
[38] 논문 Fast Parallel Operations on Search Trees IEEE, Piscataway (NJ)
[39] 서적 An introduction to parallel algorithms http://zbmath.org/?q[...] Addison-Wesley
[40] 웹사이트 Red–Black Trees http://pages.cs.wisc[...] 2021-12-22
[41] 문서 リバラシングのみ (検索は無し)、[[#amortized|Tarjan and Mehlhorn]]を参照。
[42] 서적 Algorithms and Data Structures: The Basic Toolbox http://people.mpi-in[...] Springer
[43] 서적 Introduction to Algorithms MIT Press
[44] 논문 Amortized Computational Complexity http://www.cs.duke.e[...] 1985-04
[45] 문서 左の列は右の列よりはるかに少ないノードしか含まず、特に削除の場合はそうである。これは、挿入と削除のリバランシングループから最初の反復を引き出すことで、ある程度の効率を得られることを示している。なぜなら、名前付きノードの多くは最初の反復ではNILノードであり、後で決定的に非NILノードとなるからである。([[#C-eval|この章のコメント]]を参照.)
[46] 문서 わかりやすくするために、回転は再色付けの前に行われる。しかし、この2つのアクションは可換であるため、回転を[[末尾再帰|末尾]]に行うことも自由である。
[47] 문서 [[#Pfaff a|Ben Pfaff]]でも同じような分割が見られる。
[48] 문서 Dinesh P. Mehta, Sartaj Sahni (Ed.) ''Handbook of Data Structures and Applications'' 10.4.2
[49] 서적 Introduction to Algorithms (3rd ed.)
[50] 문서 "1\"이라는 이름이 붙어 있는 부분 트리(sub-tree)"
[51] 논문 Parallel algorithms for red–black trees http://www.sciencedi[...] Elsevier



본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.

문의하기 : help@durumis.com