You are on page 1of 103

ARBORI

l. Dr. Ing. erban Radu Departamentul de Calculatoare Facultatea de Automatic i Calculatoare

Necesitatea structurii de arbore


Un arbore combin avantajele oferite de alte dou structuri: tablourile i listele nlnuite Arborii permit, pe de o parte, executarea unor cutri rapide, la fel ca i tablourile ordonate, iar pe de alt parte, inserarea i tergerea rapid a elementelor, la fel ca o list nlnuit

Operaii cu un tablou ordonat


S presupunem c avem un tablou ale crui elemente sunt ordonate Un astfel de tablou permite cutarea rapid a unui anumit element, utiliznd metoda cutrii binare De asemenea, parcurgerea unui tabou ordonat este o operaie rapid, fiecare element fiind vizitat n ordine

Inserarea ntr-un tablou ordonat este lent


Pe de alt parte, dac dorim s inserm un nou element ntr-un tablou ordonat, trebuie mai nti s gsim locul unde vom insera elementul, dup care s deplasm toate elementele mai mari cu o poziie spre dreapta, pentru a-i face loc tergerea unui element presupune aceeai operaie de deplasare multipl, fiind deci la fel de lent

Operaii cu o list nlnuit


Operaiile de inserare i tergere se efectueaz repede n cazul utilizrii listelor nlnuite Acestea se reduc la modificarea pointerilor i se efectueaz ntr-un timp constant Cutarea unui anumit element ntr-o list este o operaie lent

Cutarea ntr-o list nlnuit este lent


Trebuie s pornim de la nceputul listei i s vizitm fiecare element, pn cnd l gsim pe cel dorit n cazul mediu, cutarea presupune vizitarea a N/2 elemente i compararea cheii fiecruia cu valoarea dorit

O soluie posibil, care s permit cutarea unui element ntr-un timp mai scurt, este de a utiliza o list nlnuit ordonat, n care elementele sunt aezate n ordine Dar cutarea presupune parcurgerea elementelor, ncepnd cu primul din list i vizitnd n ordine toate elementele, deoarece singura modalitate de a avea acces la un element este de a urma lanul de legturi care conduc la el

Cutarea ntr-o list nlnuit este lent

Arbori

Arborii, care reprezint una dintre cele mai interesante structuri de date, ofer ambele faciliti:
Inserarea

i tergerea rapid din cazul listelor nlnuite Cutarea rapid din cazul tablourilor

Arbori
Arborii sunt utilizai n descrieri ierarhice, pentru modelarea unor obiecte sau fenomene Descrierea ierarhic se refer la descompunerea unei entiti n subentiti, fiecare dintre ele putnd fi caracterizate printr-un set de atribute sau nsuiri

Arbori
Utiliznd o astfel de descriere, se realizeaz o ierarhizare a prilor unei entiti pe unul sau mai multe niveluri Organizarea ierarhic este ntlnit n diverse domenii: organizarea administrativ a unei companii, planificarea meciurilor n cadrul unui turneu sportiv, evaluarea unor expresii aritmetice

Ce este un arbore
Un arbore const din noduri, care sunt unite prin arce Vom reprezenta nodurile prin cercuri, iar arcele, prin linii care unesc cercurile

Noduri
Nodurile reprezint, de regul, entiti din lumea real, cum ar fi valori numerice, persoane, pri ale unei maini, rezervri de bilete de avion Nodurile sunt elemente obinuite pe care le putem memora n orice alt structur de date

Arce
Arcele dintre noduri reprezint modul n care nodurile sunt conectate Este uor i rapid s ajungem de la un nod la altul dac acestea sunt conectate printrun arc Arcele sunt reprezentate n C i C++ prin pointeri

nlimea unui arbore

Valoarea maxim de pe nivelurile nodurilor terminale

Ordin (grad)
Numrul de descendeni direci ai unui nod reprezint ordinul sau gradul nodului Ordinul sau gradul arborelui este valoarea maxim luat de gradul unui nod component al arborelui

Tipuri de arbori
Arbori binari, n care fiecare nod dintr-un arbore are cel mult doi fii Arbori multici, n care nodurile pot avea mai muli fii

Arbori

2-3-4 Arbori B Arbori AVL (Adelson-Velskii i Landis)

Arbori binari
Dac orice nod din arbore poate avea cel mult doi fii, atunci arborele se numete arbore binar Cei doi fii ai unui nod se numesc fiu stng i, respectiv, fiu drept, n funcie de poziia lor n reprezentarea grafic a arborelui Un nod care nu are niciun fiu se numete frunz

Arbori binari
ntre numrul N de noduri al unui arbore binar i nlimea sa H exist relaiile: H N 2H 1 log2N H N

Arbori binari de cutare

Cheia fiului stng trebuie s fie mai mic dect cea a printelui, iar cheia fiului drept trebuie s fie mai mare sau egal cu cea a printelui

Reprezentarea unui arbore binar


Se memoreaz nodurile la adrese oarecare din memorie, utiliznd pointeri pentru a conecta fiecare nod cu fiii si typedef struct tnod { void * val; // valoare memorat n nod struct tnod * st; // succesor la stnga struct tnod * dr; // succesor la dreapta } tnod;

Arbori neechilibrai
ntr-un arbore neechilibrat, majoritatea nodurilor sunt situate de o singur parte a rdcinii, iar anumii subarbori pot fi, la rndul lor, neechilibrai Dezechilibrarea arborilor poate proveni de la ordinea n care sunt inserate cheile

Operaii frecvente asupra arborilor


Cutarea unui nod Inserarea unui nod Traversarea arborelui

preordine n inordine n postordine

tergerea unui nod

Cutarea unui nod

Cutarea unui nod cu o anumit cheie este cea mai simpl operaie

Eficiena operaiei de cutare


Timpul necesar pentru gsirea unui nod depinde de numrul de niveluri parcurse pn cnd acesta este gsit Timpul este direct proporional cu logaritmul binar al numrului de noduri

Inserarea unui nod


Pentru a insera un nod, trebuie mai nti s gsim locul n care l vom insera Aceast operaie este similar cu cea de cutare a unui nod care nu exist Se parcurge calea de la rdcin pn la nodul respectiv, care va fi printele noului nod

Inserarea unui nod

Dup ce am gsit nodul printe, noul nod va fi conectat ca fiu stng sau drept al acestuia, dup cum valoarea cheii sale este mai mic sau mai mare dect cea a nodului printe

Inserarea unui nod


1. Creeaz un nod nou 2. Dac arborele este vid atunci noul nod devine rdcin 3. Altfel

3.1.

ncepnd de la rdcin 3.2. Dac valoarea nodului de inserat este mai mic dect valoarea rdcinii atunci ne deplasm recursiv la stnga 3.3. Dac nu mai este nimic la stnga, se insereaz nodul

Inserarea unui nod


3.4.

Dac valoarea nodului de inserat este mai mare dect valoarea rdcinii atunci ne deplasm recursiv la dreapta 3.5. Dac nu mai este nimic la dreapta, se insereaz nodul

Traversarea arborelui
Traversarea unui arbore presupune vizitarea tuturor nodurilor, ntr-o anumit ordine Traversarea nu este o operaie rapid, dar este util n anumite situaii Exist trei moduri de traversare a unui arbore: inordine, preordine, postordine

Traversarea n inordine
Traversarea n inordine a unui arbore va conduce la vizitarea nodurilor, n ordinea cresctoare a valorilor cheilor acestora Dac dorim s crem o list sortat care s cuprind toate elementele unui arbore binar de cutare, parcurgerea n inordine este o soluie

Traversarea n inordine
Funcia recursiv care traverseaz un arbore este apelat cu un parametru reprezentnd o structur de tip nod, care este chiar rdcina arborelui Funcia trebuie s efectueze trei operaii:

Un

apel recursiv pentru a traversa subarborele stng al nodului Vizitarea nodului curent Un apel recursiv pentru a traversa subarborele drept al nodului

Exemplu Traversarea unui arbore cu trei noduri

Presupunem c avem de traversat un arbore cu trei noduri: rdcina A, cu fiul stng B i fiul drept C

Traversarea n preordine i postordine


Aceste traversri sunt utile pentru programe care analizeaz expresii aritmetice O expresie aritmetic poate fi reprezentat printr-un arbore binar Nodul rdcin conine un operator, iar fiecare din subarborii si reprezint fie numele unei variabile, fie o alt expresie

Traversarea n preordine

Succesiunea pentru cazul traversrii n preordine este :


Viziteaz

nodul Apel recursiv pentru traversarea subarborelui stng Apel recursiv pentru traversarea subarborelui drept

Traversarea n postordine

Traversarea n postordine conine tot cei trei pai, n succesiunea:


Apel

recursiv pentru traversarea subarborelui stng Apel recursiv pentru traversarea subarborelui drept Viziteaz nodul

//traversare postfixata arbore binar void postfix(tnod * r) { if (r == NULL) return; postfix(r->st); // stanga postfix(r->dr); // dreapta printf(%d , r->val); //radacina }

Valorile minime i maxime


Pentru determinarea valorii minime, ne deplasm n fiul stng al rdcinii De acolo, n fiul stng al acelui fiu .a.m.d., pn cnd ajungem la un nod care nu mai are niciun fiu stng Acest nod conine valoarea minim din arbore

Valorile minime i maxime


Va fi necesar s tim cum se determin minimul, pentru a terge un nod din arbore Pentru determinarea nodului cu valoarea maxim procedm similar, avansnd mereu spre fiul drept, pn cnd gsim un nod care nu mai are niciun fiu drept Acest nod va conine valoarea maxim

tergerea unui nod


Mai nti se caut nodul care va fi ters Dup ce am gsit nodul, apar trei cazuri care trebuie considerate separat: 1. Nodul care va fi ters este o frunz (nu are fii) 2. Nodul are un singur fiu 3. Nodul are doi fii

Cazul 1. Nodul ters nu are fii


Pentru a terge un nod frunz se modific pointerul ctre nodul printe, atribuindu-i acestuia valoarea NULL Trebuie s eliminm explicit nodul din memorie, apelnd funcia free()

Cazul 2. Nodul ters are un singur fiu


Nodul ters are dou legturi: una ctre printe i cealalt ctre unicul descendent Vom tia nodul din aceast secven, conectnd direct singurul fiu al nodului cu nodul printe Pointerul corespunztor al printelui va fi modificat, astfel nct s indice spre fiul nodului ters

Cazul 3. Nodul ters are doi fii

Dac nodul ters are doi fii, nu l putem nlocui pur i simplu cu unul dintre acetia, cel puin n cazul n care fiul are la rndul su ali fii

Cutarea succesorului
ntr-un arbore binar de cutare, nodurile sunt n ordinea cresctoare a cheilor Pentru un anumit nod, nodul cu cheia imediat superioar se numete succesorul n inordine al nodului, sau pur i simplu succesorul nodului

Cutarea succesorului
Pentru a terge un nod cu doi fii, vom nlocui nodul ters cu succesorul su Aceast operaie pstreaz ordinea elementelor Operaia se complic dac succesorul nodului ters are la rndul su succesori

Cutarea succesorului
Algoritmul se deplaseaz n fiul drept al nodului ters, a crui cheie este mai mare n urmtorul pas, se efectueaz o deplasare n fiul stng al fiului drept (dac exist un astfel de fiu), continundu-se pe ct posibil deplasarea pe o cale alctuit numai din fii stngi Ultimul nod din aceast cale este succesorul nodului iniial

Cutarea succesorului
Nodul pe care l cutm este minimul mulimii de noduri care sunt mai mari dect nodul original Cnd ne deplasm n subarborele drept, toate nodurile de acolo sunt mai mari dect cel iniial, aceasta rezultnd din modul de definire a unui arbore binar de cutare

Cutarea succesorului
Dorim s determinm cea mai mic valoare din acest subarbore Valoarea minim dintr-un arbore se poate determina urmnd calea care pornete de la rdcin i merge numai prin fiii stngi Algoritmul va determina valoarea minim care este mai mare dect nodul original Aceast valoare este chiar succesorul cutat

Cutarea succesorului

Dac fiul drept al nodului nu are fii stngi, succesorul este el nsui

Algoritmul pentru determinarea succesorului


Funcia getSuccesor() ntoarce succesorul unui nod delNode, pe care l primete ca parametru Funcia presupune existena subarborelui drept al nodului delNode, ceea ce este adevrat, din moment ce nodul ters are doi fii

Algoritmul pentru determinarea succesorului


Funcia ntoarce nodul cu valoarea imediat mai mare dect delNode Funcia se deplaseaz n fiul drept, apoi n descendenii stngi ai acestuia Funcia parcurge, ntr-o bucl while, calea format din descendenii stngi ai acestui fiu drept La terminarea buclei while, variabila succesor conine succesorul nodului delNode

Algoritmul pentru determinarea succesorului


Dup ce am determinat succesorul, trebuie s avem acces i la printele acestuia Vom memora i printele nodului curent, n variabila succesorParent Nodul succesor poate fi situat n dou poziii distincte, n raport cu current, nodul care va fi ters Succesorul este fie fiul drept al lui current, fie unul dintre descendenii stngi ai acestuia

1. succesorParent delNode 2. succesor delNode 3. current delNodedr //deplasare n fiul drept 4. while (current != NULL) //pn cnd nu mai sunt fii stngi 4.1. succesorParent succesor 4.2. succesor current 4.3. current currentst

Pseudocod getSuccesor

//deplasare n fiul stng

Pseudocod getSuccesor
5. if (succesor != delNodedr) //daca succesorul nu este chiar fiul drept //se modifica pointerii 5.1. succesorParentst succesordr 5.2. succesordr delNodedr 6. return succesor

succesor este fiul drept al lui delNode


Dac succesor este chiar fiul drept al lui delNode, lucrurile se simplific, deoarece putem deplasa subarborele cu rdcina succesor (de fapt, subarborele drept al acestuia, cel stng fiind vid) n locul nodului ters Operaia se efectueaz n doi pai:

succesor este fiul drept al lui delNode


1. Se elimin legtura dintre cmpul dr (sau st, dup caz) al nodului printe i nodul ters, atribuindu-se acestui cmp valoarea succesor 2. Subarborele stng al lui current este conectat ca subarbore stng al lui succesor, dup ce, n prealabil, a fost deconectat de la current

Pseudocod pentru tergerea nodului


//determin succesorul nodului ters(current) 1. succesor getSuccesor(current) //conecteaz printele lui current cu succesor 2. if (current == root) then root = succesor

Pseudocod pentru tergerea nodului

3. else dac exist fiul stng then parentst succesor

else parentdr succesor //conecteaz succesorul cu fiul stng al lui current

4. succesorst currentst

Observaii
Pasul 1: Dac nodul ters, current, este chiar rdcina, care nu are printe, va fi necesar s atribuim valoarea succesor rdcinii arborelui n caz contrar, nodul ters este fie fiul stng, fie cel drept al unui alt nod Cmpul corespunztor al nodului printe va fi modificat pentru a indica spre nodul succesor

Observaii
Pasul 2: Fiul stng al nodului ters (current) este conectat ca fiu stng al lui succesor Proprietate: Un nod succesor nu va avea niciodat un fiu stng Aceast proprietate este adevrat, indiferent dac succesorul este chiar fiul drept al nodului ters sau unul din descendenii stngi ai acestuia

Observaii
Algoritmul utilizat pentru determinarea succesorului parcurge mai nti fiul drept, apoi descendenii stngi ai acestuia Algoritmul se oprete cnd ajunge la un nod fr niciun fiu stng deci, din definiia algoritmului, este clar c succesorul nu poate avea un astfel de fiu Dac ar fi avut, acel fiu stng ar fi fost succesor n locul su

Observaii
Succesorul poate avea un fiu drept Existena fiului drept nu este o problem dificil, atunci cnd succesorul este fiul drept al nodului ters Cnd deplasm succesorul, subarborele su drept se deplaseaz mpreun cu el Nu exist o suprapunere cu fiul drept al nodului ters, deoarece acest fiu este succesorul nsui

succesor este un descendent stng al fiului drept al lui delNode


Dac succesor este un descendent stng al fiului drept al nodului care va fi ters, operaia de tergere va necesita 4 pai: 1. Fiul drept al succesorului devine fiul stng al printelui succesorului 2. Fiul drept al nodului ters devine fiul drept al succesorului

succesor este un descendent stng al fiului drept al lui delNode


3. Se terge legtura care l conecteaz pe current ca fiu drept (sau stng) al printelui su, conectndu-se succesor n locul lui current 4. Subarborele stng al nodului ters devine subarborele stng al lui succesor Primii doi pai sunt efectuai n funcia getSuccesor(), iar ultimii doi, n funcia de tergere

Instruciunile din cei 4 pai


1. succesorParentst succesordr 2. succesordr delNodedr 3. parentdr succesor 4. succesorst currentst

Observaii
Pasul 1 are ca efect nlocuirea succesorului cu subarborele su drept Pasul 2 pstreaz fiul drept al nodului ters n locul potrivit (ceea ce se ntmpla automat atunci cnd succesorul era fiul drept al nodului ters) Paii 1 i 2 sunt executai n instruciunea if din finalul funciei getSuccesor()

Eficiena arborilor binari


Majoritatea operaiilor asupra arborilor presupun o parcurgere descendent pentru cutarea unui anumit nod Ct timp dureaz o astfel de cutare ntr-un arbore? ntr-un arbore complet, aproximativ jumtate din noduri se afl pe ultimul nivel

Eficiena arborilor binari


Pe parcursul unei cutri, vom vizita cte un nod de pe fiecare nivel Prin urmare, durata necesar operaiei de cutare va fi direct proporional cu numrul de niveluri Presupunnd c arborele este complet, n tabel se prezint numrul de niveluri necesar pentru memorarea anumitor numere de noduri

Eficiena arborilor binari


Dac notm numrul de noduri din prima coloan cu N, iar numrul de niveluri din coloana a doua cu L, observm c N este inferior cu o unitate fa de 2 ridicat la puterea L: N = 2L 1 Adunnd 1 n ambii membri ai ecuaiei, rezult: N + 1 = 2L

Eficiena arborilor binari


Aceast notaie este echivalent cu: L = log2(N + 1) Prin urmare, timpul necesar pentru executarea operaiilor elementare asupra arborilor binari este proporional cu logaritmul binar al lui N

Comparaii ntre arbori i celelalte structuri de date


ntr-un tablou neordonat sau ntr-o list cu 1.000.000 de elemente, sunt necesare, n medie, 500.000 de comparaii pentru a cuta un anumit element ntr-un arbore cu acelai numr de noduri, numrul de comparaii efectuate este ns cel mult 20

Comparaii ntre arbori i celelalte structuri de date


ntr-un tablou ordonat, putem cuta rapid un element, dar inserarea unui nou element va necesita, n medie, deplasarea a 500.000 de elemente Inserarea unui nod ntr-un arbore cu 1.000.000 de elemente necesit numai 20 de comparaii i un timp scurt pentru a conecta noul nod n arbore

Comparaii ntre arbori i celelalte structuri de date


tergerea unui element dintr-un tablou cu 1.000.000 de elemente necesit, n medie, deplasarea a 500.000 de elemente tergerea unui nod dintr-un arbore cu acelai numr de noduri presupune cel mult 20 de comparaii pentru a cuta elementul, plus alte cteva, necesare cutrii succesorului su, i o durat scurt de timp pentru a realiza efectiv tergerea elementului i nlocuirea sa cu succesorul

Comparaii ntre arbori i celelalte structuri de date


Arborii asigur o implementare eficient a tuturor operaiilor elementare asupra structurilor de date Traversarea unui arbore nu este ns la fel de rapid ca i celelalte operaii, dar traversrile nu sunt utilizate foarte frecvent n aplicaiile care presupun memorarea unor baze mari de date

Concluzii
Arborii sunt alctuii din noduri, unite prin muchii Rdcina este nodul cel mai din vrf al unui arbore; nu are un nod printe n orice arbore binar, un nod are cel mult doi fii

Concluzii
ntr-un arbore binar de cutare, toate nodurile care sunt descendeni stngi ai unui nod A au chei mai mici dect A; toate nodurile care sunt descendeni drepi ai lui A au chei mai mari (sau egale) fa de A Arborii permit executarea cutrilor, inserrilor i tergerilor ntr-un timp O(logN)

Concluzii
Nodurile reprezint entiti de date memorate n cadrul arborelui Muchiile se reprezint prin pointeri ctre fiii fiecrui nod Traversarea unui arbore presupune vizitarea tuturor nodurilor sale, ntr-o anumit ordine Cele mai simple traversri sunt cele n preordine, inordine i postordine

Concluzii
Un arbore este neechilibrat dac rdcina are mai muli descendeni stngi dect drepi, sau invers Cutarea unui nod presupune compararea valorii cutate cu cheia dintr-un anumit nod i avansul la fiul stng al nodului, dac valoarea cutat este mai mic, respectiv la fiul drept, dac valoarea este mai mare dect cheia nodului

Concluzii
Inserarea unui nod necesit gsirea locului potrivit i apoi modificarea unuia din pointerii nodului printe, astfel nct noul nod s devin fiul acestuia Traversarea n inordine realizeaz vizitarea nodurilor dintr-un arbore de cutare n ordine cresctoare Traversrile n preordine i postordine sunt utile la evaluarea expresiilor aritmetice

Concluzii
Dac un nod nu are fii, poate fi ters, atribuind pointerului corespunztor printelui valoarea NULL Dac un nod are un singur fiu, poate fi ters, conectnd fiul la pointerul corespunztor printelui acelui fiu Dac un nod are doi fii, tergerea se efectueaz prin nlocuirea acestuia cu succesorul su

Concluzii
Succesorul nodului A este nodul cu valoarea minim din subarborele drept al lui A (a crui rdcin este deci fiul drept al lui A) La tergerea unui nod cu doi fii, apar mai multe cazuri, dup cum succesorul este chiar fiul drept al nodului ters sau un descendent stng al acestuia