Sunteți pe pagina 1din 7

Laboratorul 10 - SD

Laboratorul 10
De la SD
Salt la: Navigare, cutare

Laboratorul 10 - Arbori rosu-negru


Responsabil : Bogdan Ghit (2010) Mircea Gherzan (2009) Andrei Homescu (2008)

Cuprins
[ascunde] [ascunde] 1 Obiective 2 Arbori binari de cautare 2.1 Implementarile operatiilor 2.1.1 Find 2.1.2 Insert 2.1.3 Remove 2.1.4 Predecessor/Successor 2.1.5 Parcurgerea 2.2 Rotatii in arbori de cautare 3 Arbori rosu-negru 4 Referine 4.1 Aplicatii

Obiective
In urma parcurgerii acestui laborator, studentul va fi capabil: sa sa sa sa sa implementeze operatiile esentiale efectuate de arborii binari de cautare inteleaga operatiile de rotatie in arborii binari de cautare inteleaga utilizarea operatiilor de rotatie in cadrul echilibrarilor efectuate de arborii AVL implementeze operatiile Insert si Find ale unui arbore rosu-negru utilizeze arbori binari de cautare si arbori rosu-negru in rezolvarea altor probleme

Arbori binari de cautare


Un arbore binar de cutare este o reprezentare a unei mulimi de valori cu ajutorul unui arbore binar, astfel nct fiecare nod din arborele binar sa conin cte un element din mulimea dat. Elementele mulimii se numesc chei; fiecare cheie poate avea asociate una sau mai multe valori, deci arborii binari de cutare (pe care i vom mai nota i Binary Search Tree sau BST) pot fi folosii ca dicionare. Valorile din mulime sunt distribuite nodurilor arborelui astfel nct s se respecte urmtoarea proprietate, numit proprietatea de arbore binar de cutare:
cheie[s] cheie[x] cheie[d], x A , s Stang [x] , d Drept [x]

Cu alte cuvinte, pentru orice nod x, cheile din subarborele su stng sunt mai mici dect cheia lui x, iar cheile din subarborele drept sunt mai mari dect cheia sa. Pentru o mulime de elemente dat, putem construi muli arbori binari de cutare cu elementele mulimii. De exemplu, pentru mulimea de elemente {1, 2, 3, 4, 5, 6}, civa arbori binari posibili sunt:

Arborii binari de cautare trebuie s efectueze intr-un timp eficient urmatoarele operatii: Find(A,x) cauta in dictionar daca exista cheia x si returneaza 1 daca o gaseste sau 0 daca nu exista in arbore (in alte implementari, aceasta functie poate returna chiar nodul cu cheia x sau NULL daca acesta nu exista).

file:///C|/Users/Matrix/Desktop/Laboratorul_10.htm[4/18/2012 21:44:49]

Laboratorul 10 - SD

Insert(A,x) adauga in dictionar cheia x, daca nu exista deja in dictionar. Remove(A,x) sterge din dictionar cheia x, daca aceasta exista deja. Primele 3 operaii necesit un timp O(d) pentru a accesa un nod din arbore aflat la adancimea d. In cazul arborilor binari oarecare, aceasta valoare poate fi maxim N-1, unde N este numarul de noduri din arbore, cum se poate vedea in figura 1. De aceea, dorim s minimizm adncimea arborelui pentru a minimiza timpul necesar fiecrei astfel de operaii.

Implementarile operatiilor
n memorie, arborele va fi stocat ca un pointer ctre nodul aflat n rdcin, iar fiecare nod va fi reprezentat printr-o structur care conine cel puin un membru pentru cheia din nod, un pointer ctre printele nodului i cte un pointer pentru fiecare fiu al nodului. Dac structura de date nu trebuie s suporte operaiile Predecessor/Successor, pointer-ul ctre printe poate fi omis pentru a face economie de spaiu de memorie.

Find
Find parcurge arborele de la rdcin spre frunze, apropiindu-se la fiecare pas n arbore de valoarea dat pe baza proprietii de arbore binar. Astfel, dac valoarea dat x este mai mic dect cheia nodului curent, atunci nu se poate afla n subarborele drept al nodului.
int Find( Node *root, int x ) { Node *p = root; while( p != NULL ) { if( p->key == x ) return 1; /* am gasit valoarea in arbore */ if( x < p->key) p = p->left; else p = p->right; } /* valoarea data nu exista in arbore */ return 0; }

Insert
Insert caut n arbore un gol (un nod sub care putem insera valoarea astfel nct s se pstreze proprietatea) n acelai fel ca Find.
void Insert( Node **root, int x ) { Nod *p; if( *root == NULL ) { /* am gasit un gol */ p = CreateNode(); p->key = x; *root = p; return; } p = *root; if( x == p->key ) { /* valoarea exista deja in arbore */ return; } if( x < p->key ) { /* valoarea data trebuie inserata in subarborele stang */ Insert( &p->left, x ); p->left->parent = p; /* actualizam parintele */ } if( x > p->key ) { Insert( &p->right, x ); p->right->parent = p; } }

Un exemplu al rulrii lui Insert(A,4.5) pe un arbore binar este prezentat n continuare:

Remove
Remove se efectueaz n mai muli pai: cutm valoarea dat n arbore; dac nu exist, operaia s-a terminat dac nodul gsit are 1 singur fiu, l eliminm din arbore, legnd direct printele su i unicul su fiu dac nodul gsit x are 2 fii, cutm n arbore succesorul su y, apoi nlocuim cheia lui x cu cheia lui y i l tergem pe y ca la pasul precedent; nodul y va avea ntotdeauna maxim un fiu ( demonstraia acestei afirmaii rmne ca tem de gndire).

file:///C|/Users/Matrix/Desktop/Laboratorul_10.htm[4/18/2012 21:44:49]

Laboratorul 10 - SD

Un exemplu de tergeri ale nodurilor 2 i 5 din primul exemplu de mai sus urmeaz:

Predecessor/Successor
Pentru implementrile operaiilor Predecessor/ Successor , vom folosi urmtoarea afirmaie ajuttoare: elementul minim/maxim din arbore este cel mai din stnga/dreapta nod din arbore. Pentru a calcula cel mai mic element dintr-un arbore, vom porni de la rdcina sa i vom vizita fiul stng atta timp ct acesta exist. Ultimul nod vizitat este chiar minimul din arbore. n mod similar se calculeaz i nodul de cheie maxim din arbore. Pentru calculul succesorului unui nod x, avem 2 cazuri: fiul drept al lui x exist; n acest caz, succesorul lui x este elementul cel mai mic din subarborele corespunztor fiului drept al lui x; folosim algoritmul prezentat nainte; x nu are un fiu drept; n acest caz, trebuie s urcm n arbore pn cnd nodul curent este fiu stng al printelui su, ceea ce nseamn c toate nodurile vizitate nainte aveau chei mai mici dect x (fiecare nod era fiu drept al printelui su, deci avea cheia mai mare), dar nodul curent i toi descendenii si (inclusiv x) au cheile mai mici dect printele.
Node *Successor( Node *nod ) { Node *p = nod; if( p->right != NULL ) { p = p->right; while( p->left != NULL ) p = p->left; return p; } while( p->parent != NULL && p == p->parent->right ) p = p->parent; return p->parent; }

n mod similar, se implementeaz i funcia Predecessor.

Parcurgerea
Parcurgerea n inordine a unui BST genereaz cheile din arbore n ordine cresctoare (demonstraia acestei afirmaii se face uor prin inducie). Putem folosi arborii binari de cutare mpreun cu parcurgerea n inordine ca algoritm de sortare.
void Inorder( Node *nod ) { if( !nod ) return; Inorder( nod->left ); printf( %d , nod->key ); /* aici putem efectua orice operatie */ Inorder( nod->right ); }

Rotatii in arbori de cautare


Pentru a reduce complexitatea unora dintre operaiile menionate la O(logN), putem efectua pai suplimentari in cadrul lor pentru a ne asigura c arborele este echilibrat intr-o oarecare msura. Echilibrarea arborelui se poate face prin diverse metode ca reconstruirea acestuia (in cazul scapegoat trees) sau rotaii ale nodurilor arborilor (metoda utilizata de arborii rou-negru, AVL sau treaps). Cele 2 tipuri de operatii de rotaie sunt prezentate in figura de mai jos.

file:///C|/Users/Matrix/Desktop/Laboratorul_10.htm[4/18/2012 21:44:49]

Laboratorul 10 - SD

void LeftRotation(Node **root, Nod *x) { Node *y = x->right; // subarborele stang al lui y devine subarborele drept al lui x x->right = y->left; y->left->parent = x; // leaga parintele lui x la y y->parent = x->parent; if (x->parent == NULL ) *root = y; if (isLeftChild(x)) x->parent->left = y; if (isRightChild(x)) x->parent->right = y; // x este subarbore stang al lui y y->left = x; x->parent = y; }

Arbori rosu-negru
Arborii rou-negru introduc cteva restricii suplimentare asupra nodurilor arborelui pentru a-l menine aproximativ echilibrat. n urma unei operaii care duce la nclcarea proprietilor, se efectueaz operaii de recolorare i rotaie asupra arborelui. Nodurile unui arbore rou-negru sunt completate cu un cmp: culoarea nodului; fiecare nod poate avea una dintre cele 2 culori din denumire. De asemenea, este adugat la arbore un nod-santinel, care ine loc lui NULL n toate operaiile de mai sus; toti pointerii catre noduri inexistente vor indica de fapt acest pseudonod. Ne vom referi la toate apariiile acestui pseudonod ca fiu al unui nod prin termenul frunz. Orice arbore rou-negru valid trebuie s respecte urmtoarele 5 proprieti: 1. 2. 3. 4. 5. Orice nod este rou sau negru Rdcina are culoarea neagr Toate frunzele sunt negre Un nod rou are ambii fii negri (cu alte cuvinte, dou noduri roii nu pot fi adiacente) Pe orice drum elementar de la rdcin la o frunz, exist acelai numr de noduri negre

Singurele operaii care modific arborele, deci pot duce la nclcarea acestor proprieti, sunt Insert i Remove. Vom trata n continuare doar reechilibrarea dup inserare, fiind o operaie destul de complex. Inserarea ntr-un arbore rou-negru efectueaz o operaie Insert specific unui BST, apoi coloreaz noul nod x n rou i verific dinspre nod spre rdcin dac au aprut nclcri ale proprietilor. Vom nota prin px printele lui x, bx bunicul lui x (adic printele lui px) i prin ux unchiul lui x (cellalt fiu al lui bx n afar de px). Cazurile care pot aprea sunt: 1. px e negru, deci proprietatea 4 (pe care o vom nota cu P4) nu a fost nclcat; am adugat un nod rou, deci i celelate proprieti sunt respectate; 2. px i ux sunt roii; conform P4, bx nu poate fi rou; colorm px i ux n negru, bx n rou i repetm algoritmul de la pasul 1 pentru bx. 3. px este rou, iar ux este negru. Dac x i px sunt fii pe direcii diferite ale prinilor (de exemplu, x este fiul stng al lui px, care la rndul su este fiul drept al lui bx), efectum nti o rotaie pe muchia (x,px). Mai departe recolorm bx n rou, px n negru i efectum o rotaie a perechii (px,bx). n acest moment, algoritmul s-a ncheiat. La sfrit, vom recolora rdcina arborelui n negru.
void InsertRB(Node **root, int val) { Node *x, *px, *bx, *ux; x = Insert(root, val); x->culoare = RED; while(x != *root && x->parent->culoare == RED ) { px = p->parent; bx = px->parent; if( px == bx->left ) { ux = bx->roght; /* cazul 2 */ if( ux->culoare == RED ) { px->culoare = BLACK; ux->culoare = BLACK; bx->culoare = RED; x = bx; continue; } /* cazul 3 de mai sus */ if( x == px->right ) {

file:///C|/Users/Matrix/Desktop/Laboratorul_10.htm[4/18/2012 21:44:49]

Laboratorul 10 - SD

LeftRotation(root, px); x = px; px = x->parent; px->culoare = BLACK; bx->culoare = RED; RightRotation(root, bx); /* x=px, y=bx in figura */ break ; } } else { /* la fel ca mai sus, dar cu stanga/dreapta inversate */ } } root->culoare = BLACK; }

Se observ c numrul maxim de rotaii efectuate la o singur reechilibrare este 2; algoritmul poate parcurge un numr mare de noduri, dar pentru fiecare nod vizitat n afar de ultimul va efectua doar recolorri. Pentru arborele rou-negru cu valorile {5,15, 18, 20, 25, 30,50}, inserarea valorii 28 presupune efectuarea urmtoarelor operaii:

Referine
Cormen, Leiserson, Riverst - "Introducere in algoritmi" (Capitolul 14 Arbori rosu-negru) www.cs.otago.ac.nz/cosc242/lectures.html

Aplicatii
1. [1p] Definiti structura BNode prin care veti reprezenta un arbore binar de cautare:
typedef struct bnode { int key; int color; int visited; struct bnode *left; struct bnode *right; struct bnode *parent; } BNode;

2. 3.

4.

5. 6. 7.

si urmatoarele operatii: BNode *CreateNode(); void DestroyTree(BNode *root); [2p] Implementati operatia de inserare a unei chei intr-un arbore binar de cautare. void Insert (BNode **root, int key); [3p] Afisati arborele pe nivele. Daca succesorul unui nod este NULL, in locul acestuia se va afisa simbolul '*'. a) [2p] implementati o functie recursiva pentru afisarea nodurilor de pe nivelul k: void printLevel(BNode *root, int k); b) [0.5p] implementati o functie care intoarce inaltimea h a arborelui: int getHeight(BNode *root); c) [0.5p] implementati o functie care afiseaza nodurile de pe fiecare nivel, pornind de la 1 (radacina) si pana la h (ultimul nivel). Folositi aceasta functie pentru testarea urmatoarelor task-uri. [6p] Implementati operatia de stergere a unei chei dintr-un arbore binar de cautare. a) [0.5p] implementati o functie recursiva sau iterativa pentru gasirea unei chei in arbore: BNode *Find(BNode *root, int x); b) [0.5p] implementati o functie care intoarce nodul ce contine cheia minima din arbore: BNode *GetMinimum(BNode *root); c) [2p] implementati o functie care intoarce succesorul unui nod din arbore: BNode *Succesor(BNode *node); d) [3p] implementati o functie care sterge un nod din arbore: void Delete(BNode **root, int key); [3p] Implementati operatiile de rotire stanga/dreapta pentru un arbore binar de cautare. void LeftRotation(BNode **root, BNode *x); void RightRotation(BNode **root, BNode *x); [3p] Implementati operatia de inserare intr-un arbore rosu-negru. void InsertRB(BNode **root, int val); [2p] Sortati un sir de numere intregi citite dintr-un fisier folosind un arbore binar de cautare sau un arbore rosu-negru. a) [1p] implementati o functie recursiva pentru parcurgerea in inordine a unui arbore binar

file:///C|/Users/Matrix/Desktop/Laboratorul_10.htm[4/18/2012 21:44:49]

Laboratorul 10 - SD

b) [1p] implementati o functie nerecursiva pentru parcurgerea in inordine a unui arbore binar, fara a utiliza o stiva. Adus de la "http://cursuri.cs.pub.ro/~sd/wiki/index.php/Laboratorul_10" Categorie: Laboratoare
Vizualizri

Pagin Discuie Vezi sursa Istoric


Unelte personale

Autentificare
Navigare

Pagina principal Pagina de Feedback Portalul comunitii Discut la cafenea Pagin aleatorie Ajutor
Teme de cas

Tema Tema Tema Tema Tema Teme Teme


Laboratoare

de cas 1 de cas 2 de cas 3 de cas 4 de cas 5 2008-2009 2009-2010

Note Laborator Laboratorul 1 Laboratorul 2 Laboratorul 3 Laboratorul 4 Laboratorul 5 Laboratorul 6 Laboratorul 7 Laboratorul 8 Laboratorul 9 Laboratorul 10 Laboratorul 11 Laboratorul 12 Laboratorul 13 Laboratorul 14
Caut

Du-te

Caut

Trusa de unelte

Ce se leag aici Modificri corelate Trimite fiier Pagini speciale Versiune de tiprit Legtur permanent

Ultima modificare 06:39, 28 aprilie 2011. Aceast pagin a fost vizitat de 6.148 ori. Coninutul este disponibil sub GNU Free Documentation License 1.2. Politica de confidenialitate Despre SD

file:///C|/Users/Matrix/Desktop/Laboratorul_10.htm[4/18/2012 21:44:49]

Laboratorul 10 - SD

Termeni

file:///C|/Users/Matrix/Desktop/Laboratorul_10.htm[4/18/2012 21:44:49]

S-ar putea să vă placă și