
- 루트 노드에서 leaf 노드로 가는 경로를 보았을 때 red black 트리는 한 경로가 다른 경로보다 2배 이상 길지 않다. 그래서 대체적으로 균형잡혀 있다.
- 각각의 노드는 color, key, left, right, p 속성을 가지고 있다.
- red black 트리는 아래 규칙을 만족하는 이진 탐색 트리이다.
규칙
- 모든 노드는 색을 가진다. (red 또는 black)
- 루트 노드는 black
- 모든 leaf 노드는 NIL, black
- red 노드는 red 자식 노드를 가질 수 없다.(2개의 black 자식을 가져야 한다.)
- 각 노드에서 leaf 노드로 가는 경로들은 같은 수의 black 노드를 가지고 있어야 한다.
회전

Left-Rotate 왼쪽 회전


- y의 왼쪽 서브트리는 x의 오른쪽 서브 트리가 된다.(바꾼다라는 표현이 헷갈림)
- y의 왼쪽 서브트리가 T.nil이 아니라면(비어있지 않다면)
y의 왼쪽 서브트리는 x를 가리키게 된다.(x의 자식 노드가 된다.) - y가 가리키는 곳이(포인터가) x가 가리키는 곳이 된다. 즉 y는 이제 x의 부모를 가리킨다.
- 만약 x의 포인터가 T.nil을 가리킨다면, 즉 루트 노드였다면 이제는 y가 루트 노드가 된다.
만약 x가 왼쪽 자식 노드였다면, y는 x의 부모의 왼쪽 자식 노드가 된다.
만약 x가 오른쪽 자식 노드였다면, y는 x 부모의 오른쪽 자식 노드가 된다. - 그러고 x를 y의 왼쪽 자식 노드로 만든다.
- x의 부모를 y로 만든다.
삽입(T에 z 넣기)

x = T.root
y = T.nil
while x =/= T.nil
y = x
if z.key < x.key
x = x.left
else x = x.right
z.p = y
if y == T.nil
T.root = z
elseif z.key < y.key
y.left = z
else y.right = z
z.left = T.nil
z.right = T.nil
z.color = RED
RB-INSERT-FIXUP(T, z)
- x = T.root
삽입하고자 하는 z와 비교될 대상 노드입니다. - y = T.nil
삽입하고자 하는 z의 부모 노드가 될 노드입니다. 현재는 x의 부모 노드입니다. - <삽입할 새로운 노드의 위치를 찾기 위한 과정>
현재 노드 x가 트리의 끝(T.nil)에 도달할 때까지 반복합니다.
y 변수에 x 값을 대입합니다. y는 계속해서 x의 부모가 됩니다.
탐색하면서 z의 키 값이 x의 키 값보다 작으면 x의 왼쪽 서브트리를 탐색하고, 크면 오른쪽 서브트리를 탐색합니다. - z가 들어갈 곳을 찾았으면, z가 y를 가리키게 합니다.(z의 부모 포인터를 y로 설정합니다.)
- 만약 y가 T.nil이면 z가 새로운 루트 노드입니다.
z가 루트 노드가 아니고 z의 키 값이 y의 키 값보다 작으면 z는 y의 왼쪽 자식 노드가 됩니다.
z가 루트 노드가 아니고 z의 키 값이 y의 키 값보다 크면 z는 y의 오른쪽 자식 노드가 됩니다. - z의 자식 노드를 T.nil로 설정하고 새로운 노드 z를 red로 설정합니다.
- 그리고 RB-INSERT-FIXUP 함수를 통해 새로운 노드가 추가된 red-black tree를 정리해줍니다.

RB-INSERT-FIXUP(T, z)
while z.p.color == RED
if z.p == z.p.p.left
y = z.p.p.right
if y.color == RED
z.p.color = BLACK
y.color = BLACK
z.p.p.color = RED
z = z.pp
else
if z == z.p.right
z = z.p
LEFT-ROTATE(T, z)
z.p.color = BLACK
z.p.p.color = RED
RIGHT-ROTATE(T, z.p.p)
else
y = z.p.p.left
if y.color == RED
z.p.color = BLACK
y.color = BLACK
z.p.p.color = RED
z = z.p.p
else
if z == z.p.left
z = z.p
RIGHT-ROTATE(T, z)
z.p.color = BLACK
z.p.p.color = RED
LEFT-ROTATE(T, z.p.p)
T.root.color = Black
RB 트리에 노드를 삽입한 후, RB 트리의 조건을 만족하도록 하는 함수
- while 루프를 사용하여 새로 삽입된 노드의 부모 노드가 빨간색동안 반복합니다.
- 만약 z의 부모가 왼쪽 자식이라면
- y는 z의 오른쪽 삼촌
- 만약 y의 색이 빨강이라면
- z의 부모(y의 형제) 노드는 검정색
- y의 색은 검정색
- z의 조부모 노드의 색은 빨간색
- z를 z의 조부모 노드로 이동합니다.
- 만약 y의 색이 검정이라면
- z가 z 부모 노드의 오른쪽 자식이라면
- z는 z의 부모 노드로 이동합니다.
- 그리고 왼쪽으로 회전합니다.
- z의 부모 노드는 검정색
- z의 조부모 노드는 빨간색
- 오른쪽으로 회전합니다.
- z가 z 부모 노드의 오른쪽 자식이라면
- 만약 z의 부모가 오른쪽 자식이라면
- y는 z의 왼쪽 삼촌
- 만약 y의 색이 빨강이라면
- z의 부모 노드는 검정색
- y의 색은 검정색
- z의 조부모 색은 빨간색
- z는 z의 조부모 노드로 이동합니다.
- 만약 y의 색이 검정이라면
- z가 z 부모 노드의 왼쪽 자식이라면
- z는 z의 부모 노드로 이동합니다.
- 그리고 오른쪽으로 회전합니다.
- z의 부모의 색은 검정색
- z의 조부모의 색은 빨간색
- 왼쪽으로 회전합니다.
- z가 z 부모 노드의 왼쪽 자식이라면
- 루트의 색상을 검정색으로 바꿉니다.
참고 자료
- Introduction to Algorithms - Thomas H. Cormen, Charles E. Leiserson, Ronald Rivest, Clifford Stein
* C언어로 작성한 코드는 https://github.com/SeryeongK/rbtree-lab 에 있습니다.
'자료구조' 카테고리의 다른 글
[자료구조] C로 연결 리스트 Linked List 구현하기 (0) | 2024.07.15 |
---|