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.. Ta đã bi
Trang 1TRƯỜ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
NGUYỄN HOÀI PHƯƠNG -0212234 NGUYỄN HỒNG PHÚ -0212226
BÀI BÁO CÁO MÔN CẤU TRÙC DỮ LIỆU 2 GVHD : Ths Phạm Phạm Tuyết Trinh
TP HCM , 2005
Trang 2Lờ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 Sv: Nguyễn Hoài Phương MSSV: 0212234 Sv:Nguyễn Hồng Phú MSSV: 0212226
Trang 3Cây Đỏ Đen Tháng 6 năm 2005
Nguyễn Hoài Phương 3 Nguyễn Hồng Phú
Mục lục:
Lời nói đầu: 2
Mục lục: 3
I- Giới thiệu: 4
II- Định nghĩa: 5
III- Các thuật toán cơ bản của Black and Red Tree 7
1- Thêm một Node mới 7
2- Xóa một node: 14
IV- Thuật toán cài đặt: 14
V- Nhận xét : 31
Trang 4I- 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ầ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
Trang 5Ng
Nhhơnbằncon
* Đ
KhhaiđốiĐểluôcâyMộnhịhơnsun
Tro
tử khôcân
Cây
Khđen
àn Nếu ta code cha của
p:
nhánh, sẽ trong trường
ân bằng
hời gian trubằng (ít ra
ấp xỉ số nodcận giải qu
hế nó có các, node cha đắc điểm
y xóa) một n
c tuân thủ, c
xếp thành mvào trước chèn những
a chúng - câ
ở thành mộhợp này, t
uy xuất nhancũng là cây
de con bên puyết vấn đề
c tính chất cnhỏ hơn no
ân bằng đưkiểm tra xemdựng lại cấu
hĩa:
hị phân tìm phải là đỏ
và các nodnode là đỏ,
ng dẫn từ gốnode mới, ccây sẽ được
nh O(logN)
y gần cân bằphải bằng s
ề cân bằng lcủa cây tìmode con phả
ược thực thi
m tính chấ
u trúc cây
kiếm( BSThoặc đen
de lá phải lunhững nod
ốc đến một cần phải tuâ
c cân bằng
không phânode là con m) theo thứ
t cân bằng v
h liên kết, d
uy xuất giả
) của cây, chằng) Điều
số node conlại cây: đó l
m kiếm nhị p
ải, bên cạnh
trong khi c
ất cân bằngBằng cách
n bên trái
là cây đỏ đphân ví dụ
h đó cây đỏ
chèn, xóa K
g của cây cnày, cây lu
các quy tắc
n
nó phải đencùng số lượquy tắc trên
n phải bảo đhĩa là mỗi no
en-là cây tì: node con
ỏ đen còn đ
Khi thêm m
có bị vi phuôn luôn đư
sau: (hình
ợng node đe-gọi là quy
005
Phú
node lớn mất cân
de sẽ là
u thay vì O(logN)
đảm cây ode trên
ìm kiếm trái nhỏ được bổ
một phần hạm hay ược giữ
3.2)
en
y tắc đỏ
Trang 6Số lượng ncao đen (bl
là mọi đườn
Bổ đề:
Một cây đỏCó: height height :Tính chấtThời gian
n tìm kiếm:
nh:
Hình 3.2 Mộ
n một đườn) Ta có thể gốc đến lá p
de +1) cây
2 * bh(x) O( log n )
ột ví dụ về c
ng dẫn từ gốphát biểu qhải có cùng
ây đỏ đen
ốc đến lá đưquy tắc 4 th
g chiều cao
ược gọi là c
eo một cáchđen
chiều
h khác
Trang 7Cây Đỏ Đen Tháng 6 năm 2005
Nguyễn Hoài Phương 7 Nguyễn Hồng Phú
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ác phép quay khi node đã được chèn
· Các phép quay trên đường đi xuống
Trang 8đi ttrị
TuyquaĐểcần
có nod
MộtamnodHìn
Hìn
Chmà
Mặnodđen
là đ
ép thêm vàotheo một đưcủa khóa no
y nhiên, tro
ay
bảo đảm k
n Theo quyhai node co
không vi phạ
y tắc như sa
on đỏ, chúnode gốc, nó
màu ảnh hư
e có màu đỏ
và phải củamàu
ước khi lật m
n thấy sau kphạm quy
ắc 4 không b
ng thể đồng
ó vấn đề vi pkhi đổi màu
ng ta đổi cácvẫn vẫn gi
bị vi phạm
g màu đỏ) lạphạm khi P
u, ta sẽ có h
t đầu như trêđến vị trí cầược điểm ch
qua phép lậ
ại có khả nă chuyển từ hai node đỏ
ên cây tìm k
ần chèn, đi hèn là phức
ần phải tiếnlàm xuất hithành đen ven)
đỏ-đen ra sa
P thay cho nhình 3.4a
i lật màu
đen của cây
ật, nhưng qăng bị vi phđen sang đỏtrên một hà
kiếm nhị phqua phải hatạp bởi các
n hành các piện tình trạn
và node cha
ao? chúng tanode cha) C
y không đổi
quy tắc 3 (mhạm Nếu no
ỏ, nhưng nếàng
Như vậy p
một node conode cha của
ếu node cha
hường:
vào giá màu và
àu khi
de đen trừ khi
Trang 9Ng
Điề
ta cĐốgốc
3 (xgốc
1.2
Thachè
lý
Nhthể
phép quay
n node mới c
i kiểm tra x
trên, node mững vị trí kh
mới được chhác nhau đố
9
uớc khi đi xbằng một pnode gốc và đen Điều n
hai node conày tránh sự
ều cao đen t
vi phạm
c đỏ-đen bị không và thự
Do vậy sau kững thao tác
khi
c hợp
e X có
Trang 10X lĐiềnodNgNếnodchá
Tha
và
Hìni) Kii) Kiii)
nh 3.5 Các
là một node
ều này có n
de con trái cgược lại, X l
u X là node
de P ở bên t
áu nội Bốn
ao tác phụcnhững bà c
nh 3.6 Ba kKhả năng 1Khả năng 2 Khả năng
biến dạng
e cháu ngoạnghĩa là, X lcủa G, hoặc
là một node
e cháu ngoạtrái hay bên
n trường hợp
c hồi quy tắccon của nó
khả năng sa: P đen 2: P đỏ và X3: P đỏ và X
của node đư
ược xác địnnăng xảy ra
nút
goại của Gnội của G
n node cha
u hoặc nó làcủa P và no
trái hoặc bêkhả năng tưrong hình 3
nh bởi các mđược xem x
màu và cấu hxét như sau
g bên node trái của P v
de con phải
P, tùy vào
u X là một n
hình của nou:(hình 3.6)
cha G
và P là của G
việc node ode X
Trang 11Ng
Chi) K
P đxunDoii) K
NếthacầnBâyphả
TrocânĐĐ
QphéKh
Trođốinàybằncây
y Đỏ Đen
guyễn Hoài
húng ta lần lKhả năng 1đen là trườn
ng khắc
đỏ-o vậy, khôngKhả năng 2
ng hợp đơn -đỏ (quy tắc
g bị vi phạm2: P đỏ và X
ỏ và X là no
àu Bắt đầumột phép lậnode mới X
ao tác như
hợp này, taSau đây là
h tạo nên câmàu node cân bằng
a có thể áp dcác bước ấ
e ông bà củacha của no
ở vị trí đỉnh
rên sẽ bảo t
X là node chnode cháu ng
ề màu Thagoại của G
goại, ta cần
50 tại node
c khi chèn n
nh 3.7a )xuấ3.7)
dụng ba bướấy:
a node X (tr
de X (node, theo huớn
toàn cây đỏ
háu ngoại củgoài nhưng
5, 87, 93 (v
và quay trái
sau:
luôn đỏ Nếcộng thêm
ao tác chèn
một phép q
e gốc, và chnode 12
g node X lên
hình 3.7b
e con trái Code con phảmàu khi cầ
iản và một v
e 25, 75 và đều đỏ, vì vỏ-đen và làm
e 25)
n (6) Đây l
Có một trườ
ải Thử làmần) Chỉnh sỉnh Một lầ
005
Phú
g có tắc 4)
vài
12 Ta vậy cần
m cho
là một
ờng hợp
m điều sửa cây
ần nữa
Trang 12Hìniii)Nếphélật Lưu
nh 3.7 Nod Khả năng
ỏ và X là no Cây đỏ đekhi chèn no
18 là node
X là node ch
X là cháu node cháu nộ
en được tạo ode 12) Xe cháu nội N
háu ngoại nội của G
ội, chúng tathành từ cá
em hình 3.8Node này v
Trang 13Ng
HìnCh
ở đnhưnod
y Đỏ Đen
guyễn Hoài
nh 3.8 Khảhỉnh lại sự sắđỉnh, như ta
ng khả năng
n cân bằng nhồi cây nhu
13
hình 3.8.cnode cháu n
ắc rối hơn
g 2, node chnhư trước (
u cũ) Phải c
nội Nếu ta cố qháu trong X(Thử làm đcần một giả
Thán
Nguy
quay phải n
X (18) đi ngiều này, rồi
ải pháp khác
ng 6 năm 20
yễn Hồng P
node ông bàgang hơn là
Trang 14ChnàonodĐĐ
QđâyQ
typSTSTSTST} S
ủ thuật cần
ép quay đầu8b Bây giờ,
ép quay, vớ
húng ta cũng
o (thứ tự kh
de thì khó mĐổi màu nodĐổi màu nod
IV- Th
pedef enumATUS_OKATUS_MEATUS_DUATUS_KEStatusEnum
dùng khi X
u biến X từ , trường hợp
ới node ông
g cần tô màhông quan tr
EY_NOT_Fm;
X là node chmột node c
p là tương t
bà ở đỉnh,
àu lại các núrọng, nhưng
háu nội là ticháu nội thà
tự như khả nnhư đã làm
út Ta làm đ
g nếu ta đợi
g như thế nà( node 25)
n
đặt:
iến hành haành node chnăng 1, và t
m trước đây
điều này trư
i đến khi saào) Các bướ
ha; node Xkhông phải vỉnh, về hướ
tìm kiếm vi
t 1 phần tử
n vì trong qu
ai phép quayháu ngoại, n
ta có thể áp Kết quả nh
ước khi làm
au khi quay
ớc là:
đây là nodvới node ônớng nâng X
iệc xóa 1 phvào cậy, và
uá trình thê
y hơn là mộnhư trong h
p dụng cùng
hư trong hìn
bất cứ phépmới tô màu
de 18)
ng bà; node lên (quay p
hỏi cây đen
i đảm
Trang 15Cây Đỏ Đen Tháng 6 năm 2005
Nguyễn Hoài Phương 15 Nguyễn Hồng Phú
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 */
Trang 16if (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;
Trang 17Cây Đỏ Đen Tháng 6 năm 2005
Nguyễn Hoài Phương 17 Nguyễn Hồng Phú
} 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;
Trang 18if (x != NIL) x->parent = y;
} /*************************************
* Chương trình chính thêm node x vào cây đỏ đen*
if (y->color == RED) { /* chú bác là RED */
if (x == x->parent->right) { /* tạo ra x là con trái*/
Trang 19Cây Đỏ Đen Tháng 6 năm 2005
Nguyễn Hoài Phương 19 Nguyễn Hồng Phú
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 */
if (x == x->parent->left) {
x = x->parent;
Trang 20rotateRight(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 *
Trang 21Cây Đỏ Đen Tháng 6 năm 2005
Nguyễn Hoài Phương 21 Nguyễn Hồng Phú
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;
else parent->right = x;
} else { root = x;
Trang 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;
Trang 23Cây Đỏ Đen Tháng 6 năm 2005
Nguyễn Hoài Phương 23 Nguyễn Hồng Phú
if (w->right->color == BLACK) { w->left->color = BLACK;
w->color = RED;
rotateRight (w);
w = x->parent->right;
} w->color = x->parent->color;
if (w->color == RED) { w->color = BLACK;
Trang 24w->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;
} StatusEnum erase(iterator z) { NodeType *x, *y;
Trang 25Cây Đỏ Đen Tháng 6 năm 2005
Nguyễn Hoài Phương 25 Nguyễn Hồng Phú
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 */
else y->parent->right = x;
else
Trang 26root = 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;
Trang 27Cây Đỏ Đen Tháng 6 năm 2005
Nguyễn Hoài Phương 27 Nguyễn Hồng Phú
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);
Trang 28return 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;
} }