Giáo trình Cây đỏ đen

Độ phức tạp:

Khi cây một nhánh, sẽ trở thành một danh sách liên kết, dữ liệu sẽ là một chiều thay vì

hai chiều. Trong trường hợp này, thời gian truy xuất giảm về O(N), thay vì O(logN)

đối với cây cân bằng.

Để bảo đảm thời gian truy xuất nhanh O(logN) của cây, chúng ta cần phải bảo đảm cây

luôn luôn cân bằng (ít ra cũng là cây gần cân bằng). Điều này có nghĩa là mỗi node trên

cây phải có xấp xỉ số node con bên phải bằng số node con bên trái.

Một cách tiếp cận giải quyết vấn đề cân bằng lại cây: đó là cây đỏ đen-là cây tìm kiếm

nhị phân vì thế nó có các tính chất của cây tìm kiếm nhị phân ví dụ : node con trái nhỏ

hơn node cha, node cha nhỏ hơn node con phải, bên cạnh đó cây đỏ đen còn được bổ

sung một số đắc điểm.

 

pdf 31 trang kimcuc 6140
Bạn đang xem 20 trang mẫu của tài liệu "Giáo trình Cây đỏ đen", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

Tóm tắt nội dung tài liệu: Giáo trình Cây đỏ đen

Giáo trình Cây đỏ đen
TRƯỜNG ĐẠI HỌC KHOA HỌC TỰ NHIÊN 
 KHOA CÔNG NGHỆ THÔNG TIN 
 BỘ MÔN CẤU TRÚC DỮ LIỆU 2 
Lời nói đầu: 
 Cây đỏ đen là một trong những cấu trức dữ liệu hay, cùng với cây nhị phân tìm 
kiếm là những cấu trúc dữ liệu có điểm mạnh trong việc lưu trữ và tìm kiếm dữ liệu. 
Song cây đỏ đen có những đặc tính riêng mà nhờ đó nó đã làm nổi bật những điểm 
mạnh của mình. 
 Trong phạm vi bài báo cáo này, chúng em xin trình bài về : khái quát cây đỏ đen, 
các thuật toán cơ bản, code cài đặt các thuật tóan cơ bản và có những nhận xét về cấu 
trúc cây đỏ đen này. 
Chúng em chân thành cam ơn cô Phạm Phạm Tuyết Trinh đã tạo điều kiện cho 
chúng em tìm hiểu đề tài lý thú này. Dù hết sức cố gắng song vẫn không tránh được 
những sai xót nhất định chúng em mong được sư mong nhận được những đóng góp 
chân tình để bài làm trở nên hòan chỉnh hơn. 
 Nhóm thực hiện 
Cây Đỏ Đen 
 2 
Mục lục: 
Lời nói đầu: ..................................................................................................................... 1 
Mục lục: ........................................................................................................................... 2 
I- Giới thiệu: ................................................................................................................ 3 
II- Định nghĩa: .......................................................................................................... 5 
III- Các thuật toán cơ bản của Black and Red Tree ............................................... 6 
1- Thêm một Node mới ........................................................................................... 6 
2- Xóa một node: .................................................................................................... 14 
IV- Thuật toán cài đặt: ............................................................................................ 14 
V- Nhận xét : ........................................................................................................... 31 
Cây Đỏ Đen 
 3 
I- Giới thiệu: 
Cây đỏ đen được ra giới thiệu bởi Rudolf Bayer trong quyển “Symmetric Binary 
B-Trees: Data Structure and maintenance Algorithms”, nhà xuất bản Acta 
Informatica, Tâp1, trang 290-306. Sau đó Leonidas J.Guibas và Robert Sedgewick 
đã thêm các đặc tính của cây đỏ đen và đặt tên cho nó ( Tham khảo: Guibas, L. and 
Sedgewick R. “ A dichromatic Framwork for Balanced Trees”, in Proc. 19th IEEE 
Symp. Foundations of Computer Science, trang 8-21, năm 1978). 
Ta đã biết cây tìm kiếm nhị phân thông thường có những thuận lợi lớn về mặt lưu 
trữ và truy xuất dữ liệu trong phép toán tìm kiếm thêm vào hay loại bỏ một phần tử. 
Do đó, cây tìm kiếm nhị phân xem ra là một cấu trúc lưu trữ dữ liệu tốt. 
Tuy nhiên trong một số trường hợp cây tìm kiếm nhị phân có một số hạn chế. Nó 
hoạt động tốt nếu dữ liệu được chèn vào cây theo thứ tự ngẫu nhiên. Tuy nhiên, nếu 
dữ liệu được chèn vào theo thứ tự đã đuợc sắp xếp sẽ không hiệu quả. Khi các trị số 
Cây Đỏ Đen 
 4 
cần chèn đã đuợc sắp xếp thì cây nhị phân trở nên không cân bằng. Khi cây không 
cân bằng, nó mất đi khả năng tìm kiếm nhanh (hoặc chèn hoặc xóa) một phần tử đã 
cho. 
Chúng ta khảo sát một cách giải quyết vấn đề của cây không cân bằng: đó là cây đỏ 
đen, là cây tìm kiếm nhị phân có thêm một vài đặc điểm . 
Có nhiều cách tiếp cận khác để bảo đảm cho cây cân bằng: chẳng hạn cây 2-3-4. 
Tuy vậy, trong phần lớn trường hợp, cây đỏ đen là cây cân bằng hiệu quả nhất, ít ra 
thì khi dữ liệu được lưu trữ trong bộ nhớ chứ không phải trong những tập tin. 
Trước khi khảo sát cây đỏ đen, hãy xem lại cây không cân bằng được tạo ra như thế 
nào. 
Hình 3.1. Các node được chèn theo thứ tự tăng dần 
Những node này tự sắp xếp thành một đường không phân nhánh. Bởi vì mỗi node lớn 
hơn node đã được chèn vào trước đó, mỗi node là con phải. Khi ấy, cây bị mất cân 
bằng hoàn toàn. Nếu ta chèn những mục (item) theo thứ tự giảm dần, mỗi node sẽ là 
con trái của node cha của chúng - cây sẽ bị mất cân bằng về phía bên kia. 
* Độ phức tạp: 
Khi cây một nhánh, sẽ trở thành một danh sách liên kết, dữ liệu sẽ là một chiều thay vì 
hai chiều. Trong trường hợp này, thời gian truy xuất giảm về O(N), thay vì O(logN) 
đối với cây cân bằng. 
Để bảo đảm thời gian truy xuất nhanh O(logN) của cây, chúng ta cần phải bảo đảm cây 
luôn luôn cân bằng (ít ra cũng là cây gần cân bằng). Điều này có nghĩa là mỗi node trên 
cây phải có xấp xỉ số node con bên phải bằng số node con bên trái. 
Một cách tiếp cận giải quyết vấn đề cân bằng lại cây: đó là cây đỏ đen-là cây tìm kiếm 
nhị phân vì thế nó có các tính chất của cây tìm kiếm nhị phân ví dụ : node con trái nhỏ 
hơn node cha, node cha nhỏ hơn node con phải, bên cạnh đó cây đỏ đen còn được bổ 
sung một số đắc điểm. 
Cây
Tro
tử 
khô
cân
Cây
Kh
đen
 Đỏ Đen 
ng cây đỏ 
thì thủ tục
ng. Nếu c
 bằng. 
II- Đị
 đỏ đen là 
i chèn (hay
. Nếu được
M
đen, việc c
 chèn sẽ k
ó, sẽ xây d
nh ngh
một cây nh
Mọi node
Node gốc
Nếu một n
Mọi đườn
 xóa) một n
 tuân thủ, c
Số lượng n
cao đen (bl
là mọi đườn
Bổ đề: 
ột cây đỏ
ân bằng đư
iểm tra xem
ựng lại cấu
ĩa: 
ị phân tìm 
 phải là đỏ 
 và các nod
ode là đỏ, 
g dẫn từ gố
ode mới, c
ây sẽ được
H
ode đen trê
ack height)
g dẫn từ g
 đen n-nod
5
ợc thực thi 
 tính chấ
 trúc cây. 
kiếm( BST
hoặc đen. 
e lá phải lu
những nod
c đến một 
ần phải tuâ
 cân bằng. 
ình 3.2. Mộ
n một đườn
. Ta có thể 
ốc đến lá p
e 
trong khi c
t cân bằng
Bằng cách 
) tuân thủ c
ôn luôn đen
e con của n
lá phải có c
n thủ các q
t ví dụ về c
g dẫn từ gố
phát biểu q
hải có cùng
hèn, xóa. K
 của cây c
này, cây lu
ác quy tắc 
. 
ó phải đen
ùng số lượ
uy tắc trên 
ây đỏ đen 
c đến lá đư
uy tắc 4 th
 chiều cao 
hi thêm m
ó bị vi ph
ôn luôn đư
sau: (hình 
. 
ng node đe
-gọi là quy
ợc gọi là c
eo một cách
đen. 
ột phần 
ạm hay 
ợc giữ 
3.2) 
n. 
 tắc đỏ 
hiều 
 khác 
Cây Đỏ Đen 
 6 
Có: height <= 2 log(n+1) 
 height : Chiều cao cây 
Tính chất: height <= 2 * bh(x) 
Thời gian tìm kiếm: O( log n ) 
Chứng Minh: 
III- Các thuật toán cơ bản của Black and Red Tree 
1- Thêm một Node mới 
Chúng ta sẽ xem xét việc mô tả qui trình chèn. Gọi X, P, và G để chỉ định nhãn những 
node liên quan. X là node vi phạm quy tắc ( X có thể là một node mới được chèn, hoặc 
node con khi node cha và node con xung đột đỏ-đỏ, nghĩa là có cùng màu đỏ). 
· X là một node cho trước. 
· P là node cha của X. 
· G là node ông bà của X (node cha của P). 
Trong quá trình thêm vào node mới có thể vi phạm các quy tắc của cây đỏ đen, chúng 
ta sẽ thực hiện các thao tác sau đây: 
· Các phép lật màu trên đường đi xuống. 
Cây
· C
· C
1.1
Phé
đi t
trị 
Tuy
qua
Để
cần
có 
nod
Mộ
tam
nod
Hìn
 Đỏ Đen 
ác phép qu
ác phép qu
 Các p
p thêm vào
heo một đư
của khóa no
 nhiên, tro
y. 
 bảo đảm k
. Theo quy
hai node co
e cha là no
t phép lật m
 giác, node
e con trái v
h 3.4. Lật 
ay khi node
ay trên đườ
hép lật m
 trong cây 
ờng dẫn từ
de và khóa
ng cây đỏ đ
hông vi phạ
 tắc như sa
n đỏ, chún
de gốc, nó 
àu ảnh hư
 có màu đỏ
à phải của
màu 
 đã được c
ng đi xuốn
àu trên đư
đỏ đen bắt
 node gốc đ
 tìm kiếm.
en, đến đư
m các quy
u: nếu phép
g ta đổi các
vẫn vẫn gi
ởng đến cá
 trước phép
 P là X1 và
7
hèn. 
g. 
ờng đi xu
 đầu như trê
ến vị trí cầ
ợc điểm ch
 tắc màu, c
 thêm vào 
 node con t
ữ màu là đe
c quy tắc đ
 lật là P (P
 X2. Xem h
ống 
n cây tìm k
n chèn, đi 
èn là phức 
ần phải tiến
làm xuất hi
hành đen v
n). 
ỏ-đen ra sa
 thay cho n
ình 3.4a. 
iếm nhị ph
qua phải ha
tạp bởi các
 hành các p
ện tình trạn
à node cha
o? chúng ta
ode cha). C
ân thông th
y trái tùy v
 phép lật m
hép lật mà
g một nod
 thành đỏ (
 gọi node ở
húng ta gọ
ường: 
ào giá 
àu và 
u khi 
e đen 
trừ khi 
 đỉnh 
i hai 
Cây Đỏ Đen 
 8 
Hình 3.4a. trước khi lật màu, Hình 3.4b sau khi lật màu. 
Chúng ta nhận thấy sau khi lật màu chiếu con đen của cây không đổi. Như vậy phép lật 
màu không vi phạm quy tắc 4. 
Mặc dù quy tắc 4 không bị vi phạm qua phép lật, nhưng quy tắc 3 (một node con và 
node cha không thể đồng màu đỏ) lại có khả năng bị vi phạm. Nếu node cha của P là 
đen, không có vấn đề vi phạm khi P chuyển từ đen sang đỏ, nhưng nếu node cha của P 
là đỏ, thì sau khi đổi màu, ta sẽ có hai node đỏ trên một hàng. 
Điều này cần phải được chuẩn bị truớc khi đi xuống theo cây để chèn node mới. Chúng 
ta có thể giải quyết trường hợp này bằng một phép quay. 
Đối với node gốc thì phép lật màu node gốc và hai node con của nó vẫn làm cho node 
gốc cũng như hai node con có màu đen. Điều này tránh sự vi phạm quy tắc 2 và quy tắc 
3 (xung đột đỏ-đỏ). Trong trường hợp này, chiều cao đen trên mỗi đường đi từ node 
gốc tăng lên 1, do đó quy tắc 4 cũng không bị vi phạm. 
1.2 Các phép quay khi chèn node 
Thao tác chèn node mới có thể làm cho quy tắc đỏ-đen bị vi phạm. Do vậy sau khi 
chèn, cần phải kiểm tra xem có phạm quy tắc không và thực hiện những thao tác hợp 
lý. 
Như đã xét ở trên, node mới được chèn mà ta gọi là node X, luôn luôn đỏ. Node X có 
thể nằm ở những vị trí khác nhau đối với P và G, như trong hình 3.5. 
Cây
Hìn
X l
Điề
nod
Ng
Nế
nod
chá
Tha
và 
 Đỏ Đen 
h 3.5. Các 
à một node
u này có n
e con trái c
ược lại, X l
u X là node
e P ở bên t
u nội. Bốn
o tác phục
những bà c
biến dạng 
 cháu ngoạ
ghĩa là, X l
ủa G, hoặc
à một node
 cháu ngoạ
rái hay bên
 trường hợp
 hồi quy tắc
on của nó. 
của node đư
i nếu nó nằ
à node cháu
 nó là node
 cháu nội. 
i, nó có thể
 phải node 
 này được 
 đỏ-đen đư
Có 3 khả n
9
ợc chèn 
m cùng bên
 ngoại nếu
 con phải c
 hoặc bên t
G. Có hai k
trình bày tr
ợc xác địn
ăng xảy ra 
 node cha 
 hoặc nó là
ủa P và no
rái hoặc bê
hả năng tư
ong hình 3
h bởi các m
được xem x
P và P cùng
 node con t
de P là nod
n phải của 
ơng tự nếu
.5. 
àu và cấu h
ét như sau
 bên node 
rái của P v
e con phải 
P, tùy vào 
 X là một n
ình của no
:(hình 3.6)
cha G. 
à P là 
của G. 
việc 
ode 
de X 
Cây
Hìn
i) K
ii) K
iii)
Ch
i) K
P đ
xun
Do
ii) K
Nế
tha
cần
 Đỏ Đen 
h 3.6. Ba k
hả năng 1
hả năng 2
 Khả năng 
úng ta lần l
hả năng 1
en là trườn
g khắc đỏ-
 vậy, không
hả năng 2
u node P đỏ
y đổi về mà
 phải làm m
hả năng sa
: P đen 
: P đỏ và X
3: P đỏ và X
ượt xét các
: P đen 
g hợp đơn 
đỏ (quy tắc
 bị vi phạm
: P đỏ và X
 và X là no
u. Bắt đầu
ột phép lậ
u khi chèn 
 là cháu ng
 là cháu n
 khả năng c
giản. Node 
 3), và khô
 quy tắc v
 là cháu ng
de cháu ng
 với giá trị 
t màu trước
10
nút 
oại của G
ội của G 
ụ thể như s
thêm vào l
ng có việc 
ề màu. Tha
oại của G
oại, ta cần 
50 tại node
 khi chèn n
au: 
uôn đỏ. Nế
cộng thêm 
o tác chèn 
một phép q
 gốc, và ch
ode 12. 
u node cha
vào số nod
đã hoàn tất
uay đơn gi
èn các node
 đen, không
e đen (quy 
. 
ản và một v
 25, 75 và 
 có 
tắc 4). 
ài 
12. Ta 
Cây
Bây
phả
Tro
cân
Đ
Đ
Q
phé
Kh
Tro
đối
này
bằn
cây
 Đỏ Đen 
 giờ, chèn 
i có các th
ng trường 
 bằng cây. 
ổi màu nod
ổi màu nod
uay với no
p quay phả
i ta hoàn tấ
ng thí dụ n
 xứng khi n
 bằng cách
g cách đổi 
 lại được c
node mới X
ao tác như 
hợp này, ta
Sau đây là 
e G - node
e P - node 
de G (25) ở
i. 
t ba buớc tr
ày, node X
ode X là n
 tạo nên câ
màu node 
ân bằng. 
 là 6. (hìn
sau: (hình 3
 có thể áp d
các bước ấ
 ông bà của
cha của no
 vị trí đỉnh
ên sẽ bảo t
 là node ch
ode cháu ng
y 50, 25, 75
75 và 87, v
11
h 3.7a. )xuấ
.7) 
ụng ba bướ
y: 
 node X (tr
de X (node
, theo huớn
oàn cây đỏ
áu ngoại củ
oài nhưng
, 87, 93 (v
à quay trái 
t hiện lỗi: 
c để phục 
ong thí dụ 
 12) 
g làm nâng
 đen. Xem 
a một node
 của một no
ới phép lật 
với node 7
cha và con 
hồi tính đỏ
này là node
 node X lên
hình 3.7b. 
 con trái. C
de con phả
màu khi cầ
5 là node đ
đều đỏ, vì v
-đen và làm
 25). 
 (6). Đây l
ó một trườ
i. Thử làm
n). Chỉnh s
ỉnh. Một lầ
ậy cần 
 cho 
à một 
ng hợp 
 điều 
ửa cây 
n nữa 
Cây
Hìn
iii)
Nế
phé
lật 
Lưu
 Đỏ Đen 
h 3.7. Nod
 Khả năng 
u node P đỏ
p đổi màu.
màu trước 
 ý là node
e P đỏ và X
3: P đỏ và X
 và X là no
 Cây đỏ đe
khi chèn no
 18 là node
 là node ch
 là cháu n
de cháu nộ
n được tạo 
de 12). Xe
 cháu nội. N
12
áu ngoại 
ội của G 
i, chúng ta
thành từ cá
m hình 3.8
ode này v
 cần thực h
c node 50, 
a. 
à node cha 
iện hai phé
25, 75, 12 
đều đỏ (cha
p quay và m
và 18. (cần
 và con đề
ột vài 
 phải 
u đỏ). 
Cây
Hìn
Ch
ở đ
như
nod
 Đỏ Đen 
h 3.8. Khả
ỉnh lại sự sắ
ỉnh, như ta
 thế cây sẽ
e 12 ở đỉnh
 năng 3: P 
p xếp này 
 đã làm tron
 không còn
, để phục h
đỏ và X là n
cũng khá rắ
g khả năng
 cân bằng n
ồi cây nhu
13
hình 3.8.c
ode cháu n
c rối hơn. 
 2, node ch
hư trước. (
 cũ). Phải c
ội 
Nếu ta cố q
áu trong X
Thử làm đ
ần một giả
uay phải n
 (18) đi ng
iều này, rồi
i pháp khác
ode ông bà
ang hơn là 
 quay trở lạ
. 
 G (25) 
đi lên, 
i, với 
Cây
Thủ
Phé
3.8
phé
Ch
nào
nod
Đ
Đ
Q
đây
Q
typ
ST
ST
ST
ST
} S
 Đỏ Đen 
 thuật cần 
p quay đầu
b. Bây giờ,
p quay, vớ
úng ta cũng
 (thứ tự kh
e thì khó m
ổi màu nod
ổi màu nod
uay với no
 là 12). 
uay lần nữa
2- 
Chú
thì k
cũn
bảo
IV- Th
edef enum 
ATUS_OK
ATUS_ME
ATUS_DU
ATUS_KE
tatusEnum
dùng khi X
 biến X từ 
 trường hợp
i node ông 
 cần tô mà
ông quan tr
à biết phải
e ông bà củ
e X (không
de P - node
 với node 
Xóa m
ng ta đã bi
hó khăn ph
g vậy, thậm
 qui tắc của
uật toá
{ 
, 
M_EXHAU
PLICATE_
Y_NOT_F
; 
 là node ch
một node c
 là tương t
bà ở đỉnh, 
u lại các nú
ọng, nhưng
 gọi chúng
a node X (
 phải màu 
 cha của X 
ông bà của 
ột node:
ết trong cậy
ức tạp hơn
 chí còn ph
 cây đỏ đen
n cài đ
STED, 
KEY, 
OUND 
14
áu nội là ti
háu nội thà
ự như khả n
như đã làm
t. Ta làm đ
 nếu ta đợi
 như thế nà
 node 25).
của node c
- ở đỉnh (k
X (25) ở đỉ
 nhị phân t
 việc inser
ức tạp hơn
. 
ặt: 
ến hành ha
nh node ch
ăng 1, và t
 trước đây.
iều này trư
 đến khi sa
o). Các bướ
ha; node X
hông phải v
nh, về hướ
ìm kiếm vi
t 1 phần tử 
 vì trong qu
i phép quay
áu ngoại, n
a có thể áp
 Kết quả nh
ớc khi làm 
u khi quay 
c là: 
 đây là nod
ới node ôn
ng nâng X 
ệc xóa 1 ph
vào cậy, và
á trình thê
 hơn là mộ
hư trong h
 dụng cùng
ư trong hìn
bất cứ phép
mới tô màu
e 18). 
g bà; node 
lên (quay p
ần tử ra kh
 ở cây đỏ đ
m vào phải
t phép. 
ình 
 một 
h 3.8c. 
 quay 
 lại 
cha 
hải). 
ỏi cây 
en 
 đảm 
Cây Đỏ Đen 
 15 
typedef int KeyType; /* Kiểu dữ liệu khoá */ 
/* Dữ liệu lưu trữ */ 
typedef struct { 
int stuff 
} RecType; 
#define compLT(a,b) (a < b) 
#define compEQ(a,b) (a == b) 
/* Khai báo cấu trúc dữ liêu */ 
typedef enum { BLACK, RED } nodeColor; 
typedef struct NodeTag { 
struct NodeTag *left; /* Con trái */ 
struct NodeTag *right; /* Con phải */ 
struct NodeTag *parent; /* Cha */ 
nodeColor color; /* Màu node (BLACK, RED) */ 
KeyType key; /* Khoá sử dụng tìm kiếm */ 
RecType rec; /* Dữ liệu node */ 
} NodeType; 
typedef NodeType *iterator; 
#define NIL &sentinel /* Node cầm canh */ 
static NodeType sentinel = { &sentinel, &sentinel, 0, BLACK, 0}; 
static NodeType *root = NIL; /* Node gốc */ 
Cây Đỏ Đen 
 16 
/************************** 
* Xoay tráI node x * 
**************************/ 
static void rotateLeft(NodeType *x) { 
NodeType *y = x->right; 
/* Thiết lập liên kết x->right */ 
x->right = y->left; 
if (y->left != NIL) y->left->parent = x; 
/* Thiết lập liên kết y->parent */ 
if (y != NIL) y->parent = x->parent; 
if (x->parent) { 
if (x == x->parent->left) 
x->parent->left = y; 
else 
x->parent->right = y; 
} else { 
root = y; 
} 
/* link x and y */ 
y->left = x; 
if (x != NIL) x->parent = y; 
Cây Đỏ Đen 
 17 
} 
static void rotateRight(NodeType *x) { 
/**************************** 
* Xoay node x bên phải * 
****************************/ 
NodeType *y = x->left; 
/* Thiết lập liên kết x->left */ 
x->left = y->right; 
if (y->right != NIL) y->right->parent = x; 
/* Thiết lập liên kết y->parent */ 
if (y != NIL) y->parent = x->parent; 
if (x->parent) { 
if (x == x->parent->right) 
x->parent->right = y; 
else 
x->parent->left = y; 
} else { 
root = y; 
} 
/* liên kết x và y */ 
y->right = x; 
Cây Đỏ Đen 
 18 
if (x != NIL) x->parent = y; 
} 
/************************************* 
* Chương trình chính thêm node x vào cây đỏ đen* 
*************************************/ 
static void insertFixup(NodeType *x) { 
/* Kiểm tra thuộc tính đỏ đen */ 
while (x != root && x->parent->color == RED) { 
/* we have a violation */ 
if (x->parent == x->parent->parent->left) { 
NodeType *y = x->parent->parent->right; 
if (y->color == RED) { 
/* chú bác là RED */ 
x->parent->color = BLACK; 
y->color = BLACK; 
x->parent->parent->color = RED; 
x = x->parent->parent; 
} else { 
/* chú bác là BLACK */ 
if (x == x->parent->right) { 
/* tạo ra x là con trái*/ 
Cây Đỏ Đen 
 19 
x = x->parent; 
rotateLeft(x); 
} 
/* đổi màu và xoay */ 
x->parent->color = BLACK; 
x->parent->parent->color = RED; 
rotateRight(x->parent->parent); 
} 
} else { 
/* Tương tự như trên */ 
NodeType *y = x->parent->parent->left; 
if (y->color == RED) { 
/* chú bác là is RED */ 
x->parent->color = BLACK; 
y->color = BLACK; 
x->parent->parent->color = RED; 
x = x->parent->parent; 
} else { 
/* chú bác là BLACK */ 
if (x == x->parent->left) { 
x = x->parent; 
Cây Đỏ Đen 
 20 
rotateRight(x); 
} 
} 
x->parent->color = BLACK; 
x->parent->parent->color = RED; 
rotateLeft(x->parent->parent); 
} 
} 
root->color = BLACK; 
} 
/*********************************************** 
* Cấp phát và thêm vào trên cây * 
***********************************************/ 
StatusEnum insert(KeyType key, RecType *rec) { 
NodeType *current, *parent, *x; 
/Tìm cha mới*/ 
current = root; 
parent = 0; 
while (current != NIL) { 
if (compEQ(key, current->key)) 
return STATUS_DUPLICATE_KEY; 
Cây Đỏ Đen 
 21 
parent = current; 
current = compLT(key, current->key) ? 
current->left : current->right; 
} 
/* Thiết lập node mới */ 
if ((x = malloc (sizeof(*x))) == 0) 
return STATUS_MEM_EXHAUSTED; 
x->parent = parent; 
x->left = NIL; 
x->right = NIL; 
x->color = RED; 
x->key = key; 
x->rec = *rec; 
/* Thêm node */ 
if(parent) { 
if(compLT(key, parent->key)) 
parent->left = x; 
else 
parent->right = x; 
} else { 
root = x; 
Cây Đỏ Đen 
 22 
} 
insertFixup(x); 
return STATUS_OK; 
} 
/************************************* 
* Chương trình chính loại bỏ node x * 
*************************************/ 
void deleteFixup(NodeType *x) { 
while (x != root && x->color == BLACK) { 
if (x == x->parent->left) { 
NodeType *w = x->parent->right; 
if (w->color == RED) { 
w->color = BLACK; 
x->parent->color = RED; 
rotateLeft (x->parent); 
w = x->parent->right; 
} 
if (w->left->color == BLACK && w->right->color == BLACK) { 
w->color = RED; 
x = x->parent; 
} else { 
Cây Đỏ Đen 
 23 
if (w->right->color == BLACK) { 
w->left->color = BLACK; 
w->color = RED; 
rotateRight (w); 
w = x->parent->right; 
} 
w->color = x->parent->color; 
x->parent->color = BLACK; 
w->right->color = BLACK; 
rotateLeft (x->parent); 
x = root; 
} 
} else { 
NodeType *w = x->parent->left; 
if (w->color == RED) { 
w->color = BLACK; 
x->parent->color = RED; 
rotateRight (x->parent); 
w = x->parent->left; 
} 
if (w->right->color == BLACK && w->left->color == BLACK) { 
Cây Đỏ Đen 
 24 
w->color = RED; 
x = x->parent; 
} else { 
if (w->left->color == BLACK) { 
w->right->color = BLACK; 
w->color = RED; 
rotateLeft (w); 
w = x->parent->left; 
} 
w->color = x->parent->color; 
x->parent->color = BLACK; 
w->left->color = BLACK; 
rotateRight (x->parent); 
x = root; 
} 
} 
} 
x->color = BLACK; 
} 
StatusEnum erase(iterator z) { 
NodeType *x, *y; 
Cây Đỏ Đen 
 25 
if (z->left == NIL || z->right == NIL) { 
/* y có một node con là NIL */ 
y = z; 
} else { 
/* Tìm cây thay thế với node con NIL */ 
y = z->right; 
while (y->left != NIL) y = y->left; 
} 
/* y chỉ có một con */ 
if (y->left != NIL) 
x = y->left; 
else 
x = y->right; 
/* Xoá y */ 
x->parent = y->parent; 
if (y->parent) 
if (y == y->parent->left) 
y->parent->left = x; 
else 
y->parent->right = x; 
else 
Cây Đỏ Đen 
 26 
root = x; 
if (y != z) { 
z->key = y->key; 
z->rec = y->rec; 
} 
if (y->color == BLACK) 
deleteFixup (x); 
free (y); 
return STATUS_OK; 
} 
StatusEnum eraseKey(KeyType key) { 
NodeType *z; 
/* Tìm node */ 
z = root; 
while(z != NIL) { 
if(compEQ(key, z->key)) 
break; 
else 
z = compLT(key, z->key) ? z->left : z->right; 
} 
if (z == NIL) return STATUS_KEY_NOT_FOUND; 
Cây Đỏ Đen 
 27 
return erase(z); 
} 
iterator next(iterator i) { 
if (i->right != NIL) { 
for (i = i->right; i->left != NIL; i = i->left); 
} else { 
iterator p = i->parent; 
while (p && i == p->right) { 
i = p; 
p = p->parent; 
} 
/* trả về node "inorder" */ 
i = p; 
} 
return i; 
} 
iterator begin() { 
/* Trả về con trỏ đến giá trị đầu tiên */ 
iterator i; 
for (i = root; i->left != NIL; i = i->left); 
Cây Đỏ Đen 
 28 
return i; 
} 
iterator end() { 
/* Trả về con trỏ đến giá trị cuối cùng */ 
return NULL; 
} 
RecType value(iterator i) { 
return i->rec; 
} 
StatusEnum find(KeyType key, iterator *iter) { 
NodeType *current; 
current = root; 
while(current != NIL) { 
if(compEQ(key, current->key)) { 
*iter = current; 
return STATUS_OK; 
} else { 
current = compLT (key, current->key) ? 
current->left : current->right; 
} 
} 
Cây Đỏ Đen 
 29 
return STATUS_KEY_NOT_FOUND; 
} 
int main(int argc, char **argv) { 
int maxnum, ct, n; 
RecType rec; 
KeyType key; 
StatusEnum status; 
/* Chạy bằng dòng lệnh: 
* 
* rbt maxnum 
* 
* rbt 2000 
* Xữ lý 2000 records 
* 
*/ 
iterator iter; 
maxnum = atoi(argv[1]); 
printf("maxnum = %d\n", maxnum); 
for (ct = maxnum; ct; ct--) { 
key = rand() % 90 + 1; 
if ((status = find(key, &iter)) == STATUS_OK) { 
Cây Đỏ Đen 
 30 
rec = value(iter); 
if (rec.stuff != key) printf("fail rec\n"); 
status = erase(iter); 
if (status) printf("fail: status = %d\n", status); 
} else { 
rec.stuff = key; 
status = insert(key, &rec); 
if (status) printf("fail: status = %d\n", status); 
} 
/* Hiễn thị các node */ 
{ 
iterator i; 
for (i = begin(); i != end(); i = next(i)) { 
RecType rec; 
rec = value(i); 
printf("%d\n", rec.stuff); 
} 
} 
return 0; 
Cây Đỏ Đen 
 31 
V- Nhận xét : 
Giống như cây tìm kiếm nhị phân thông thường, cây đỏ đen có thể cho phép việc tìm 
kiếm, chèn và xóa trong thời gian O(log2N). Thời gian tìm kiếm là gần như bằng nhau 
đối với hai loại cây, vì những đặc điểm của cây đỏ đen không sử dụng trong quá trình 
tìm kiếm. Điều bất lợi là việc lưu trữ cần cho mỗi node tăng chút ít để điều tiết màu đỏ-
đen (một biến boolean). 
Đặc thù hơn, theo Sedgewick, trong thực tế tìm kiếm trên cây đỏ đen mất khoảng 
log2N phép so sánh, và có thể chứng minh rằng nó không cần hơn 2*log2N phép so 
sánh. 
Thời gian chèn và xóa tăng dần bởi một hằng số vì việc phải thực thi phép lật màu và 
quay trên đường đi xuống và tại những điểm chèn. Trung bình một phép chèn cần 
khoảng chừng một phép quay. Do đó, chèn hày còn chiếm O(log2N) thời gian, nhưng 
lại chậm hơn phép chèn trong cây nhị phân thường. 
Bởi vì trong hầu hết các ứng dụng, có nhiều thao tác tìm kiếm hơn là chèn và xóa, có lẽ 
không có nhiều bất lợi về thời gian khi dùng cây đỏ đen thay vì cây nhị phân thuờng. 
Dĩ nhiên, điều thuận lợi là trong cây đỏ đen, dữ liệu đã sắp xếp không làm giảm hiệu 
suất O(N). 

File đính kèm:

  • pdfgiao_trinh_cay_do_den.pdf