|
| 1 | +# Red-Black Tree와 java.util에서의 구현 방식 1 |
| 2 | +- 1편 : Red-Black Tree란? |
| 3 | +- 2편 : java.util에서의 구현 코드로 이해하는 Red-Black Tree |
| 4 | + |
| 5 | +## 1. Red-Black Tree란 |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | +레드 블랙 트리란 Balanced Binary-Search Tree로, 모든 노드들을 빨간 색 혹은 검은 색으로 칠해 놓았기 때문에 레드-블랙 트리라고 부른다. <br> |
| 10 | + |
| 11 | + |
| 12 | + |
| 13 | +<br> |
| 14 | + |
| 15 | +어이 없지만, 이런 이유로 Red-Black 트리이다. 트리를 처음 고안한 논문의 저자들이 사용할 수 있었던 프린터가 만들어낸 가장 "멋진"색이기 때문이라고 한다. <br> <br> |
| 16 | + |
| 17 | +레드 블랙 트리는, 이런 빨강-검정으로 트리의 노드들을 색칠하고, 색에 대한 규칙을 세워 규칙을 어기는 경우 다시 균형을 맞춰 높이를 낮춘다. <br> |
| 18 | +균형을 맞추는 트리들이 균형을 맞추는 이유는 트리 Depth를 줄여 빠르게 탐색하기 위해서이다! 편향된 트리를 보면 알겠지만, 탐색 시간 복잡도가 O(N)이 된다. <br> |
| 19 | + |
| 20 | + |
| 21 | + |
| 22 | +가장 아래에 있는 데이터를 찾는 경우 데이터 전체 갯수만큼 탐색하게 된다. <br> |
| 23 | + |
| 24 | +균형을 맞췄을 때, 최악 탐색 시간 복잡도가 줄어들게 되기 떄문에, 균형을 맞추는 것이다. |
| 25 | + |
| 26 | + |
| 27 | + |
| 28 | +어떤 데이터를 탐색해도 균일하게 빠르다. (시간 복잡도 증명 추가 예정) <br> <br> |
| 29 | + |
| 30 | + |
| 31 | +## 2. Red-Black Tree 규칙 |
| 32 | +레드 블랙 트리는 균형을 맞추기 위해 색을 칠한다고 했다. 색칠된 노드들의 규칙을 살펴보자. |
| 33 | + |
| 34 | +1. 모든 노드는 빨강 혹은 검정으로 색칠 되어 있다. |
| 35 | +2. Root는 Black이다. |
| 36 | +3. 모든 Leaf Node는 Black이다. |
| 37 | +4. **빨강 노드는 연속될 수 없다.** |
| 38 | +5. Root 노드에서 모든 Leaf 노드까지 가는 경로의 Black Node 갯수는 같다! |
| 39 | +6. **새로 삽입되는 노드는 빨강이다.** |
| 40 | + |
| 41 | +<br> |
| 42 | + |
| 43 | +보통 5번까지만 규칙으로 언급되고, 6번은 이해를 용이하기 위해 기재했다. <br> |
| 44 | +**결국 새로운 노드는 무조건 빨강색으로 삽입되기 때문에, 빨강이 연속되는 순간이 나오게 되는 것이고, 빨강 노드가 연속되는 경우에 균형을 맞추는 작업이 이루어진다.** |
| 45 | + |
| 46 | + |
| 47 | + |
| 48 | +## 3. Red-Black Tree의 균형을 맞추기 위한 연산 |
| 49 | +Red-Black Tree가 균형을 맞추는 방식은 2가지이다. |
| 50 | +1. `Recoloring` : 주변 노드들의 색을 변경해 균형을 맞춘다. |
| 51 | +2. `Rotation` : 노드들을 회전 시켜 균형을 맞춘다. AVL Tree처럼 회전시킨다. Restructring이라고 표현하는 한글 아티클도 많은데, 이는 Recolor를 포함하는 표현인듯 하다. |
| 52 | + |
| 53 | +<br> |
| 54 | + |
| 55 | +두 가지 방법을 좀 더 자세히 살펴보자. 그다음 삽입과 삭제시에 무슨 일이 일어나는지 두 가지 방법을 통해 설명하겠다. 그리고 Java 라이브러리의 구현을 살펴보자. |
| 56 | + |
| 57 | +<br> |
| 58 | + |
| 59 | +### 설명하기 전에.. |
| 60 | +1. NIL 노드 : 아무 데이터가 없는 Black 노드이다. Red-Black Tree에서 규칙을 지키기 위해 데이터가 없는 리프 노드를 NIL 노드로 사용한다. |
| 61 | +2. Grand Parent 노드 : 부모의 부모 노드이다. |
| 62 | +3. Parent Sibling 노드 : 말 그대로 부모 노드의 형제 노드이다. Grand Parent Node의 자식 노드 중 부모 노드가 아닌 노드를 이렇게 부르겠다. |
| 63 | +4. 균형은 여러번 맞춰질 수 있다 : 균형을 맞추는 작업을 1회 실시하더라도, 빨간 노드가 연속하는 상황이 벌어질 수 있다. <br> 그런 경우 균형을 맞추는 작업은 여러번 반복된다. |
| 64 | + |
| 65 | +<br> |
| 66 | + |
| 67 | +### 3.1 Recoloring |
| 68 | + |
| 69 | +Recoloring은 말 그대로 노드들의 색을 다시 칠하는 것이다. <br> |
| 70 | + |
| 71 | + |
| 72 | + |
| 73 | +<br> |
| 74 | + |
| 75 | +위 그림에서 파란색 동그라미로 표시한 것이 새 노드이다. |
| 76 | +위 그림처럼 노드들의 색을 바꾸는 것인데, 삽입과 삭제시 색 변경이 다르게 진행될 수 있다. |
| 77 | + |
| 78 | +<br> |
| 79 | + |
| 80 | +### 삽입시 Recoloring |
| 81 | +**Recoloring은 삽입시 부모와, 부모의 형제 노드가 둘 다 빨간색인 경우 발생한다.** <br> |
| 82 | + |
| 83 | +1. 부모 노드와 Parent Sibling 노드를 검은 색으로 변경한다. |
| 84 | +2. 이후 Grand Parent Node를 빨간 색으로 변경한다. |
| 85 | + - 만약 Grand Parent Node가 루트였다면 검은 색으로 변경한다. |
| 86 | + - 만약 Grand Parent Node가 빨간색이 되면서, "빨간색 노드는 연속으로 2개가 올 수 없다"규칙이 깨지는 경우, Recoloring 혹은 Rotation을 진행한다. |
| 87 | + |
| 88 | + |
| 89 | +<br> |
| 90 | + |
| 91 | + |
| 92 | +### 3.2 Rotation |
| 93 | +노드들을 회전시킨다. <br> |
| 94 | +AVL Tree의 Rotation을 안다면 그것과 동일하다. <br> |
| 95 | +설명을 너무 복잡하게 하는 곳이 많은데, 그림과 코드를 먼저 보는게 훨씬 쉽다. 코드는 짧지만 상상하면 머리가 복잡해진다. 종이에 직접 그려보면 괜찮다. <br> |
| 96 | + |
| 97 | +마치 핸들을 돌리듯이 x와 y를 잡고 왼쪽, 오른쪽으로 돌리는 모습을 상상하면 된다! <br> |
| 98 | + |
| 99 | + |
| 100 | +### Left-Rotate |
| 101 | + |
| 102 | + |
| 103 | +x, y, 감마를 잡고 왼쪽으로 회전한다고 생각해보면 된다. 위와 같은 상황에서 y에 자식이 있다면, 그 값은 x보다 크고, y보다 작은 것이므로, x의 오른쪽에 가게 된다. 간단한 c++ 코드로는 아래와 같이 구현할 수 있다. |
| 104 | + |
| 105 | +```c++ |
| 106 | +x->rightChild = y->leftChild; |
| 107 | +y->leftChild = x; |
| 108 | +``` |
| 109 | + |
| 110 | +### Right-Rotate |
| 111 | + |
| 112 | + |
| 113 | + |
| 114 | + |
| 115 | +Left Rotate와 반대이다. |
| 116 | + |
| 117 | +코드로는 아래와 같이 구현할 수 있다 (c++) |
| 118 | +```c++ |
| 119 | +y->leftChild = x->rightChild; |
| 120 | +x->rightChild = y; |
| 121 | +``` |
| 122 | + |
| 123 | + |
| 124 | +### LR, RL Rotate |
| 125 | +AVL Tree처럼 LR, RL 회전도 있다. |
| 126 | + |
| 127 | + |
| 128 | + |
| 129 | + |
| 130 | +LR 회전은 위와 같이 수행되는데, 더 아래에 있는 xy먼저 잡고 Left Rotate를 한 다음, yz를 잡고 Right Rotate한다. 보통 새로 삽입된 노드가 부모의 오른쪽 자식이고, 부모는 Grand Parent Node의 왼쪽 자식일 대 발생한다. <br> |
| 131 | +RL 회전은 반대 상황에서 발생한다. |
| 132 | + |
| 133 | + |
| 134 | + |
| 135 | + |
| 136 | +<br> |
| 137 | + |
| 138 | +이렇게 균형을 맞추기 위한 연산들을 알아봤다. 이제, 균형을 맞추는 두 연산 `Recolor`와 `Rotate`를 통해 Red-Black Tree의 삽입 연산과 삭제 연산을 알아보자. 그리고 코드를 살펴본 다음, Java 라이브러리에서 어떻게 사용하는지 살펴보자 (HashMap과 TreeSet, TreeMap에서 사용) |
0 commit comments