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.
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
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:
- giao_trinh_cay_do_den.pdf