You are on page 1of 6

CÂY ĐỎ ĐEN (RED-BLACK TREES)

1. Các tính chất


Cây đỏ đen là một cây nhị phân tìm kiếm với thêm một thông tin lưu trữ ở mỗi nút đó là
màu sắc của nút: đỏ hoặc đen. Bằng việc định màu các nút trên đường đi từ nút gốc đến các
nút lá, cây đỏ đen đảm bảo rằng: đường đi dài nhất từ một nút gốc đến một nút lá không vượt
quá hai lần độ dài bất cứ đường đi nào từ nút gốc đó đến một nút lá bất kỳ, vì vậy cây đỏ đen
là một cây được xem cân bằng.
Mỗi nút trên câu đỏ đen là một con trỏ nút chứa 5 thông tin:
• Color : màu sắc
• Key: giá trị khóa
• Left: cây con trái
• Right: cây con phải
• P: nút cha của nó
Nếu nút con hoặc nút cha của một nút không tồn tại thì trường đó có giá trị NIL. Ta quy
ước các nút NIL là các nút ngoài của cây, như vậy các nút trong của cây là các nút mang giá
trị khóa.
Một cây nhị phân tìm kiếm là một cây đỏ đen nếu thõa mãn các tính chất sau của câu đỏ
đen:
1. Màu của mỗi nút hoặc là đỏ hoặc đen
2. Nút gốc màu đen
3. Tất cả các nút lá (NIL) là đen
4. Hai nút con của mọi nút đỏ đều là đen
5. Đối với một nút bất kì, tất cả đường đi từ nút đó đến các nút lá (là hậu duệ của
nó) đều có cùng số lượng nút đen trên đường đi
Ví dụ về cây đỏ đen

Hình_1
Mỗi nút trên cây đỏ đen được tô màu đỏ hoặc đen, hai nút con của nút đỏ đều là nút đen,
tất cả các đường đi xuất phát từ một nút bất kỳ đến các nút lá đều đi qua số lượng nút đen như
nhau. Số nút đen trên đường đi được gọi là độ cao đen của nút đó. Tất cả các nút lá là NIL và
được xem là có màu đen, độ cao đen ở nút lá là 0. (Hình_1)
Hình_2
Để thuận tiện trong việc cài đặt, người ta thay các nút NIL bằng nút cầm canh nil[T], nút
này được tô màu đen, chiều cao của nút này được lờ đi, cha của nút gốc cũng là nút cầm canh
như Hình_2

Hình_3
Khi biểu diễn người ta có thể bỏ qua các nút lá và cha của nút gốc như Hình_3
Bổ đề: một cây đỏ đen với n nút trong có chiều cao không quá 2lg(n+1)
Chứng minh:
Trước hết ta chức minh một nút có độ cao đen là bh thì có ít nhất 2bh – 1 nút con.
+ Với x là nút lá: bh(x)=0 nên xbh(x) – 1 = 1 – 1 = 0
+ Với x là một nút trong bất kì có 2 nút con, mỗi nút con có độ cao đen là bh(x) hoặc
bh(x) – 1 tùy thuộc vào nút con là đỏ hoặc đen. Giả sử mỗi nút con có độ cao bh(x) – 1, ta có
số nút trong của cây con gốc x là (2bh(x)-1 – 1) + (2bh(x)-1 – 1) + 1 = 2bh(x) – 1
Gọi h là chiều cao của cây đỏ đen. Theo tính chất 4 của cây đỏ đen ta có ít nhất một nửa
số nút trong trên đường đi từ nút gốc đến nút lá kể cả nút gốc là đen. Như vậy chiều cao đen
của cây ít nhất là h/2 nên n ≥ 2h/2 - 1. Chuyển 1 sang vế trái và lấy logarit cơ số 2 cả hai vế ta
có: lg(n+1) ≥ h/2 hay h ≤ 2lg(n+1)
2. Phép quay
Trong các phép CHÈN và XÓA trên cây đỏ đen có n nút trong với độ phức tạp O(lg n).
Tuy nhiên, khi thực hiện các thao tác trên thì các tính chất của cây đỏ đen có thể bị vi phạm.
Để khôi phục lại các tính chất trên người ta phải tô màu lại một số nút và thay đổi cấu trúc
một số con trỏ nút trên cây.
Chúng ta thay đổi cấu trúc của các con trỏ nút thông qua phép quay, đây là thao tác bảo
toàn được cấu trúc cây nhị phân tìm kiếm. Có hai phép quay là quay trái và quay phải. Khi
thực hiện phép quay trái (LEFT-ROTATE) tại nút x thì giả định cây con phải của nó khác
nil[T] và tương tự khi thực hiện phép quay phải (RIGHT-ROTATE).

Hình_4
Khi thực hiện phép quay trái tại x, con phải y của x trở thành nút cha của x, con trái của
nút y trở thành con phải của nút x và nút x trở thành con trái của nút y.
Mã giả của phép quay trái tại x với con phải của x khác nil[T].
LEFT-ROTATE(T, x){
1 y ← right[x] ▹ đặt y là con phải của x.
2 right[x] ← left[y] ▹ chuyển con trái của y thành con phải của x
3 p[left[y]] ← x
4 p[y] ← p[x] ▹ đặt cha của y là cha của x.
5 if p[x] = nil[T]
6 then root[T] ← y
7 else if x = left[p[x]]
8 then left[p[x]] ← y
9 else right[p[x]] ← y
10 left[y] ← x ▹ đặt x là con trái của y.
11 p[x] ← y }

Ví dụ:

Hình_5
3. Phép chèn
Việc chèn một nốt vào cây đỏ đen gồm n nút hoàn thành trong O(lg n). Việc chèn một nút
z vào cây đỏ đen T như việc chèn vào một cây nhị phân tìm kiếm bình thường. Sau đó tô màu
nút z là đỏ và gọi thủ tục RB_INSERT_FIXUP để thực điều chỉnh cây sau khi chèn bằng cách
hiện tô màu lại một số nút và thực hiện một số phép quay cần thiết.
Mã giả của phép chèn nút z vào cây đỏ đen T như sau:
RB-INSERT(T, z){
1 y ← nil[T]
2 x ← root[T]
3 while x ≠ nil[T]
4 do {y ← x
5 if key[z] < key[x]
6 then x ← left[x]
7 else x ← right[x]}
8 p[z] ← y
9 if y = nil[T]
10 then root[T] ← z
11 else if key[z] < key[y]
12 then left[y] ← z
13 else right[y] ← z
14 left[z] ← nil[T]
15 right[z] ← nil[T]
16 color[z] ← RED
17 RB-INSERT-FIXUP(T, z)}

Mã giả của phép điều chỉnh cây sau khi chèn:


RB-INSERT-FIXUP(T, z){
1 while color[p[z]] = RED
2 do if p[z] = left[p[p[z]]]
3 then y ← right[p[p[z]]]
4 if color[y] = RED
5 then {color[p[z]] ← BLACK ▹ Case 1
6 color[y] ← BLACK
7 color[p[p[z]]] ← RED
8 z ← p[p[z]] }
9 else if z = right[p[z]] ▹ Case 2
10 then z ← p[z]
11 LEFT-ROTATE(T, z)
2 else { color[p[z]] ← BLACK ▹ Case 3
13 color[p[p[z]]] ← RED
14 RIGHT-ROTATE(T, p[p[z]])}
15 else (same as then clause
with "right" and "left" exchanged)
16 color[root[T]] ← BLACK }
Để hiểu thủ tục RB-INSERT-FIXUP làm việc như thế nào chúng ta cùng xem xét ví dụ
sau:

Hình_6
Trong ví dụ trên, ở phần (a): nút z vừa được chèn vào cây. Trong khi cả z và p[z] đều màu
đỏ thì tính chất 4 bị vi phạm. Khi mà nút chú bác của z là y là màu đỏ thì Case 1 được thực
hiện. Các nút cha và chú bác của z được đổi thành màu đen và nút z di chuyển lên phía trên
của cây, kết quả của thao tác này có thể xảy ra ở phần (b). Thêm một lần nữa cả z và p[z] đều
màu đỏ nhưng nút chú bác y của z là màu đen. Trong trường hợp này khi mà z là con phải của
p[z] thì Case 2 được thực hiện. Sau khi thực hiện một phép quay trái tại nút z, kết quả dẫn đến
như ở phần (c). Lúc này z là con trái của p[z] và nút chú bác y của z là màu đen nên Case 3
được thực hiện: đổi màu p[z] thành đen và p[p[z]] thành đỏ. Một phép quay phải tại p[p[z]]
dẫn đến kết quả như phần (d), lúc này các tính chất của cây đỏ đen được thỏa mãn.
4. Phép xóa
RB-DELETE(T, z){
1 if left[z] = nil[T] or right[z] = nil[T]
2 then y ← z
3 else y ← TREE-SUCCESSOR(z)
4 if left[y] ≠ nil[T]
5 then x ← left[y]
6 else x ← right[y]
7 p[x] ← p[y]
8 if p[y] = nil[T]
9 then root[T] ← x
10 else if y = left[p[y]]
11 then left[p[y]] ← x
12 else right[p[y]] ← x
13 if y ≠ z
14 then key[z] ← key[y]
15 copy y's satellite data into z
16 if color[y] = BLACK
17 then RB-DELETE-FIXUP(T, x)
18 return y }

RB-DELETE-FIXUP(T, x){
1 while x ≠ root[T] and color[x] = BLACK
2 do if x = left[p[x]]
3 then {w ← right[p[x]]
4 if color[w] = RED
5 then {color[w] ← BLACK ▹ Case 1
6 color[p[x]] ← RED ▹ Case 1
7 LEFT-ROTATE(T, p[x]) ▹ Case 1
8 w ← right[p[x]] } ▹ Case 1
9 if color[left[w]] = BLACK and color[right[w]] = BLACK
10 then {color[w] ← RED ▹ Case 2
11 x ← p[x] } ▹ Case 2
12 else if color[right[w]] = BLACK
13 then {color[left[w]] ← BLACK ▹ Case 3
14 color[w] ← RED ▹ Case 3
15 RIGHT-ROTATE(T, w) ▹ Case 3
16 w ← right[p[x]] ▹ Case 3
17 color[w] ← color[p[x]] ▹ Case 4
18 color[p[x]] ← BLACK ▹ Case 4
19 color[right[w]] ← BLACK ▹ Case 4
20 LEFT-ROTATE(T, p[x]) ▹ Case 4
21 x ← root[T]}} ▹ Case 4
22 else (same as then clause with "right" and "left" exchanged)
23 color[x] ← BLACK}

5.

You might also like