Documente Academic
Documente Profesional
Documente Cultură
Laboratorul 10
De la SD
Salt la: Navigare, cutare
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
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; } }
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; }
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 ); }
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
Autentificare
Navigare
Pagina principal Pagina de Feedback Portalul comunitii Discut la cafenea Pagin aleatorie Ajutor
Teme de cas
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]