일반 BST에서 최악의 경우(노드가 한쪽으로 편향되어 있는 경우) 삽입, 삭제, 검색의 시간 복잡도는 O(N)임.
모든 노드를 다 확인해야함. 레드블랙 트리는 스스로 균형을 맞춰줘서 트리가 편향되지 않도록 해줘서 O(logN)이 될 수 있도록 해줌.nil 노드란? (보라색 표시)
- 존재하지 않음을 의미하는 노드
- 자녀가 없을 때 자녀를 nil 노드로 표기
- 값이 있는 노드와 동등하게 취급
- RB 트리에서
leaf 노드는 nil 노드
- 모든 노드는 red 혹은 black
- 루트 노드는 black
- 모든 nil(leaf) 노드는 black
4. red의 자녀들은 black or red가 연속적으로 존재할 수 없음
5. 임의의 노드에서 자손 nil 노드들까지 가는 경로들의 black 수는 같다(자기 자신은 카운트에서 제외)
#5
속성을 만족해야 성립하는 개념5번 속성을 이용하여 임의의 노드에서 nil 노드까지의 경로 하나만 골라서 black height를 계산하면 됨.
색을 바꾸면서도 #5 속성을 유지하기
- RB 트리가 #5 속성을 만족하고 있고, 두 자녀가 같은 색을 가질 때 부모와 두 자녀의 색을 바꿔줘도 #5 속성은 여전히 만족한다.
RB 트리는 어떻게 균형을 잡는가?
삽입/삭제 시 주로#4, #5
를 위반하며 이들을 해결하려고 구조를 바꾸다 보면 자연스럽게 트리의 균형이 잡히게 된다.
overview
0. 삽입 전 RB 트리 속성 만족한 상태
1. 삽입 방식은 일반적인 BST와 동일
2. 삽입 후 RB 트리 위반 여부 확인
3. RB 트리 속성을 위반했다면 재조정
4. RB 트리 속성을 다시 만족
삽입하는 노드는 항상red
insert(50)
#3. 모든 nil 노드는 black 조건 만족
)#2 루트 노드는 black
) 조건 위반. 따라서, 루트 노드를 black으로 바꾸면 해결됨.insert(20)
왜 새로 삽입하는 노드는 red인가?
삽입 후에도 #5 속성을 만족하기 위해,임의의 노드에서 자손 nil 노드들까지 가는 경로들의 black 수는 같다(자기 자신은 카운트에서 제외)
insert(10)
#4. 노드가 red라면 자녀들은 black
을 위반하게 됨.BST의 특징 또한 유지
되어야 함(루트노드:20(black), 왼쪽자식:10(red), 오른쪽자식:50(red))회전
이다.red 삽입 후 #4 속성을 위반했을 때(case3)
- 삽입된 red 노드가 부모의 왼쪽* 자녀 & 부모도 red고 할아버지의 왼쪽* 자녀 & 삼촌(=부모의 형제)은 black이라면
부모와 할아버지의 색을 바꾼 후 할아버지 기준으로 오른쪽\* 으로 회전한다.
- 오른쪽 왼쪽을 바꿔도 성립함.
insert(40) - #4 속성 위반
삽입된 노드를 기준으로 할아버지까지의 경로가 꺾였다는 점
red 삽입 후 #4 속성을 위반했을 때(case2)
- 삽입된 red 노드가 부모의 오른쪽* 자녀 & 부모도 red고 할아버지의 왼쪽* 자녀 & 삼촌(=부모의 형제)은 black이라면
부모를 기준으로 왼쪽\*으로 회전한 뒤 case.3의 방식으로 해결함.
- 오른쪽, 왼쪽을 바꿔도 성립
insert(30)
RB 트리가 #5 속성을 만족하고 있고, 두 자녀가 같은 색을 가질 때 부모와 두 자녀의 색을 바꿔줘도 #5 속성은 여전히 만족한다.
red 삽입 후 #4 속성을 위반했을 때(case1)
- 삽입된 red 노드의 부모도 red & 삼촌(=부모의 형제)도 red라면
부모와 삼촌을 black으로 바꾸고 할아버지를 red로 바꾼 뒤 할아버지에서 다시 확인을 시작함.
- 할아버지의 색이 red로 변경됐는데 만약 루트노드라면 black으로 바꿔줘야 하고, 할아버지의 색이 red로 변경됐는데 할아버지의 부모 노드가 있고, 부모 또한 red라면 #4 조건을 위반하므로 다시 확인을 해야함.
insert(80)
insert(40)
할아버지 노드를 확인
해야 하는데 모든 red-black tree의 조건을 만족하므로 상황 종료.insert(35)
insert(25)
회전을 하면서 위치가 없어진 노드들은 자식이 없어진 노드의 자식 노드로 보통 들어가게 되는듯
- 삭제 전 RB 트리 속성 만족한 상태
- 삭제 방식은 일반적인 BST와 동일
- 삭제 후 RB 트리 속성 위반 여부 확인
- RB 트리 속성을 위반했다면 재조정
- RB 트리 속성을 다시 만족
RB 트리에서
노드를 삭제
할 때어떤 색
이 삭제되는지가속성 위반 여부
를확인
할 때 매우 중요함.
-> 삭제하려는 노드의자녀(유효한 값을 가지는 자녀)
가 없거나 하나라면
삭제되는 색 = 삭제되는 노드의 색
ex) 25 삭제: red 삭제, 80 삭제: black 삭제, 40 삭제: black 삭제
삭제하려는 노드의
자녀가 둘이라면
삭제되는 색 = 삭제되는 노드의 successor의 색
ex) 20 삭제: successor 25 -> red 삭제
: 20의 오른쪽 서브트리 중 가장 작은 값인 25가 자리를 대신하게 됨. 이때 삭제되는 색은 20의 red가 아니라 25가 20의 자리를 대체하면서 20의 색을 물려받게 되기 때문
35 삭제: successor 37 -> red 삭제
: 오른쪽 서브트리에서 가장 작은 값인 37이 35 자리를 대체하게 되고, 35의 색은 유지하고 37 위치에서의 빨간색이 삭제됨.
50 삭제: successor 80 -> black 삭제
속성 위반 여부 확인은
삭제되는 색
을 통해
- 삭제하려는 노드의 자녀가 없거나 하나라면 삭제되는 색은
삭제되는 노드의 색
- 삭제하려는 노드의 자녀가 둘이라면 삭제되는 색은
삭제되는 노드의 successor의 색
삭제되는 색이 red라면 어떠한 속성도 위반하지 않는다.
#2, #4, #5 속성을 위반할 수 있음.
black
이고 #5
위반일 때 extra black 부여
대체한 노드
에 extra black
을 부여함.doubly black
: extra black이 부여된 black 노드red and black
: extra black이 부여된 red 노드doubly black
이 되거나 red-and-black
이 된다.30은 자녀가 하나라서 삭제되는 색은 30의 black -> #5 위반
20과 25가 바로 연결되면서 -> #4 위반
삭제된 색은 30의 black이었고, 30을 대체하는 25의 reddp extra black 부여
25가 red-and-black이 됐으니 25를 black으로 바꿔주면 종료
결국 extra black을 어떻게 없앨것인지가 관건
네 가지 case
로 분류할 때의 기준은 doubly black
의 형제의 색
과 그 형제의 자녀들의 색
doubly black의 오른쪽 형제가 black
& 그 형제의 오른쪽 자녀가 red
일 때 그 red를 doubly black 위로 옮기고 옮긴 red로 extra black을 전달해서 red-and-black으로 만들면 red-and-black을 black으로 바꿔서 해결
red를 왼쪽으로 보내기 위해서는 D의 위치가 red가 돼야 하고, 이를 위해 D의 black을 C와 E로 보내고 D를 red로 바꾼다(#5의 규칙을 만족하기 위해)
.
c가 red인지 black인지 알 수 없기 때문에 extra black과 같이 표기 해주면 red-and-black 혹은 doubly black으로 생각할 수 있음.
red가 왼쪽으로 넘어갈 수 있도록 왼쪽으로 회전 전에 B와 D의 색을 바꿔준다.
B를 기준으로 왼쪽으로 회전한다.
<증명>
A와 C의 extra black을 B로 올려도 #5는 만족함.
B는 red-and-black이 됐기 때문에 B의 색을 Black으로 바꿔서 extra black을 제거하면 문제 해결
doubly black의 오른쪽 형제가 black & 그 형제의 오른쪽 자녀가 red일 때,
오른쪽 형제는 부모의 색으로, 오른쪽 형제의 오른쪽 자녀는 black으로, 부모는 black으로 바꾼 후에 부모를 기준으로 왼쪽으로 회전하면 해결~!
오른쪽* 형제는 부모의 색으로, 오른쪽* 형제의 오른쪽* 자녀는 black으로, 부모는 black으로 바꾼 후에 부모를 기준으로 왼쪽*으로 회전하면 해결
* 오른쪽 왼쪽을 바꿔도 성립
doubly black의 형제의 오른쪽 자녀가 red가 되게 만들어서 이후엔 case. 4를 적용하여 해결
doubly black의 형제의 오른쪽* 자녀를 red가 되게 만들어서 이후엔 case. 4를 적용하여 해결
형제가 black
& 그 형제의 두 자녀 모두 black
일 떄, doubly black과 그 형제의 black을 모아서 부모에게 전달해서 부모가 extra black을 해결하도록 위임한다.
black을 전달받은 B는 red-and-black 혹은 doubly black이 되고, #5 속성은 여전히 만족되고 있음.
B가 red-and-black
이 됐다면 black
으로 바꿔주면 상황은 종료되지만 B
가 doubly black
이 됐다면 B가 루트 노드라면 black으로 바꿔서 해결, 아니라면 case 1, 2, 3, 4 중에 하나로 해결함.
doubly black과 그 형제의 black을 모아서 부모에게 전달하여 부모가 extra black을 해결하도록 위임한다.
doubly black의 형제를 black으로 만든 후 case 2, 3, 4 중에 하나로 해결
B를 기준으로 왼쪽으로 회전하면 doubly black A의 형제는 C가 되며 즉, black이 된다.
회전 후에도 #5 속성을 만족하려면 왼쪽으로 회전하기 전에 B와 D의 색을 바꿔줌.
부모와 형제의 색을 바꾸고 부모를 기준으로 왼쪽으로 회전한 뒤 doubly black을 기준으로 case 2, 3, 4 중에 하나로 해결.
삭제되는 색이 black 일 때, #5 위반 해결하기
삭제되는 색이 black
일 때 삭제되는 색이 있던 위치를 대체한 노드
에 extra black
을 부여
한다.
대체한 노드가 red-and-black
이 됐다면 black
으로 바꿔주면 끝
대체한 노드가 doubly black
이 됐다면 case 1, 2, 3, 4
중에 하나로 해결함.
delete(15)
삭제되는 노드는 15, 삭제되는 색은 15의 black(15의 자녀가 없기 때문에), 15의 위치를 대체할 nil node에 extra black을 부여함.
nil 노드는 doubly black이 됐기 때문에 어떤 case인지 분류해야 함. doubly black의 왼쪽 형제도 black이고 그 형제의 왼쪽 자녀가 red
여서 case. 4에 해당한다.
5를 부모 노드의 색인 red로 바꾸고 5의 부모인 10과 5의 왼쪽 자녀인 2는 black으로 바꾼 뒤 10을 기준으로 오른쪽으로 회전함.
delete(33)
삭제되는 노드는 33, 삭제되는 색은 33의 black, 33의 위치를 대체할 nil node에 extra black을 부여함.
nil 노드는 doubly black이 됐기 때문에 어떤 case인지 분류해야 한다. doubly black의 왼쪽 형제가 black이고 그 형제의 왼쪽 자녀는 black이고 오른쪽 자녀가 red여서 case. 3에 해당함.
case. 4의 방식으로 해결할 수 있게 case. 4의 형태로 먼저 만들려면 25와 27의 색을 바꾸고 25를 기준으로 왼쪽으로 회전함.
delete(37)
delete(35)
delete(40)
삭제되는 노드는 40, 삭제되는 색은 45의 black, 45의 위치를 대체할 nil node에 extra black을 부여함.
nil 노드는 doubly black이 됐기 때문에 어떤 case인지 분류해야 한다. doubly black의 형제도 black이고 그 형제의 두 자녀도 black이기 때문에 case. 2에 해당함.
nil 노드의 extra black과 80의 black을 모아서 50으로 올리고 80은 red로 바꿔준다. 50은 extra black을 가진다.
이제 50이 doubly black이 됐기 때문에 이번엔 어떤 case인지 분류해야 한다. doubly black의 왼쪽 형제가 black이고 그 형제의 왼쪽 자녀가 red이기 때문에 case. 4에 해당함.
20을 부모 노드의 색인 black으로 바꾸고 20의 부모인 45와 20의 왼쪽 자녀인 5는 black으로 바꾼 뒤 45를 기준으로 오른쪽으로 회전함.
delete(50)
삭제되는 노드는 50, 삭제되는 색은 50, 삭제되는 색은 50의 black, 50의 위치를 대체할 80에 extra black을 부여함.
80은 red-and-black이 됐기 때문에 80을 black으로 바꾸면 red-black 트리의 모든 속성을 만족하며 상황 종료
delete(80)
삭제되는 노드는 80, 삭제되는 색은 80의 black, 80의 위치를 대체할 nil 노드에 extra black을 부여함.
nil 노드는 doubly black이 됐기 때문에 어떤 case인지 분류해야 한다. doubly black의 형제가 red이기 때문에 case. 1에 해당함.
case. 1의 형태를 바꿔서 case. 2, 3, 4 중에 하나의 형태로 만든다.
형제와 부모의 색을 바꾼 뒤 45를 기준으로 오른쪽으로 회전함.
doubly black의 형제가 black이고 형제의 두 자녀가 모두 black이기 때문에 case. 2의 방식으로 해결함(doubly black의 black과 형제 노드의 black을 부모노드에게 줌).
45가 red-and-black이 됐기 때문에 검은색으로 바꿔주면 해결됨.
delete(27)
형 잘볼게요 👍