| Strukture podataka i algoritmi |
| 8.2 Crveno-crna stabla |
Crveno-crno stablo je binarno stablo pretrazivanja
sa jos jednim dodatnom informacijom za svaki cvor:
bojom, koja je ili crvena ili crna.
Takodje je neophodno da vodimo racuna o roditelju svakog cvora,
tako da bi struktura cvora crveno-crnog stabla bila:
struct t_red_black_node {
enum { red, black } colour;
void *item;
struct t_red_black_node *left,
*right,
*parent;
}
Tokom ovog razmatranja,
NULL cvorove koji zavrsavaju stablo
smatracemo listovima i obojene u crno.
|
|
![]() | Osnovno crveno-crno stablo |
![]() | Osnovno crveno-crno stablo sa
dodatim strazarskim cvorovima.
Implementacije algoritama sa crveno-crnim cvorovima obicno
ukljucuju strazarske cvorove kao standardan nacin za prepoznavanje
da se doslo do lista.
Oni su, u stvari, crni NULL cvorovi iz osobine 2. |
Sada se vidi zasto je crveno-crno stablo dobro stablo za pretrazivanje: ono se uvek moze pretraziti u O(log n) koraka.
Kao i sa gomilama, dodavanja i brisanja iz crveno-crnog stabla remete crveno-crne osobine, tako da ih je potrebno popravljati. Da bismo ovo uradili, neophodno je da pogledamo nekoliko operacija na crveno-crnim stablima.
|
Rotacija je lokalna operacija u stablu pretrazivanja
koja ocuvava in-order poredak kljuceva.
Primetimo da u oba stabla, in-order obilazak daje:
A x B y C | ![]() |
left_rotate( Tree T, node x ) {
node y;
y = x->right;
/* Pretvorimo levo podstablo cvora y u desno podstablo cvora x */
x->right = y->left;
if ( y->left != NULL )
y->left->parent = x;
/* Novi roditelj cvora y je bivsi roditelj cvora x */
y->parent = x->parent;
/* Roditelj treba da pokazuje na cvor y umesto na cvor x */
/* Najpre proverimo da li se nalazimo u korenu - tada nema roditelja! */
if ( x->parent == NULL ) T->root = y;
else
if ( x == (x->parent)->left )
/* cvor x je bio sa leve strane svog roditelja */
x->parent->left = y;
else
/* inace je cvor x morao da bude sa desne strane */
x->parent->right = y;
/* Konacno, stavimo cvor x sa leve strane cvora y */
y->left = x;
x->parent = y;
}
rb_insert( Tree T, node x ) {
/* Dodavanje u stablo na uobicajen nacin */
tree_insert( T, x );
/* Sada oporavi crveno-crne osobine */
x->colour = red;
while ( (x != T->root) && (x->parent->colour == red) ) {
if ( x->parent == x->parent->parent->left ) {
/* Ako je roditelj x sa leve strane, tada je y desni ujak cvora x */
y = x->parent->parent->right;
if ( y->colour == red ) {
/* slucaj 1 - promeni boje */
x->parent->colour = black;
y->colour = black;
x->parent->parent->colour = red;
/* Pomeri x nagore kroz stablo */
x = x->parent->parent;
}
else {
/* y je crni cvor */
if ( x == x->parent->right ) {
/* a x je sa desne strane */
/* slucaj 2 - pomeri x nagore i rotiraj */
x = x->parent;
left_rotate( T, x );
}
/* slucaj 3 */
x->parent->colour = black;
x->parent->parent->colour = red;
right_rotate( T, x->parent->parent );
}
}
else {
/* ponoviti "if" deo sa izmenjenim "right" i "left" */
}
/* Oboji koren u crno */
T->root->colour = black;
}
Ovde je primer operacije dodavanja.
|
Animacija crveno-crnog stabla Animaciju su napisali Linda Luo, Mervyn Ng, Anita Lee, John Morris i Woi Ang. |
|
Posaljite komentare na adresu morris@ee.uwa.edu.au |
Studiranje koda otkriva samo jednu petlju. U toj petlji, cvor x u korenu podstabla cije crveno-crne osobine pokusavamo da oporavimo, moze biti pomeren nagore kroz stablo bar jedan nivo u svakoj iteraciji petlje. Posto je stablo u pocetku imalo visinu O(log n), postoji O(log n) iteracija. Procedura tree_insert takodje ima O(log n) slozenost, tako da procedura rb_insert sveukupno traje O(log n) koraka.
Kljucni pojmovi |
|
Dalje na AVL stabla Nazad na Sadrzaj |