Sunteți pe pagina 1din 117

Introducere

Cursul de Structuri de date este un curs fundamental pentru cei care vor să facă din
informatică o profesie.Orice program foloseşte o sructură de date mai complicată sau mai
smplă, implicită sau explicită. De utilizarea unei structuri optime depinde viteza de execuţie a
programului. Putem spune însă că cea mai importantă apicaţie a acestor structuri este în
domeniul bazelor de date. Istoria Bazelor de date este, de fapt, istoria structurilor folsite
pentru a modela baza de date. Putem spune că de la structra de date se porneşte în
elaborarea unui program şi în proiectarea unei baze de date.

Obiectivele cursului
 Cursul de Structuri de date are ca obiectiv principal formarea de
cunoştinţe corecte despre cele mai utilizate structuri de date şi de priceperi
în utilizarea acestora. Totodată facem o introducere utilă în structura
relaţiomală, cea mai folosită structură în bazele de date.

Competenţe conferite
la sfârşitul acestui curs, studenţii vor fi capabili să:
 Utilizeze structuri elementare ca stivă, coadă, arbore binar
 Să foloseacă diverşi arbori bionari de căutare cum ar fi roşu-negri, AVL,
splay
 cunoască modul de indexare a bazelor de date prin arbori B+ sau prin
tabele de repartizare
 poată mânui algebra relaţionlă

Resurse şi mijloace de lucru


Rezolvarea problemelor necesită compillator pentru limbajul folosit pentru
elaborarea programelor: Pascal, C++, Jawa etc.

Structura cursului

Cursul de structuri de date este structutat în 10 unităţi de învăţare. Fiecare unitate


de învăţare cuprinde: obiective, aspecte teoretice privind tematica unităţii de
învăţare respective, exemple, teste de autoevaluare precum şi probleme propuse
spre discuţie şi rezolvare.

1
Cerinţe preliminare
Discipline necesare a fi parcurse şi eventual promovate înaintea disciplineisunt
algoritmica şi un limbaj de programare procedural.

Discipline deservite
Discipline deservite sunt Baze de date, programare procedurală, limbajul Jawa.

Durata medie de studiu individual


Parcurgerea de către studenţi a unităţilor de învăţare ale cursului de
Marketing (atât aspectele teoretice cât şi rezolvarea testelor de autoevaluare şi
rezolvarea problemelor propuse) se poate face în 2-3 ore pentru fiecare unitate.

Evaluarea
La sfârşitul semestrului, fiecare student va primi o notă, care va cuprinde: nota la
examenul scris ce va conţine întrebări teoretice din materia prezentată în cadrul
acestui material, ce va deţine o pondere de 60% în nota finală, urmând ca 40% să
constitue nota la laborator obşinută pe baza problemelor rezolvate ţi a programelor
elaborate.

Cuprins
UI.1 Structuri liniare
UI.2 Arbori binari
UI.3 Arbori Roşu-negri, Splay, AVL
UI.4 Îmbogăţirea structurilor de date
UI.5 Arbori balansaţi B+
UI.6 Heap-uri binare
UI.7 Heap-uri binomiale
UI.8 Structura datelor pe disc magnetic
UI.9 Structura relaţională
UI.10 Algebra relaţională

Introducere
Am folosit, până acum, structuri foarte simple de date cum ar fi:
 variabile simple (dintre care unele aveau domeniul de valori
formate doar din două valori).
 vectori cu componentele sortate sau nesortate (aşa cum sunt

2
folosiţi în matematică).
 matrici considerate ca vectori de vectori sau ca masive
biortogonale.
Agner Krarup Erlang, inginer danez, care a lucrat la o compania de
telefoane din Copenhaga a publicat în 1909 prima lucrare privind teoria aşteptării
în care sunt enunţate disciplinele FIFO, LIFO, care mai târziu au stat la baza
structurilor de date coadă şi stivă. Erlang este unitatea de măsură pentru volumul
traficului din telecomunicaţii. Stiva utilizată în arhitectura calculatorului a fost
patentată în 1957 de Friedrich L. Bauer un pionier în ştiinţa calculatoarelor, de
origine germană.

Chestionar evaluare prerechizite


Se dau n, ((A(i, j), j=1, n), i=1, n) (A este o matrice pătratică, cu n linii şi n
coloane). Matricea se numeşte subdiagonală dacă elementele aflate deasupra
diagonalei principale sunt egale cu zero. Adică A(i, j)=0 pentru j>i.
a) Să se transforme partea utilă a matricii (elementele eventual diferite de zero)
într-un vector. Se cere formula prin care A(i,j) intră în AV(k), adică k=f(i,j).
b) Să se demonstreze că suma, produsul cu un scalar şi produsul a două matrici
subdiagonale, sunt tot matrici subdiagonale.
c) Să se scrie algoritmul care:
 citeşte două matrici subdiagonale A şi B,
 transformă matricile în vectori VA şi VB,
 face produsul matricilor iniţiale folosindu-se numai de vectorii VA şi VB
 transformă produsul, aflat în vector, în matrice subdiagonală,
 scrie rezultatul

Unitatea de învăţare 1 Structuri liniare.

1.1 Introducere
O structură liniară este o mulţime de n 0 componente x(1), x(2), …, x(n) cu
Proprietăţile:

3
a) Când n = 0 spunem ca structura este vidă.
b) Daca n > 0 atunci x(1) este primul element iar x(n) este ultimul element.
c) Oricare ar fi x(k) unde k_{2,…,n-1} există un predecesor x(k-1) si un succesor
x(k+1).
Ne va interesa să executăm cu aceste structuri urmatoarele operaţii:
adăugarea unui element;
extragerea unui element;
accesarea unui element x(k) din structură;
combinarea a două sau mai multe structuri într-una singură;
“ruperea“ unei structuri în mai multe structuri;
sortarea elementelor unei structuri;
căutarea unui element al structurii care are anumite proprietăţi etc.

1.2 Competenţe
La sfârşitul acestei unităţi de învăţare studenţii vor fi capabili să:
 utilizeze, în algoritmi, structurile de stivă şi coadă

Durata medie de studiu individual


Parcurgerea de către studenţi a acestei unităţide învîţare se face în 3 ore.

1.3 Stiva.
Una din cele mai folosite structuri liniare este stiva.O stivă este caracterizată de
disciplina de intrare şi ieşire din stivă.
Să considerăm o mulţime de cărţi puse una peste alta; există o primă carte care se
poate lua foarte şor (TOP) şi o carte care se poate lua numai dacă deplasez toate celelalte
cărţi (BOTTOM).
Disciplina unei stive este “ ultimul intrat - primul ieşit “ (disciplină care nu v-ar place
să fie respectată când staţi la rând la lapte ! ) ( Last in, first out - prescurtarea acestei reguli
este LIFO).
Care ar fi diferenţele fată de un vector :
-un vector are o lungime fixă, non zero cunoscută aprioric
-o stivă poate fi vidă
-stiva are un numar variabil de elemente în timpul execuţiei unui algoritm
Exemplu
Scaunele puse unul peste altul, la circ, pe care se urcă un acrobsat.

Daţi alte exemple de stivă.

Se pune problema reprezentării concrete a unei stive în memoria unui calculator.


Putem aloca o stivă în două moduri :
I ) Secvenţial

4
II ) Înlănţuit
I ) Alocarea secvenţială a stivei.
Folosim vectorul ca fiind structura cea mai apropiată de structura reală a memoriei. În
vectorul (x (i) ), i=1,n

| x(1) | x(2) | x(3) | … | x(k) | … | x(n) |


↑ ↑
Bottom Top
-din n componente ale unui vector doar ‘k’ elemente fac parte din stivă.
Algoritmul de intrare în stivă va fi :

a STIVA
Daca k = n atunci DEPASIRE
altfel
k=k+1
x(k) = a
Sdaca
Return

Algoritmul de ieşire din stivă va fi :


aSTIVA
Daca k = 0 atunci STIVA VIDA
altfel
a = x( k )
- k=k–1
Sdaca
Return

II ) Alocarea înlănţuită a stivei


În alocarea înlănţuită fiecare element al structurii este însoţit de adresa la care se afla
precedentul element. Vom avea vârful pus în evidenţă (ancorat) în INC şi un semn special
“NIL” în loc de adresa bazei ca în figura următoare :
| INFO | LEG |

INC | || x(k) | ||x(k-1) | |…|x(2) | ||x(1) | NIL |

(Ordinea 1,2,…,k este ordinea intrării în stivă).


În acest caz intrarea în stivă va folosi stiva de locuri libere (această stivă se numeşte
LIBERE) pentru a obţine locuri la introducerea în stivă.
Vom prezenta în continuare algoritmii de intrare-ieşire dintr-o stivă în cazul în care
alocarea ei a fost înlănţuită :
Algoritmul de intrare in stiva va fi :

a STIVA
yLIBERE
INFO(y) = a ; LEG(y)=INC ; INC = y
Return

Algoritmul de ieşire din stivă va fi :

5
aSTIVA
Daca INC= ‘ ’ atunci ‘STIVA VIDA’
Altfel
INCLIBERE
a=INFO(INC)
INC=LEG(INC)
Sdaca
Return
Să presupunem acum că vrem să scoatem din stiva înlănţuită S elementul cu
informaţia x. Algoritmul va fi următorul:
EXTR(S,x)
y=s
z=LEG(y)
Repeta
Daca z=nil atunci
Scrie (‘nu exista’, x)
Return
Altfel
Daca INFO(z)=x Atunci
z  LIBERE
LEG(y)=LEG(z)
Return
Altfel
y=z; z=LEG(y)
SDaca
SDaca
SCiclu
Definim, în continuare, o structură dublu înlănţuită.
|LEGP| INFO | LEGU |

Aici LEGP este adresa precedentului, iar LEGU este adresa următorului.

INC | || | x(k) | || |x(k-1) | |…| |x(2) | || |x(1) |  |

Să ne reamintim...
Stiva este o structură liniară, dinamică. Adică seamănă cu un vector , dar nu
are componenţă fixă. În ea intră şi ies elemente pe parcursul execuţiei unui algoritm.

1.4 Coada.
O altă structură liniară utilizată în conceperea algoritmilor este coada. O coadă este
caracterizată şi ea de o disciplină de intrare-iesire, bineinţeles diferită de cea a stivei.
Exemplu
De această dată puteţi să vă gândiţi la coada la lapte: primul care s-a aşezat la
coadă va fi primul servit, adică primul care iese din coadă.

6
Daţi alte exemple de coadă.

Disciplina unei cozi este “primul venit, primul plecat” ( “first in, first out “ având
prescurtarea FIFO).
O coadă poate fi vidă şi are şi ea un număr variabil de elemente în timpul execuţiei
unui algoritm.
I ) Alocarea secvenţială a cozii.
Coada alocata secvenţial îşi va găsi locul tot într-un vector (x(i)),i=1,n.
| x(1) | x(2) | … | x(f) | … | x(s) | … | x(n) |
↑ ↑
FAŢĂ SFÂRŞIT

Din cele ‘n’ componente ale vectorului doar componentele x(f) … x(s) fac parte din
coadă.
Algoritmul de intrare în coadă va fi :

a COADA
Daca S = n atunci ‘DEPASIRE’
Altfel
S=S+1
x(S) = a
Sdaca
Return

Algoritmul de ieşire din coadă va fi :

aCOADA
Daca F> S atunci COADA VIDA
Altfel
a=x(F);F=F+1
Sdaca
Return

Se poate observa uşor ca procedând în acest fel (scoţând din faţă şi introducând la sfârşit)
coada “migrează” spre dreapta şi poate să ajungă în situaţia DEPASIRE când de fapt mai
există mult loc gol (în vectorul x) pe primele poziţii.
Imaginaţi-vă cum s-ar putea folosi vectorul mai eficient pentru alocarea unei
cozi.

II ) Alocarea înlănţuită a cozii.


Se face în mod similar cu alocarea înlănţuită a stivei în noduri de tipul:
| INFO | LEG |

| x(F) | || | | … | x(S) | nil |


FAŢĂ SFÂRŞIT

7
Algoritmul de intrare în coadă va fi :

a COADA
yLIBERE
INFO(y) = a ; LEG(SFARSIT)=y
Return

Algoritmul de ieşire din coadă va fi :

aCOADA
Daca FATA= ‘nil’ atunci COADA VIDA
Altfel
a=INFO(FATA)
FATALIBERE
FATA=LEG(FATA)
Sdaca
Return
Să ne reamintim...
Disciplina unei cozi este “primul venit, primul plecat” (FIFO).
O coadă poate fi vidă şi are un număr variabil de elemente în timpul
execuţiei unui algoritm.

.
Rezumat
 Am văzut, aici, cum se utilizează, în algoritmi, structurile liniare de stivă şi coadă.
 Le-am clasificat după modul de alocare în memoria calculatorului şi am dat
aloritmii de intrare, ieşire şi acces la un element la structurii.
 Se poate observa că structura de stivă seste mult mai flexibilă şi de aceea este şi
mult mai des folosită.
1.5 Test de autoevaluare a cunoştinţelor
1.5.1 Având o structură de tip stivă S, cu funcţiile pentru gestionare: Intra(S, x); //
depune în stivă
Iese(S, x, vid); //extrage din stivă. Ce va scrie următorul algoritm?
Stiva1
Intra(S, 0)
Intra(S, 1)
Intra(S, 3)
Intra(S, 2)
Iese(S, x, vid)

8
scrie( x )
Iese(S, x, vid)
scrie( x )
Iese(S, x, vid)
scrie( x )
Return
Alegeţi dintre: a) 012 b) 310 c) 231 d) 013
1.5.2 Ca să arătăm forţa acestei structuri să vedem ce permutări pot ieşi din stivă
dacă la intrare avem 1,2,3? Evident că prin secvenţa:
Intra(S,1)
Iese(S,x,vid)
scrie( x )
Intra(S,1)
Iese(S,x,vid)
scrie( x )
Intra(S,1)
Iese(S,x,vid)
scrie(x)
va ieşi permutarea identică’1,2,3’.
Câte permutări diferite de permutarea identică se pot obţine astfel?
Alegeţi dintre: a) 2 b) 4 c) 0 d) 1
1.5.3 Se dă o stivă şi o valoare x. Să se introducă în stivă după elementul cu INFO =
x un element cu INFO = y.
1.5.4. Pentru reprezentarea unei cozi simplu înlănţuite avem nevoie de:
a) un pointer cap care să indice spre capul cozii
b) un pointer sf care să indice spre sfârşitul cozii
c) doi pointeri cap şi sf care să indice spre capul, respectiv sfârşitul cozii
d) nici una din variantele de mai sus
1.5.5 Se dă o stivă dublu înlănţuită. Să scrie algoritmul pentru scoaterea din stivă a
nodului cu informaţia x.
Răspunsurile se află la sfârsit pag 103.

9
Unitatea de învăţare2. Arbori binari.

2.1 Introducere
O structură neliniară nu mai respectă regula existenţei unui unic predecesor,
respectiv succesor. Dintre structurile neliniare vom studia diferitele tipuri arbori,
insistând pe proprietăţile care sporesc complexitatea utilizării lor ca structuri de
date.

2.2 Competenţe
La sfârşitul acestei unităţi de învăţare studenţii vor şti:
 Ce sunt arborii binari
 Cum se memorează ei
 Cum se parcurg arborii binari

10
 Cum se transformă un arbore oarecare în arbore binar
 Ce este un nomenclator
 Ce sunt arborii binari de căutare
 Ce operaţii se fac cu aceşti arbori

Durata medie de studiu individual


Parcurgerea de către studenţi a acestei unităţide învîţare se face în 3 ore.

2.3 Arborele binar.


Un arbore în care orice vârf (nod) are 0, 1 sau 2 descendenţi se numeşte arbore binar.
Definiţii
O muchie leagă părintele (nod ascendent) de copil (nod descendent sau fiu).
Frunza este un nod care nu are copii.
Rădăcina unui arbore este nodul care nu este descendentul nimănui
Adâncimea unui nod este egală cu lungimea drumului de la rădăcina arborelui la nod.
Mulţimea nodurilor care au aceeaşi adâncime n se numeşte nivelul n al arborelui.
Înălţimea unui arbore este egală cu cea mai mare dintre adâncimile frunzelor arborelui.
Dimensiunea unui arbore este dată de numărul total de noduri.
Două noduri care au acelaşi părinte se numesc fraţi. Ele se disting unul faţă de celălalt
prin enunţarea poziţiei lor faţă de părinte (stânga, dreapta).
Tipuri de arbori binari
Un arbore binar care are vârfuri cu 0 sau 2 descendenţi se numeşte arbore binar strict.
Un arbore binar strict care are toate nivelele pline se numeşte arbore binar complet.
Un arbore binar plin este un arbore în care fiecare nod are doi sau niciun copil.
Un arbore binar aproape complet este un arbore în care orice nod care are copil drept are
şi copil stâng. (se foloseşte şi definiţia complementară dacă are copil stâng trebuie să aibă
neapărat şi drept).
Un arbore binar este echilibrat dacă diferenţa dintre adâncimea frunzelor este mai mică
sau egală cu 1.

Proprietăţi
Numărul de noduri n pentru un arbore binar cu înălţimea h
h  1  n  2 h 1  1
Înălţimea h pentru un arbore binar cu n noduri
 log 2  n  1  1  h  n  1

11
Numărul de arbori binari distincţi cu n noduri
 2n !
 n  1! n!
Numărul de arbori binari distincţi de înălţime h
 
 h   h21   h 1 1  4 h 1  3 , unde  0  1

Demonstraţi formulele de mai sus

Utilizări ale arborilor binari

Un arbore binar strict se poate folosi, de exemplu, la reprezentarea în memorie a unei expresii
aritmetice. Frunzele acestui arbore conţin operanzii, iar celelalte noduri conţin operatorii.
Deoarece nu toate operaţiile sunt comutative, este foarte important dacă un nod este
descendent pe stânga sau pe dreapta. În exemplul următor este reprezentată expresia
 7  3  2  243
2

Exemplu 2.1

Arbore binar asociat unei expresii, unde * este operaţia de înmulţire, ^ este
operaţia de ridicare la putere, iar / împărţirea
Desenaţi arborele binar asociat expresiei :
(x-1)*(a+b)^3
Alocarea unui arbore binar se poate face:

12
- secvenţial
- înlănţuit
- mixt
Alocarea secvenţială a unui arbore binar
În vectorul (x(i), i=1, n) vom avea următoarele reguli:
- rădăcina este în x(1);
- pentru fiecare nod x(i), descendentul său din stânga este x(2·i) iar cel din dreapta este x(2·i +
1);
- dacă nu există descendent, se pune * sau NIL.

Exemplu 2.2
| - | * | / |+ | c | 2 | 1 | a | b |nil|nil|nil|nil| c | 3.5 |nil|…|nil|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 31
Reprezemtarea secvenţială a arborelui din exemplul 2.1.

Alocarea înlănţuită a unui arbore binar

În acest caz se folosesc noduri de forma , unde LS şi LD conţin adresele de


memorie ale nodurilor descendent stâng, respectiv descendent drept.

Exemplu 2.3

Exemplu de alocare înlănţuită.

Desenaţi arborele binar care are alocarea înlănţuită de mai sus.

13
Alocarea mixtă a unui arbore binar
La acest tip de alocare se folosesc trei vectori INFO, LS, LD unde LS(i) şi LD(i) conţin
indicii unde se află memoraţi descendentul stâng, respectiv descendentul drept pentru nodului
i.

Exemplu 2.4

INFO LS LD

1 - 2 3

2 * 4 5

3 / 6 7

4 + 8 9

5 c nil nil

6 2 nil nil

7 ^ 10 11

8 a nil nil

9 b nil nil

10 c nil nil

11 3 nil nil

Exemplu de alocare mixtă pentru arborele binar din exemplul 2.1.

Desenaţi alocarea mixtă pentru arborele binar din exemplul 2.3.

Parcurgerile arborilor binari


Arborele binar se defineşte recursiv ca: rădăcină, subarbore stâng, subarbore drept (fiecare
subarbore este la rândul lui un arbore binar, posibil vid);
După poziţia rădăcinii (R) relativ la subarborele stâng (S) şi subarborele drept (D), avem
următoarele trei tipuri de parcurgeri ale unui arbore binar:

14
1. postordine (SRD);
2. preordine (RSD)
3. inordine (SRD)

Exemplu 2.5
Exemplu de parcurgere în preordine pentru arborele binar din exemplul 2.1.
- * + 7 3 2 / 24 ^ 2 3

această scriere se numeşte scriere poloneză prefixată a unei expresii aritmetice. A


fost inventată în 1920 de polonezul Jan Łukasiewicz.
Screţi parcurgerea în preordine pentru arborele binar din exemplul 2.3.

Exemplu 2.6
Exemplu de parcurgere în inordine pentru arborele binar din exemplul 2.1.
7 + 3 * 2 - 24 / 2 ^ 3
care se mai numeşte şi proiecţia arborelui, pentru că dacă am “tăia” legăturile
dintre noduri “gravitaţia” ar atrage către pământ nodurile exact în inordine.

Proiecţia unui arbore binar


Screţi parcurgerea în inordine pentru arborele binar din exemplul 2.3.

Exemplu 2.7
Exemplu de parcurgere în postordine pentru arborele binar din exemplul 2.1.
7 3 + 2 * 24 2 3 ^ / -
această scriere se numeşte scriere poloneză postfixată a unei expresii aritmetice.
Inventată în 1950 şi publicată în 1957 de australianul Charles Hamblin

15
Screţi parcurgerea în postordine pentru arborele binar din exemplul 2.3.

Să ne reamintim...
Există trei moduri specifice de parcurgere a arborilor binari. Referindu-ne
la definiţia recursivă a arborilor binari, prcurgerea în preordine este RSD,
prcurgerea în inordine este SRD, iar prcurgerea în postordine este SDR.

2.4 Arbori n-ari


Pentru reprezentarea structurii unui produs format din ansambluri, subansambluri şi aşa
mai departe până la piese simple nu se poate utiliza un arbore binar. Această structură dă
naştere unui arbore oarecare n-ar, care poate fi transformat în arbore binar în felul următor:
pentru fiecare nod al arborelui n-ar, descendentul din stânga rămâne descendentul stâng şi în
arborele binar asociat, toţi ceilalţi descendenţi din arborele n-ar vor deveni descendenţii
dreapta unul pentru celălalt în arborele binar. Intuitiv această transformare înseamnă păstrarea
legăturii dintre părinţi şi primul descendent al acestora din arborele n-ar, ştergerea legăturilor
dintre părinţi şi ceilalţi descendenţi şi refacerea legăturilor şterse la nivelul fraţilor
“dezmoşteniţi”. În final trebuie aranjate nodurile pentru a se vedea clar orientarea lor stânga,
respectiv dreapta.

Exemplu 2.8
Exemplu de arbore n-ar şi transformarea lui în arbore binar

Daţi un exemplu de arbore n-ar şi transformaţi-l în arbore binar

2.5. Arbori binari de căutare

Arborii binari de căutare sunt structuri de date care suportă multe operaţii cum ar fi:
SEARCH (căutare), MINIMUM, MAXIMUM, PREDECESOR, SUCCESOR, INSERT

16
(introducere) şi DELETE (ştergere). Un arbore de căutare poate fi folosit atât ca dicţionar cât
şi ca o coadă de priorităţi. Operaţiile de bază pe un arbore binar de căutare au complexitatea
proporţională cu înălţimea arborelui. Pentru un arbore binar complet aceste operaţii se execută
în cel mai rău caz în O(lgn). Dacă arborele este o înlănţuire liniară de n noduri atunci aceleaşi
operaţii se vor face în cel mai rău caz în O(n).
În practică nu putem garanta întotdeauna randomizarea construirii arborilor de căutare, dar
sunt anumiţi arbori de căutare (arborii roşu-negri, arborii AVL, arborii SPLAY, arborii
balansaţi) ale căror performanţe sunt bune pentru operaţiile de bază, chiar şi în cel mai rău
caz.
Un arbore binar de căutare are următoarele proprietăţi:
 Fiecare nod are o valoare, numită cheie
 Este definită o regulă de ordonare a acestor valori:
o Nodurile din subarborele stâng au valori strict mai mici decât părintele
o Nodurile din subarborele drept au valori mai mari sau egale decât părintele

Proprietăţile arborelui binar de căutare ne permite să extragem toate cheile sortate


crescător cu ajutorul unui algoritm recursiv pentru parcurgerea în inordine.

Exemplu 2.9
Exemplu de arbore binar de căutare.

Daţi un exemplu de arbore binar de căutare.

Tipuri de arbori binari de căutare:


 G.M. Adelson-Velsky şi E.M. Landis - Arbori AVL
 Daniel Sleator şi Robert Tarjan - Arbori splay şi Arbori link/cut
 Igal Galperin şi Ronald L. Rivest. Arbori scapegoat
 Leo J. Guibas şi Robert Sedgewick - Arbori Roşu-Negru
 Aragon şi Seidel - Arbori Treap

17
Să ne reamintim...
Un arbore binar de căutare poate fi reprezentat de o structură de date
înlănţuită în care fiecare nod este un obiect. Într-un nod x avem |KEY | ADR | LS |
LD | P | KEY(x) însemnă valoarea cheii din nodul x, informaţia de lângă KEY se
mai numeşte şi informaţie satelit (SAT), legătura la copilul din stânga, legătura la
copilul din dreapta, şi părintele nodului x. Dacă un copil sau un părinte lipsesc,
câmpul corespunzator va conţine NIL. Un arbore binar de căutare este un arbore
binar care satisface condiţia:
a) Pentru orice nod y care se află într-un subarbore stâng al nodului x
KEY(y) ≤ KEY(x)
b) Pentru orice nod y care se află într-un subarbore drept al nodului x
KEY(x) ≤ KEY(y)

Operaţii asupra unui arbore binar de căutare

Cea mai comună operaţie efectuată asupra unui arbore binar de căutare este căutarea unei
chei memorată în arbore căreia îi vom spune căutare binară. Această structură mai suportă
şi interogări de tipul ”care este Minimul, Maximul, Succesorul, Predecesorul?”. În
continuare vom examina aceste operaţii şi vom vedea că fiecare acţiune se poate face într-un
timp proporţional cu înălţimea arborelui, deci (h).
Exemplu 2.10
Exemplu de căuttare într-un arbore binar de căutare.

Drumul pentru găsirea cheii 13.


Căutarea cheii 13 trebuie făcută pe partea stângă a rădăcinii 15, unde găsim
cheia 6, deci căutarea trebuie continuată pe partea dreaptă, unde găsim cheia 7,
vom continua căutarea pe partea dreaptă şi găsim cheia 13. Calea acestei căutări
este: 15 − 6 − 7 − 13.

18
Evidenţiaţi drumul pentru găsirea cheii 4..

Vom folosi următorul algoritm pentru a căuta într-un arbore binar de căutare un nod cu
cheie dată:
CAUTBIN(Rad, k,Rez)
x = Rad
Cât timp x ≠ NIL şi k ≠ KEY (x)
Dacă k < KEY (x) atunci
x = LS(x)
altfel
x = LD(x)
Sfârşit dacă
Sfârşit cât timp
Dacă x = NIL atunci
Rez = NIL
altfel
Rez = ADR(x)
Sfârşit dacă
Return
Un element al unui arbore binar de căutare, a cărui cheie este minimă, poate fi găsit
urmărind pointerele descendenţilor din partea stângă începând de la rădăcină până când este
întâlnită o adresă = Nil. Următorul algoritm determină nodul de cheie minimă a unui arbore
cu rădăcina Rad:
MINBIN(Rad,Min)
x = Rad
Cât timp x ≠ NIL
x = LS(x)
Sfârşit cât timp
Min = KEY (x)
Return
Scrieţi algoritmul care determină nodul de cheie maximă a unui arbore cu
rădăcina Rad:

19
Fiind dat un nod într-un arbore binar de căutare, câteodată este important să-i găsim
succesorul în şirul sortat al cheilor obţinut prin parcurgerea în inordine. Dacă toate cheile sunt
distincte, succesorul unui nod x este nodul cu cea mai mică cheie, mai mare decât KEY(x).
Structura arborilor binari de căutare ne permite să determinăm succesorul unui nod fără a
compara vreodată cheile. Următorul algoritm determină succesorul nodului x, dacă acesta
există, şi returnează Nil dacă x este cea mai mare cheie din arbore:
SUCCBIN(x, y)
Dacă LD(x) ≠ NIL atunci
Cheamă MINBIN (LD(x),y)
Return
Sfârşit dacă
y = P(x)
Cât timp y ≠ Nil şi x = LD(y)
x=y
y = P(y)
Sfârşit cât timp
Return
Să ne reamintim...
Algoritmul pentru succesor conţine două cazuri:
 Dacă sub arborele drept al nodului x nu este gol, atunci succesorul lui x este cel
mai din stânga nod al subarborelui drept, pe care îl găsim chemând MINBIN.
 Dacă subarborele drept al nodului x este gol şi x are un succesor y, atunci y este
cel mai mic strămoş al lui x şi descendentul stâng al lui y este de asemenea un
strămoş al lui x.
Operaţiile de inserare şi ştergere aplicate unei mulţimi dinamice reprezentate de un arbore
binar de căutare cauzează schimbări în arbore. Structura de date trebuie modificată ca să
reflecte aceste schimbări, dar proprietăţile arborelui binar de căutare trebuie să fie în
continuare păstrate. Modificarea arborelui pentru inserarea unui element este relativ directă, în
schimb la ştergere, este ceva mai complicat.

Inserarea
Pentru inserarea unei noi valori într-un arbore binar de căutare T vom folosi algoritmul
INSBIN. Această procedură este exemplificată în figura de mai jos, unde nodurile albe
marchează calea de la rădăcina până la poziţia în care se face inserarea. Linia punctată indică

20
legătura în arbore care este adăugată pentru inserarea elementului. (cheia elementului care se
inserează este 13). La început z- locul pentru noua cheie, iese din Libere-stiva de locuri libere.

Exemplu 2.11

Exemplu de inserare acheii 13.


Arătaţi cum se inserează cheia 7.

INSBIN(x, y)
y = NIL
x = Rad
z ⇐ Libere
LS(z) = NIL şi LD(z) = NIL
Cât timp x ≠ NIL
y=x
Dacă KEY (z) < KEY (x) atunci
x = LS(x)
altfel
x = LD(x)
Sfârşit dacă
Sfârşit cât timp
P(z) = y
Dacă y = NIL atunci {adică dacă arborele este vid}
RAD(T) = z
altfel
Dacă KEY (z) < KEY (y) atunci
LS(z) = z
altfel
LD(z) = z

21
Sfârşit dacă
Sfârşit dacă
Return

Ştergerea
Algoritmul pentru ştergerea unui nod dat z dintr-un arbore binar de căutare are ca
argument un pointer către z. Procedura consideră trei cazuri ilustrate în exemplul 2.
a) Dacă z nu are nici un descendent modificăm cheia lui z înlocuind-o cu Nil.
b) Dacă z are un singur descendent îl eliminăm pe z făcând o nouă legătură între descendentul
si părintele lui z.
c) Dacă z are doi copii îl eliminăm pe z prin înlocuirea conţinutului său cu cel al succesorului
său care nu are descendent stâng.

Exemplu 2.12

Arătaţi cum se sterge cheia 4.

Exemplu 2.13

22
Arătaţi cum se sterge cheia 13.

Mai jos este dat algoritmul pentru ştergerea unui nod dintr-un arbore binar de căutare.

ELIMINBIN(T, z)
Dacă LS(y) ≠ NIL atunci
x = LS(y)
altfel
x = LD(y)
Sfârşit dacă
Dacă x ≠ NIL atunci
P(x) = P(y)
Sfârşit dacă
Dacă P(y) = NIL atunci
RAD = x
altfel
Dacă y = LS(P(y)) atunci
LS(P(y)) = x
altfel
LS(P(y)) = x
Sfârşit dacă
Sfârşit dacă
Dacă KEY (z) < KEY (y) atunci
KEY (z) = KEY (y)
ADR(z) = ADR(y)
Sfârşit dacă
Return

Rotaţia

Înţelegem prin rotaţie o simplă transformare a arborelui ca în figura de mai jos:

23
Rotaţia la dreapta în jurul unui nod presupune că nodul dat are copil stâng, iar rotaţia la stânga
în jurul unui nod presupune că are copil drept.

Proprietăţile rotaţiei

Rotaţia schimbă structura unui arbore binar, în general rotaţia depinde de forma arborelui
şi poate fi folosită pentru a modifica înălţimea arborelui.
Rotaţia schimbă structura locală a unui arbore binar, dar numai la nivelul nodurilor în
jurul căreia se efectuează rotaţia şi a copiilor acestora, părintele şi nepoţii acestora rămânând
neschimbaţi.
Rotaţia nu schimbă ordinea dintr-un arbore binar, aşa că rotaţia păstrează proprietatea din
definiţia arborilor binari de căutare.

Exemplu 2.14

În exemplu se poate vedea evoluţia unui arbore binar în care s-a efectuat o
rotaţie spre dreapta după nodul 15. Trebuie să observaţi că după rotaţie nodurile
implicate în rotaţie îşi păstrează legăturile (nodul stâng – LS, nodul drept LD,
dacă ele există), dar LD a nodului stâng (dacă există) migrează ca LS al celuilalt
nod implicat în rotaţie. (În acest mod se respectă proprietatea arborelui binar de
căutare.)

Efectuaţi în arborele din exemplul de mai sus o rotaţie dreapta şi apoi stânga după
nodul cu cheia 6.

24
Să ne reamintim...
O rotaţie este o operaţie locală într-un arbore de căutare care conservă
disciplina cheilor, adică proprietatea de arbore binar de căutare.

2.7 Rezumat
Un arbore în care orice vârf are zero, unul sau doi descendenţi se
numeşte arbore binar. Un arbore binar care are numai vârfuri cu nici
un descendent sau cu doi descendenţi se numeşte arbore strict binar.
Alocarea unui arbore binar se poate face: secvenţial, înlănţuit sau mixt.
Am dat algoritmii de parcurgere în preordine, inordine şi postordine
recursivi şi iterativi.
Am dat apoi o metodă de a construi un arbore asociat unui arbore oarecare
care, de această dată, este binar. Transformarea se face în felul următor : pentru
fiecare nod descendentul din dreapta este fratele următor (elementul următor aflat
la acelaş nivel de descompunere).
Un arbore binar de căutare este un arbore binar care satisface condiţia:
a) Pentru orice nod y care se află într-un subarbore stâng al nodului x
KEY(y) ≤ KEY(x)
b) Pentru orice nod y care se află într-un subarbore drept al nodului x
KEY(x) ≤ KEY(y)
Cea mai comună operaţie efectuată asupra unui arbore binar de căutare
este căutarea unei chei memorată în arbore careia îi vom spune căutare binară.
Aceasta structură mai suportă şi alte opraţii de tipul Minimum-ul, Maximum-ul,
Succesor-ul, Predecesor-ul, Inserare şi Stergere. Pentru toate aceste operaţii am
dat algoritmii corespunzători.

2.7 Test de autoevaluare a cunoştinţelor


2.7.1 Scrieţi algoritmul pentru determinarea predecesorului (este simetric cu cel
pentru determinarea succesorului)
2.7.2 Scrieţi algoritmul de căutare binară recursiv.
2.7.3 Fiind dat şirul 36, 15, 45, 38, 39, 12, 16 să se construiască prin inserări
succesive un arbore binar de căutare.
2.7.4 Efectuaţi independent operaţiile de mai jos pe arborele construit mai sus:
a) ştergeţi nodul 45 folosind predecesorul
b). ştergeţi rădăcina arborelui folosind predecesorul
c) ştergeţi succesiv cheile 36, 15, 39 folosind predecesorul
d) ştergeţi succesiv cheile 36, 15, 39 folosind succesorul.
2.7.5 Executaţi rotaţiile posibile în jurul nodului 4 pentru fiecare dintre arborii de
mai jos.

25
Rezultatele le găsiţi la sfârşit, la pag 103.

Unitatea de învăţare 3 Arbori roşu-negri, AVL şi Splay.

26
3.1 Introducere
Am văzut că arborii binari de căutare pot fi foarte folositori dar complexitatea
algoritmilor este proporţională cu înălţimea arborelui. Numai în cazuri speciale
putem impune ca această înălţime să fie minimă, adică proporţională cu
log(numărul de noduri). Vedem în continuare astfel de cazuri.

3.2 Competenţe
La sfârşitul acestei unităţi de învăţare studenţii vor fi capabili să:
Folosiţi în algoritmi arbori binari de căutare optimizaţi ca înălţime
 Roşu-negri
 AVL
 Splay

Durata medie de studiu individual


Parcurgerea de către studenţi a acestei unităţide învăţare se face în 3 ore.

3.3 Arbori Roşu-negri.

Au fost inventaţi de LJ. Guibas şi R. Sedgewick în 1978.


Am arătat, în unitatea de învăţare precedentă,că operaţiile de căutare, predecesor,
succesor, minimum, maximum, inserarea, şi ştergerea pentru un arbore binar de căutare cu
înălţimea h se fac în O(h). Deci aceste operaţii se execută rapid dacă înălţimea este mică; dar,
dacă înălţimea este mare, performanţele lor nu pot fi mai bune decât ale unei liste înlănţuite.
Arborii roşu-negri sunt una din schemele de arbori de căutare care sunt „aproape echilibraţi”
cu scopul de a garanta că operaţiile dinamice au complexitatea O(lg(n)).
În general echilibrarea acestor arbori se face prin operaţia de rotaţie care a fost descrisă în
capitolul anterior.

Proprietăţile arborilor roşu-negri.

Un ARN este un arbore binar de căutare în care fiecărui nod i se atribuie un atribut numit
culoare care poate lua valorile roşu sau negru şi este înzestrat cu următoarele proprietăţi:

1. Orice nod este roşu sau negru şi vom nota cul(x)=R dacă nodul este roşu sau cul(x)=N
dacă nodul este negru

27
2. Rădăcina este neagră
3. Toate frunzele sunt negre (de obicei ele sunt nil)
4. Ambii copii ai unui nod roşu sunt negri
5. Părintele unui nod roşu este negru
6. Toate drumurile de la rădăcină la o frunză conţin acelaşi număr de noduri negre (nu se
iau în considerare nodurile nil). Acest număr îl vom numi înălţime neagră şi se
notează cu hn

Exemplu

Un exemplu de arbore roşu-negru

Daţi şi voi un exemplu de arbore roşu-negru.

1
Relaţia dintre înălţimea neagră şi înălţimea arborelui roşu negru este hn  h . Ştim că
2
1
 log 2 (n  1)  1  h , iar n2 h 1
1  2 hn
1  2 2
h
 1 de unde rezultă că
1 1
h h 1
n2 2
1  n 1  2 2
 log 2 (n  1)  h , aşadar h   2 log 2 (n  1) , deci
2

 log 2 (n  1)  1  h ARN   2 log 2 (n  1)

Un arbore roşu-negru cu n noduri interne are înălţimea cel mult 2 log(n + 1). Operaţiile
dinamice căutare, minimum, maximum, succesor, predecesor pot fi implementate pentru
arborii roşu-negri în O(lg(n)).

Operaţiile de inserare şi ştergere aplicate unui arbore roşu-negru cu n chei modifică


arborele, ceea ce ar putea duce la distrugerea proprietăţilor pe care trebuie să le aibă un arbore

28
roşu-negru. Pentru a restaura aceste proprietăţi va trebui sa schimbăm culoarea anumitor
noduri şi, de asemenea, să schimbăm structura pointerilor printr-o rotaţie, care este o operaţie
locală într-un arbore de căutare care conservă disciplina cheilor şi are o complexitatea O(1).

Inserarea
Există două situaţii de bază în care ne vom afla când inserăm un nod într-un arbore roşu-
negru:
I. Părintele nodului de inserat este negru situaţie pe care o vom numi NR şi care se rezolvă la
fel ca la arborele binar de căutare.
II. Părintele nodului de inserat este roşu situaţie pe care o vom numi RR şi care se rezolvă mai
complicat pentru că încalcă proprietatea 4, iar dacă am încerca rezolvarea problemei prin
recolorarea nodului inserat în negru am încălca proprietatea 6.
1) dacă unchiul este roşu atunci nodul inserat nu va încălca proprietatea 6 pentru că nodurile
roşii nu contează la înălţimea neagră a ARN (arbore roşu-negru), în această situaţie, pe care o
vom numi S-RRr, vom recolora părintele şi unchiul şi bunicul nodului de inserat procedură
care va mări cu o unitate înălţimea neagră dar poate produce alte încălcări ale proprietăţilor
ARN.
2) dacă unchiul este negru atunci rezolvarea încălcărilor se face după locul nodului inserat
faţă de viitorul său părinte, respectiv bunic. Astfel:
A). dacă nodul inserat este pe partea stângă a părintelui, respectiv a bunicului (partea
dreaptă a părintelui, respectiv a bunicului), situaţie pe care o vom numi Ss-RRn (Dd-
RRn)atunci se va face o rotaţie: la dreapta (stânga) după bunic recolorarea P, U, B.
Să ne reamintim...

Cazurile de inserare într-un ARN


Poziţie-
Mod de soluţionare
Cul(P(x))-Cul(x)-Cul(U(x))
*-NR* La fel ca într-un ABC
* RRr Recolorare P(x), U(x), B(x)
Ss-RRn RotD(B(x))+recolorare x şi B(x) +
sau eventual rezolvarea unei noi încălcări dar
Dd-RRn cu un nivel mai sus
Sd-RRn RotD(P(x)) / RotS(P(x)) pentru a ajunge
sau în situaţia Dd-RRn, respectiv Ss-RRn
Ds-RRn

29
B) dacă nodul inserat este pe partea stângă a părintelui dar pe dreapta bunicului sau
invers, situaţii numite Sd-RRn sau Ds-RRn se face o rotaţie astfel încât să ajungem în situaţia
descrisă la A).
Observaţie
În afara situaţiei *-NR* rezolvarea unei încălcări conform regulilor RRr, Ss-RRn, ş.a.m.d.
poate să urce problema mai sus, în loc să o rezolve definitiv.

Ştergerea
Ştergerea unui nod dintr-un arbore roşu-negru este un pic mai complicată decât operaţia
de inserare. Cazurile de ştergere sunt grupate după aceleaşi reguli ca la ABC:
1) Cazul în care nodul de şters are copii doar frunze nil
a) dacă nodul are culoarea roşie este o ştergere banală
b) dacă nodul are culoarea neagră se recolorează părintele şi subarborele drept al fratelui, iar
dacă fratele nu are doar descendenţi nil, atunci se efectuează rotaţii după părinte, dacă nodul
se află pe stânga, respectiv după frate dacă nodul este pe dreapta, altfel nu se fac rotaţii.
2) Cazul în care nodul are un singur copil diferit de nil, el va avea culoarea contrară părintelui
- el va lua locul părintelui şters şi culoarea negru.
3) Cazul în care nodul care trebuie şters are doi copii se înlocuieşte cu predecesorul sau
succesorul său şi se reia procedura de ştergere pentru noua situaţie care va fi de tipul 1)
Algoritmul pentru rotaţie_stânga.

Rotaţie_stânga(T ,x)
y=LD(x)
LD(x)=LS(y)
Dacă LS(y) Nil atunci
P(LS(y))=x
Sfârşit dacă
P(y)=P(x)
Dacă P(x)=Nil atunci
Rad(T)=y
altfel
Dacă x = LS(P(x)) atunci
LS(P(x))=y
altfel

30
LD(P(x))=y
Sfârşit dacă
LS(y)=x
P(x)=y
Return

Scrieţi algoritmul pentru rotaţie dreapta.

Să ne reamintim...

Un ARN este un arbore binar de căutare în care fiecărui nod i se atribuie un atribut
numit culoare care poate lua valorile roşu sau negru şi este înzestrat cu proprietăţile:

1. Orice nod este roşu sau negru


2. Rădăcina este neagră
3. Toate frunzele sunt negre
4. Ambii copii ai unui nod roşu sunt negri
5. Părintele unui nod roşu este negru
6. Toate drumurile de la rădăcină la o frunză conţin acelaşi număr de noduri
negre. Înălţimea neagră se notează cu hn

3.4. Arbori AVL.


Au fost inventaţi de G.M. Adelson-Velsky şi E.M. Landis. Am arătat în capitolul 3 că
operaţiile de căutare, predecesor, succesor, minimum, maximum, inserarea, şi ştergerea într-
un arbore binar de căutare cu înălţimea h se fac în O(h). Înseamnă că aceste operaţii se
execută rapid dacă înălţimea este mică. Arborii AVL sunt încă una din schemele de arbori de
căutare care sunt ”aproape echilibraţi” cu scopul de a garanta ca operaţiile dinamice să aibă
complexitatea O(lg(n)).

31
Pentru a putea defini arborii AVL trebuie să ştim ce este factorul de balansare.
Definiţii:
Factorul de balansare (FB) a unui nod x reprezintă diferenţa dintre înălţimea subarborelui
drept şi cea a subarborelui stâng.
Un nod care are factorul de balansare -1, 0 sau 1 se numeşte balansat.
Arborele AVL este un arbore binar de căutare care are proprietatea că oricare nod al său
este balansat.
În funcţie de factorul de balansare a rădăcinii unui arbore AVL putem defini trei tipuri de
arbori
LH când FB(rad) = -1
RH când FB(rad) = +1
EH când FB(rad) = 0
S-a demonstrat că înălţimea unui AVL care are n noduri este cuprinsă între valorile:
log2(n+1)-1 ≤ h ≤ 1,4405log2(n+2)-0,3277

Exemplu

Daţi şi voi un exemplu de arbore AVL cu factorul de balansare.

Factorul de balansare se poate strica doar în cazul inserării sau ştergerii.


Observaţie. Trebuie să reţinem că factorul de balansare al subarborelui este calculat după
inserare iar al arborelui înainte de inserare.

Inserarea
Cazul I.
a) EH – Orice

32
Dacă subarborele în care se face inserarea este EH atunci este clar că tipul arborelui nu va
încălca în niciuna din situaţii regula AVL.
b) Orice - EH
Dacă arborele AVL este de tipul EH inserarea poate strica factorul de balansare doar
pentru nodurile de pe drumul de la rădăcina subarborelui până la nodul de inserat, caz în care
problema se gestionează ca într-unul din cazurile pe care le vom enumera în continuare, dar la
unul din nivelele de mai jos.
Dacă tipul arborelui este LH sau RH atunci rădăcina va avea, după inserare, factorul de
balansare +2 sau -2, în acest caz ne interesează tipul subarborelui în care se inserează noul
nod, factorul de balansare al acestuia putând fi LH, RH.
Cazul II.
a) Left-Left sau Right-Right
Cazurile cele mai simple sunt atunci când atât subarborele cât şi arborele au acelaşi
factor de balansare, de exemplu: Left-Left sau Right-Right. După recalcularea factorului de
balans pentru rădăcină se observă că proprietatea AVL a fost încălcată. Rezolvarea acestei
probleme se face printr-o rotaţie dreapta/stânga a nodului al cărui factor de balansare încalcă
proprietatea AVL.
b) Left-Right sau Right-Left
Când arborele şi subarborele au factorii de balansare diferiţi Left – Right, Right – Left
se execută o rotaţie care să ne aducă într-una din situaţiile Cazului I adică Left–Left sau
Right–Right apoi se execută rotaţia corespunzătoare cazului în care s-a ajuns.

Exemplu
În figură este reprezentat un arbore AVL cu factorii de balansare calculaţi
înaintea inserării nodului cu cheia 6 (roşu), dar şi după inserare (albastru). Din
aceste calcule rezultă că ne aflăm într-un caz Left-Left pentru că arborele era LH
înainte de inserare şi subarborele în care s-a făcut inserarea a devenit LH după
inserare.

33
Pentru a rezolva problema încălcării proprietăţilor AVL (factorul de balansare al
rădăcinii este -2) se va efectua o rotaţie spre dreapta după rădăcină. În figura
următoare se poate vedea arborele AVL şi factorii lui de balansare după
efectuarea rotaţiei amintite.

AVL după rotaţia Left-Left

Adăugaţi, şi voi, în acest arbore, un nod cu cheia 5.

Ştergerea
Procedăm la fel ca în ABC doar că va trebui să recalculăm factorul de balans al tuturor
nodurilor care se află pe drumul de la nodul şters (este mereu frunză) la rădăcină. Când
întâlnim un factor de balans +2 sau -2 îl restabilim cu rotaţiile cunoscute la inserare şi
recalculăm factorul de balansare de la cest nod spre rădăcină.
a) Ştergerea unei frunze ne face probleme atunci când fratele ei nu este frunză, care
impune executarea de rotaţii pentru aduce problema într-una din situaţiile Left-Left
sau Right-Right.
b) Ştergerea unui nod care are un copil nu ne face probleme pentru că dacă fratele are
factorul de balansare 0, atunci prin ştergerea nodului şi înlocuirea sa cu copilul,

34
părintele va avea noul factor de balansare 0, iar în cazul în care fratele are factorul de
balansare +1 sau -1 noul factor de balansare al părintelui va fi +1 sau -1.
c) Ştergerea unui nod care are doi copii se rezolvă la fel ca la ABC, iar dacă factorul de
balansare al unui nod devine +2 sau -2 se execută o rotaţie după acesta.
Să ne reamintim...
Factorul de balansare (FB) a unui nod x reprezintă diferenţa dintre înălţimea
subarborelui drept şi cea a subarborelui stâng.
Un nod care are factorul de balansare -1, 0 sau 1 se numeşte balansat.
Arborele AVL este un arbore binar de căutare care are proprietatea că oricare
nod al său este balansat.
În funcţie de factorul de balansare a rădăcinii unui arbore AVL putem defini trei
tipuri de arbori
LH când FB(rad) = -1
RH când FB(rad) = +1
EH când FB(rad) = 0

35
3.5 Arbori Splay.
Daniel Dominic Kaplan Sleator şi Robert Tarjan au inventat arborii splay, arborii link/cut
şi structurile de date persistente.
Arborii splay sunt arbori binari de căutare care se autobalansează folosind o operaţie
specială numită splay. Această operaţie mută cheia dată x pe poziţia rădăcinii. În cazul în care
cheia căutată nu se află în arbore va fi folosită ultima cheie vizitată în drumul efectuat pentru
căutarea lui x. În cadrul acestei operaţii se folosesc noţiunile de nepot şi rotaţie.
Un nepot poate fi left-left, right-right, left-right, sau right-left. “N este un nepot left–left
dacă este un copil stânga al unui nodului părinte P, iar p este copil stâng al nodului bunic B”
Aşadar N este un nepot left-left dacă: N<P<B
Există situaţii în care nepotul nu are încă bunic, acestea sunt N<P sau P>N.
Rotaţiile efectuate pot fi simple şi se numesc zig sau zag, dar pot fi şi duble şi ele se
numesc zig-zig sau zig-zag.
Rotaţia zig se efectuează pentru nepotul N<P
Rotaţia zag pentru P<N
Rotaţia zig-zig N < P < B, B < P < N (left-left sau right-right)
Rotaţia zig-zag B < N < P, P < N < B (left-right, right-left)
În figura 6.1.1. este schema logică după care se execută operaţiile splay.
În schema logică din figura de mai jos puteţi vedea cum se efectuează rotaţiile în funcţie de
tipul nepotului. Va trebui să ştiţi când sunt necesare aceste rotaţii numite splay.

36
Operaţia Se execută splay

Căutare Dacă cheia este găsită se face splay în jurul nodului unde
se află cheia, altfel se foloseşte părintele ultimului nod
vizitat.
Inserare Pentru nodul în care a fost inserată noua cheie

Ştergere Pentru nodul şters, apoi se şterge rădăcina, care provoacă


o separare în doi subarbori prin operaţia numită Split. Se
face splay pentru succesorul sau predecesorul nodului
şters, iar ulterior se execută operaţia de unificare a celor
doi arbori numită Join.
Split desparte arborele dat în doi subarbori, unul care conţine toate nodurile având cheile
mai mici decât o cheie x dată, iar celălalt format din toate nodurile care au cheile mai mari sau
egale decât cheia dată.

Join uneşte doi arbori în care oricare dintre cheile unui arbore sunt mai mici sau egale
decât cheile celuilalt.
Aproape toate operaţiile (mai puţin ştergerea) dintr-un arbore splay se pot reduce la
efectuarea unui număr de operaţii splay.
O secvenţă de m operaţii într-un arbore splay care are iniţial n noduri se va efectua într-
un timp O (n ln (n) + m ln (n)).

3.5 Rezumat
Am văzut aici ce sunt arborii roşu-negri, cum se pot face inserţii şi ştergeri în
complexitate O(Log(n)). Aceleaşi proprietăţi le-am obţinut şi pentru arborii AVL şi
Splay.
3.6 Test de autoevaluare a cunoştinţelor
3.6.1. Construiţi prin inserări succesive arborele roşu-negru având cheile 41, 38, 31,
12, 19, 33, 40, 8, 5, 39, 44.
3.6.2 Ştergeţi folosind predecesorul, acolo unde cazul, următoarele chei: 12, 39, 41
din arborele obţinut la exerciţiul 3.1.
3.6.3 Calculaţi factorul de balansare pentru nodurile arborelui binar din figură

37
3.6.4 În figura următoare stabiliţi tipul de nepot pentru nodurile 1, 13, 17, 21.

Arbore Splay
Rezultatele le găsiţi la sfârşit, la pag 108.

38
Unitatea de învăţare 4 Îmbogăţirea structurilor de date.

4.1 Introducere
În practica programării apar câte o dată situaţii care necesită numai o structură de
date clasică, ca de exemplu lista dublu înlănţuită, tabela de dispersie sau arborele
binar de căutare, însă majoritatea problemelor care trebuie rezolvate au nevoie de o
structură nouă. Totuşi foarte rar este nevoie să se creeze un tip complet nou de
structură de date. Mai des se potriveşte să fie suficient să adaugăm informaţii
suplimentare la o structură de date clasică în aşa fel încât ea să raspundă nevoilor
impuse de aplicaţia pe care o realizăm.
Desigur, îmbogăţirea structurilor de date nu este întotdeauna simplă, deoarece
informaţia adăugată trebuie să fie actualizată, şi întreţinută prin operaţiile obişnuite
ale structurii de date respective.

4.2 Competenţe
La sfârşitul acestei unităţi de învăţare studenţii vor fi capabili să:
 Creaţi structuri de date noi folosind unele cunoscute
 Rezolvaţi optim probleme de statistică de ordine
 Lucraţi cu structuri de intervale

Durata medie de studiu individual


Parcurgerea de către studenţi a acestei unităţide învîţare se face în 2 ore.

4.3 Arbori pentru statistici de ordine


Definim a i-a statistică de ordine a unei mulţimi de n elemente ca al i-lea cel mai mic
element. De exemplu, minimul unei multimi de n elemente este prima statistică de ordine (i =
1), iar maximul este a n-a statistică de ordine (i = n). Intuitiv, o mediană este punctul de la
jumătatea drumului. Când n este impar, mediana este unică, şi apare pe pozitia i = (n+ 1)/2.
Când n este par, există două mediane, care apar pe poziţiile i = n/2,
i = n/2+ 1.
Se poate arăta că orice statistică de ordine poate fi determinată într-un timp de O(n) în
cazul unei mulţimi neordonate.
În acest capitol vom vedea cum se pot modifica arborii roşu-negri pentru ca orice
statistică de ordine să se determine într-un timp O(lg n) şi vom afla cum se determină rangul
unui element - poziţia acestuia în ordonarea liniară a mulţimii - tot într-un timp O(lg n).
In figura următoare vom prezenta o structură de date care posedă operaţii rapide de
statistici de ordine. Un arbore cu statistică de ordine T este un arbore roşu-negru care conţine
o informaţie suplimentară în fiecare nod. La câmpurile uzuale pentru un nod x dintr-un arb
ore roşu-negru: KEY(x), CUL(x), P(x), LS(x), şi LD(x), se adaugă un câmp nu DIM(x). Acest
câmp conţine numărul de noduri (interne) din subarborele cu rădăcina x (incluzându-l şi pe x),
adică dimensiunea subarborelui. Dacă facem convenţia DIM(NIL)=0, atunci are loc
identitatea:
DIM(x)=DIM(LS(x))+DIM(LD(x))+1
Un arbore de statistică de ordine care este de fapt un arbore roşu-negru îmbogăţit.

39
Exemplu
Nodurile gri sunt roşii, iar nodurile negre sunt negre. În partea de jos a fiecarui
nod este câmpul DIM(x) care reprezintă numărul de noduri ale subarborelui cu
rădăcina x.

Daţi un exemplu de statistică de ordine.

Exemplu
Pentru a vedea cum funcţioneaza RN-SELECT, să considerăm căutarea
pentru al 17 -lea cel mai mic element din arborele de statistica de ordine T din
figura de mai sus. Se începe cu x egal cu rădăcina, a carei cheie este 26 şi cu i =
17.
Deoarece dimensiunea subarborelui stâng al lui 26 este 12,. Prin urmare,
ştim deja că nodul cu rangul 17 este a117-13 = 4-lea cel mai mic element din
subarborele drept al lui 26. După apelul recursiv, x este nodul având cheia 41, iar i
= 4.
Deoarece dimensiunea subarborelui stâng al lui 41 este 5, rangul său în
subarborele în care acesta este rădăcina, este 6. Prin urmare ştim deja că nodul cu
rangul 4 este în al 4-lea cel mai mic element al subarborelui stâng al lui 41. După
apelul recursiv, x este nodul având cheia 30, iar rangul său în subarborele pentru
care el este rădăcină este 2. Aşadar se face un nou apel recursiv pentru a-l
determina pe al 14-2 =2-lea cel mai mic element din subarborele având rădăcina
38. La acest apel vom constata că subarborele stâng are dimensiunea 1, ceea ce
înseamnă că rădăcina 38 este al doilea cel mai mic element. În consecinţă, acest

40
ultim apel va întoarce pe y ca pointer la nodul având cheia 38 şi execuţia
procedurii se termină.

Arătaţi cum funcţionează RN-SELECT pentru căutarea celui de al 15 –lea cel mai
mic element din acelaăi arbore.

Deoarece fiecare apel recursiv coboară un nivel în arborele de statistică de ordine T,


timpul total pentru acest algoritm este, în cel mai defavorabil caz, proporţional cu înălţimea
arborelui. Deoarece arborele este roşu-negru înălţimea sa este O(lg n), unde n este numărul de
noduri. Prin urmare, timpul de execuţie al algoritmului prezentat este O(lg n) pentru o
mulţime dinamică avand n elemente.
Determinarea rangului unui element.
Fiind dat un pointer la un nod x dintr-un arbore de statistică de ordine T, procedura
RN-RANG returnează r = poziţia lui x în ordinea liniară dată de parcurgerea în inordine a lui
T.

RN-RANG(T,x,r)
R=DIM(LS(x))+1
y=x
cat timp yRAD(T)
daca y=LD(P(x)) atunci
r=r+DIM(LS(P(y)))+1
sdaca
y=P(y)

sciclu

return
Exemplu
Execuţia algoritmului RN-RANG pe arborele de statistică de ordine, din
figura anterioară, pentru determinarea rangului nodului având cheie 38 va
produce următoarea secvenţa de valori pentru KEY(y) şi r înregistrate la
începutul corpului ciclului cat timp.
Iteraţia KEY r
1 38 2
2 30 4
3 41 4
4 26 17
Procedura va retuma rangul r = 17.

.Arătaţi care este secvenţa de valori pentru KEY(y) şi r înregistrate la începutul


corpului ciclului cat timp pentru determinarea rangului nodului având cheie 19.

Fiecare iteraţie a ciclului cat timp consumă un timp de O(1), iar y urcă un nivel în
arbore la fiecare iteraţie, timpul de execuţie al algoritmului RN- RANG este, în cel mai rău

41
caz, proporţional cu înălţimea arborelui: O(lg n) pentru un arbore de statistică de ordine având
n noduri.
Întreţinerea dimensiunilor subarborilor.
Fiind dată valoarea câmpului dimensiune din fiecare nod, procedurile RN-SELECT şi
RN-RANG pot calcula repede informţia de statistică de ordine. Nu am caştigat nimic dacă
câmpurile nu se pot întreţine eficient prin operaţiile de bază ce modifică arborii roşu-negri.
Vom arăta acum că dimensiunile subarborilor se pot întreţine atât pentru inserare cât şi pentru
ştergere, fara afectarea timpilor asimptotici de execuţie ai acestor operaţii.
Inserarea unui nod într-un arbore roşu-negru se face în două etape:
- se insereaza nodul x în arborele dat ca şi cum ar fi un arbore binar de căutare obişnuit
şi se colorează inserat cu roşu
-se aplică asupra arborelui rezultat un algoritm care va recolora nodurile pentru
conservarea proprietăţilor specifice arborelui roşu-negru.
În prima fază se coboară în arbore începând de la rădăcină şi se inserează nodul nou ca
fiu al unui nod existent. A doua fază înseamnă urcarea în arbore, modificând culorile şi
efectuând la sfârşit rotaţii pentru a conserva proprietăţile roşu-negru.
Pentru a întreţine dimensiunile subarborilor în prima fază, se va incrementa câmpul
dimensiune[x] pentru fiecare nod x de pe drumul traversat de la rădăcină în jos spre frunze.
Noul nod care se adăuga va primi valoarea 1 pentru câmpul său dimensiune. Deoarece pe
drumul parcurs sunt O(lg n) noduri, costul suplimentar pentru întreţinerea câmpurilor
dimensiune va fi şi el O(lg n ). În faza a doua, singurele modificări structurale ale arborelui
roşu-negru sunt produse de rotaţii, care sunt cel mult două. Mai mult, rotaţia este o operaţie
locală; ea invalideză numai câmpurile dimensiune din nodurile incidente (de la capetele)
legăturii în jurul căreia se efectuează rotaţia. La codul procedurii ROTEŞTE-STANGA(T ,x)
se adaugă următoarele două linii:
dimensiune(y)= dimensiune(x)
dimensiune(x)= dimensiune(LS(x))+ dimensiune(LD(x))+1
Figura de mai jos ilustrează cum sunt actualizate câmpurile dimensiune. Pentru
procedura ROTEŞTE-DREAPTA modificările sunt simetrice.
Deoarece la inserarea unui nod într-un arbore roşu-negru sunt necesare cel mult două
rotaţii, se consumă un timp suplimentar de O(1) pentru actualizarea câmpurilor dimensiune, în
faza a doua a inserării. În concluzie, timpul total necesar pentru inserarea unui nod într-un
arbore de statistică de ordine cu n noduri este de O(lg n) acelaşi din punct de vedere
asimptotic cu cel al arborilor roşu-negru obişnuiţi.
Ştergerea unui nod dintr-un arbore roşu-negru are de asemenea două faze: prima
operează pe arborele binar de căutare, iar a doua face cel mult trei rotaţii şi în rest nu
efectuează alte modificări structurale ale arborelui. Prima fază elimină din arbore un nod y.
Pentru a actualiza dimensiunile subarborelui, vom traversa un drum în sus de la nodul y la
rădăcină şi vom decrementa câmpurile dimensiune ale nodurilor de pe acest drum. Deoarece
drumul are lungimea O(lg n), în cazul unui arbore roşu-negru cu n noduri, timpul suplimentar
consumat cu întreţinerea câmpurilor dimensiune în prima fază a ştergerii unui nod este de
O(lg n). Cele O(1) rotaţii din faza a doua a ştergerii sunt gestionate în aceeaşi manieră ca şi în
cazul inserării. Prin urmare, atât inserarea cât şi ştergerea, inclusiv întretinerea câmpurilor
dimensiune, consumă un timp O(lg n) pentru un arbore de statistică de ordine cu n noduri.

42
Să ne reamintim...
La proiectarea algoritmilor apare frecvent problema îmbogăţirii structurilor
de date uzuale pentru ca acestea să ofere funcţionalitate suplimentară.
Procesul de îmbogăţire a unei structuri de date se poate împărţi în patru paşi:
1. Alegerea unei structuri de date suport.
2. Determinarea informaţiei suplimentare care trebuie inclusă şi întreţinută în
structura de date luată ca suport.

3. Verificarea posibilităţii întreţinerii informaţiei suplimentare în cazul


operaţiilor de bază care modifică structura suport.
4. Proiectarea noilor operaţii.
Ca şi în cazul altor metode de proiectare prezentate schematic, nu trebuie să
respectăm exact paşii în ordinea de mai sus. Nu are nici un rost, de exemplu, să se
determine informaţia suplimentară şi proiectarea noilor operaţii (paşii 2 şi 4) dacă nu
se va putea întreţine eficient informaţia suplimentară memorată în structura de date.
Totuşi, această metodă în patru paşi va asigura o abordare ordonată a eforturilor de
îmbogăţire a unei structuri de date şi o schemă de organizare a documentaţiei
referitoare la aceasta.

Paşii de mai sus au fast exemplificaţi la începutul capitolului pentru proiectarea


arborilor de statistică de ordine. La pasul 1 am ales ca structură suport arborii roşu-negri. O
indicaţie asupra utilităţii acestor arbori la obţinerea statisticilor de ordine este dată de eficienţa
operaţiilor specifice mulţimilor dinamice pe o ordine totală, precum MINIM, MAXIM,
SUCCESOR şi PREDECESOR.
La pasul 2 am adăugat câmpurile dimensiune, care conţin, pentru fiecare nod x,
dimensiunea subarborelui având rădăcina x. În general, informaţia suplimentară are ca scop sa
facă operaţiile (proprii structurii îmbogăţite) mai eficiente. De exemplu, am fi putut
implementa operaţiile RN-SELECT şi RN-RANG folosind numai cheile memorate în arbore,
însă în acest caz timpul lor de execuţie nu ar mai fi fost O(lg n). Uneori această informaţie
suplimentară conţine referinţe şi nu date.
La pasul 3, ne-am asigurat că operaţiile de inserare şi ştergere pot întreţine câmpurile
dimensiune fără a-şi altera eficienţa asimptotică, ele executându-se tot într-un timp O(lg n). În
cazul ideal, un numar mic de modificări ale structurii de date, trebuie să fie suficient pentru a
întreţine informaţia suplimentară. De exemplu, dacă am memora în fiecare nod rangul său din
arbore, atunci operaţiile RN-SELECT şi RN-RANG s-ar executa mai rapid, dar inserarea unui
nou element minim în arbore, ar provoca modificarea acestei informaţii (rangul) în fiecare
dintre nodurile arborelui. În schimb dacă memorăm dimensiunea subarborilor în locul
rangului, inserarea unui nou element va necesita modificări ale informaţiilor doar in O(lg n)
noduri.
La pasul 4, am proiectat operaţiile RN-SELECT şi RN-RANG. De fapt, îmbogăţirea
structurii de date este impusă tocmai de nevoia de a implementa noi operaţii. Uneori
informaţia suplimentară se va putea folosi nu numai la proiectarea operaţiilor noi, ci şi la
reproiectarea celor proprii structurii de date suport pentru a le îmbunătăţii performanţele.
4.5 Arbori de intervale.
Ne propunem să îmbogăţim arborii roşu-negri pentru a realiza operaţii pe mulţimi
dinamice de intervale. Un interval închis este o mulţime notată [t1;t2] ={tR|t1,t2R, t1<t<t2}.

43
În această secţiune vom presupune că intervalele cu care lucrăm sunt închise; extinderea
rezultatelor la intervale deschise sau semideschise este imediată.
Intervalele reprezintă un instrument convenabil de reprezentare a evenimentelor care
ocupa fiecare un interval continuu de timp. Am putea dori, de exemplu, să interogăm o bază
de date de intervale de timp pentru a descoperi ce evenimente au apărut într-un anumit
interval. Bazele de date temporale, de altfel, sunt la modă acum. Structura de date prezentată
în aceasta secţiune oferă un mijloc eficient de întreţinere a unei astfel de baze de date de
intervale.
Intervalul [t1;t2] se poate reprezenta sub forma unui obiect i, care are câmpurile jos[i] =
t1 (capătul inferior) şi sus[i] = t2 (capătul superior).
Spunem ca intervalele i şi i’ se suprapun daca i  i’ adică dacă jos[i]  sus[i’] şi jos[i’] 
sus[i]. Pentru orice două intervale i şi i’ are loc trihotomia intervalelor, adică ele verifică doar
una din urmatoarele trei proprietăţi:
a. i şi i’ se suprapun,
b. sus[i] < jos[i‘],
c. sus[i] < jos[i ‘].

În figura următoare sunt prezentate cele trei cazuri:

(a)

(b) (c)

Numim arbore de intervale un arbore roşu-negru care întreţine o mulţime dinamică de


elemente, în care fiecare element x conţine un interval int[x]. Arborii de intervale au
urmatoarele operaţii.
INSEREAZĂ(T, x) adaugă la arborele de intervale T elementul x care are în câmpul int un
interval.
ŞTERGE(T,x) şterge elementul x din arborele de intervale T.
CAUTA(T,x,r) retumează un pointer la un element din arborele de intervale pentru care int[y]
se suprapune cu intervalul int[x], sau NIL dacă în mulţime nu există un astfel de element.
--
În figura următoare vom ilustra modul de reprezentare al unei mulţimi de intervale cu
ajutorul unui arbore de intervale. Vom aplica metoda în patru paşi descrisă mai înainte pentru
a proiecta arborele de intervale şi operaţiile proprii acestuia.

44
Exemplu

Şi arborele corespunzător

Parcurgerea în inordine a acestui arbore va produce lista nodurilor sortată după


capătul din stânga.

.Daţi şi voi unexemplu de arbore de intervale după ce vă definiţi o mulţime de


intervale.

Pasul 1: Structura de date suport


Am ales ca structură suport un arbore roşu-negru în care fiecare nod x conţine un
câmp interval int[x] şi pentru care cheia nodului x este capătul inferior, jos[int[x]], al
intervalului. Prin urmare, o traversare în inordine a structurii de date va produce o listă a
intervalelor, ordonată după capătul inferior al acestora.

Pasul 2: Informaţia suplimentară.


Pe lângă câmpul int[x], fiecare nod x va conţine o valoare max[x] care reprezintă
valoarea maximă a capetelor intervalelor memorate în subarborele având rădăcina x.
Deoarece capătul superior al fiecărui interval este cel puţin la fel de mare ca şi capătul inferior
al acestuia, max[x] va fi de fapt valoarea maximă a capetelor superioare ale intervalelor
memorate în subarborele având rădăcina x.

45
Pasul 3: Întreţinerea informaţiei suplimentare.
Inserarea şi ştergerea se pot executa într-un timp O(lg n) pe un arbore de intervale cu n
noduri. Valoarea câmpului max[x] se determină uşor dacă se cunosc int[x] şi valorile max ale
fiilor nodului x cu :
max[x] = max(sus[int[x]], max[LS[x]], max[LD[x]]).
De fapt, actualizarea câmpurilor max după o rotaţie se poate realiza într-un timp O(1).
Pasul 4: Proiectarea noilor operaţii.
Singura operaţie care trebuie proiectată este CAUTA(T ,i,x), care găseşte un interval
din arborele T suprapus pe intervalul i. Dacă T nu conţine astfel de intervale se returnează
NIL altfel retumează x - pointer la intervalul căutat.
CAUTA(T,i,x)
X=rădăcină[T]
cat timp X NIL şi i nu se suprapune cu int[x]
daca LS[x] NIL şi max[LS[x]]  jos[i] atunci
x=LS[x]
alfel
x=LD[x]
return

4.6 Rezumat
În acest capitol am vom văzut cum se pot modifica arborii roşu-negri pentru
ca orice statistică de ordine să se determine într-un timp O(lg n) şi cum se determină
rangul unui element - poziţia acestuia în ordonarea liniară a mulţimii - tot într-un
timp O(lg n).
La câmpurile uzuale pentru un nod x dintr-un arbore roşu-negru: KEY(x),
CUL(x), P(x), LS(x), şi LD(x), se adaugă un câmp nou DIM(x). Acest câmp conţine
numărul de noduri (interne) din subarborele cu rădăcina x (incluzându-l şi pe x),
adică dimensiunea subarborelui. Dacă facem convenţia DIM(NIL)=0, atunci are loc
identitatea:
DIM(x)=DIM(LS(x))+DIM(LD(x))+1
La proiectarea algoritmilor apare frecvent problema îmbogăţirii structurilor
de date uzuale pentru ca acestea să ofere funcţionalitate suplimentară.
Procesul de îmbogăţire a unei structuri de date se poate împărţii în patru paşi:
1. Alegerea unei structuri de date suport.
2. Determinarea informaţiei suplimentare care trebuie inclusă şi întreţinută în
structura de date luată ca suport.
3. Verificarea posibilităţii întreţinerii informaţiei suplimentare în cazul
operaţiilor de bază care modifică structura suport.
4. Proiectarea noilor operaţii.
Am îmbogăţit arborii roşu-negri pentru a realiza operaţii pe mulţimi dinamice
de intervale.
Numim arbore de intervale un arbore roşu-negru care întreţine o mulţime
dinamică de elemente, în care fiecare element x conţine un interval int[x]. Arborii de
intervale au urmatoarele operaţii:
 INSEREAZĂ(T, x) adaugă la arborele de intervale T elementul x care are în

46
câmpul int un interval.
 ŞTERGE(T,x) şterge elementul x din arborele de intervale T.
 CAUTA(T,x,r) retumează un pointer la un element din arborele de intervale
pentru care int[y] se suprapune cu intervalul int[x], sau NIL dacă în mulţime
nu există un astfel de element.

4.7 Test de autoevaluare a cunoştinţelor


Exerciţiul 4.7.1.
Verificati afirmaţia: ‘dacă am memora în fiecare nod rangul său din arbore, atunci
operaţiile RN-SELECT şi RN-RANG s-ar executa mai rapid, dar inserarea unui nou
element minim în arbore, ar provoca modificarea acestei informaţii (rangul) în
fiecare dintre nodurile arborelui’ .
Exerciţiul 4.7.2. Scrieţi algoritmul care găseşte toate intervalele i’ pentru care
sus[i] < jos[i ‘], unde i este un interval la intrare.
Exerciţiul 4.7.3. Care este complexitatea algoritmului de mai sus?

Rezultatele le găsiţi la sfârşit, la pag 111.

47
Unitatea de învăţare 5. Arbori balansaţi B+.

5.1 Introducere
Arborii balansaţi sunt arbori de căutare destinaţi să lucreze eficient pe
discuri magnetice; ei sunt realizaţi urmărind aceleaşi idei şi scopuri ca şi arborii
roşu-negrii dar sunt superiori acestora în minimizarea timpului pentru intrare-ieşire
.
Diferenţa esenţială este că, în arborii balansaţi, un nod poate avea mai mulţi
descendenţi (până la sute). Asemănarea este că înălţimea arborelui este O(log n)
deşi baza logaritmului (mult mai mare) dă o înălţime corespunzator mai mică.
Aceasta este important pentru că operaţiile asupra arborelui, cum ar fi căutarea,
inserarea şi ştergerea au complexităţi proporţionale cu înălţimea arborelui.
Se vede din exemplu cum arborii balansaţi generalizează arborii binari de
căutare.

5.2 Competenţe
La sfârşitul acestei unităţi de învăţare studenţii vor fi capabili să:
 ştim ce sunt arborii balansaţi
 calculăm înălţimea arborilor balansaţi
 să efectăm operaţii cu arbori balansaţi

Durata medie de studiu individual


Parcurgerea de către studenţi a acestei unităţide învîţare se face în 2 ore.

Exemplu
Cheile sunt consoane. Un nod conţine n(x) chei şi are n(x) + 1 descendenţi.
Toate frunzele au aceeaşi adancime. Nodurile albe marcheză drumul pentru
căutarea literei R.

48
Inlocuiţi literele cu numere astfel ca să se păstreze proprietăţile de arbore balansat
B+.

5.3 Structura datelor în memoria pe disc.


Avem la dispoziţie multe tehnologii de memorare a datelor. Memoria principală este
realizată pe cipuri de siliciu. Această memorie a crescut şi s-a ieftinit de-a lungul timpului,
totuşi ea rămâne mai mică şi mai scumpă decât memoria pe medii magnetice deşi mult mai
rapidă.
Timpul unor operaţii pe calculator ce includ citiri şi scrieri pe disc depind de:
- numarul de accese la disc
- timpul de lucru al procesorului.
Folosim arbori balansaţi în aplicaţii în care datele nu pot intra în memoria Principală.
Algoritmii conţinuţi în acest capitol copiază anumite pagini de memorie de pe disc în
memoria principală şi, pe cele care s-au modificat, le rescrie (înapoi pe disc). Modelul, din
acest punct de vedere, este următorul:
Fie x un pointer către un obiect. Dacă obiectul se află în memoria principală, ne vom

referi la câmpuri ca de obicei (ex.KEY(x)). Dacă obiectul se află pe disc, vom face mai întâi o
operaţie de citire CIT_DISK(x) a obiectului x şi apoi ne putem referi la câmpurile lui. Dacă s-
au efectuat modificări ale câmpurilor lui x ele vor fi actualizate pe disc prin scriere
SCR_DISK(x).
Arbore balansat care are mai mult de un miliard de chei. Ca să micşorăm numărul de
accese la disc trebuie să mărim dimensiunea nodului. În general un nod va fi memorat pe o
pagină întreagă. Aceasta înseamnă un factor de ramificare între 50 şi 2000.
5.4 Definiţia arborilor balansaţi.
Vom considera, ca şi mai înainte, că “informaţia satelit” asociată cu o cheie este
memorată în acelaşi nod cu cheia şi este “mutată” odată cu mutarea cheii.
Un arbore balansat (echilibrat) T este un arbore cu rădăcina Rad(T) cu următoarele
proprietăţi :
1.Fiecare nod are următoarele câmpuri:
a) n( x) numarul de chei de stocate în x
b) cele n( x) chei memorate în ordine crescătoare
KEY1(x),KEY2(x),...,KEYn(x)(x).
c)F(x) cu valoare adevarat daca x este frunză şi fals dacă x nu este frunză
d) Dacă x este nod intern (Frunza(x) este fals) atunci x mai conţine n(x)+ 1
pointeri Cl(X),C2(X) ,... ,Cn(x)+l(X) la copiii (descendenţii) lui x
2.Cheile din x separă cheile din descendenţi adică dacă kj este o cheie oarecare din
descendentul de la adresa Cj( x) cu j{1,2,...,n( x)+ 1} atunci:
k1KEY1(x)k2KEY2(X) ... KEY n(x)(x)kn(x)+l

49
3.Fiecare frunză are aceeaşi “adâncime” care este înălţimea arborelui.
4.Există un număr maxim şi un număr minim de chei pe care le poate conţine un nod
care sunt în legătură cu t  2 numit gradul minim al lui T.
a)Fiecare nod, în afară de rădăcină, are cel puţin t-1 chei şi deci, dacă este
intern, are cel puţin t descendenţi. Dacă arborele este nevid, rădăcina trebuie să aibă
cel puţin o cheie .
b)Fiecare nod poate conţine cel mult 2t-1 chei (un nod intern are cel mult 2t
descendenţi). Spunem ca un nod este plin, dacă are exact 2t-1 chei.
Cel mai simplu arbore balansat este cu t = 2 unde fiecare nod poate avea 2, 3 sau 4
descendenţi.
Înălţimea unui arbore balansat.

Teorema
Dacă n1 este numărul de chei dintr-un arbore balansat cu înălţimea h şi gradul minim
t  2 atunci h logt ((n+1)/2).
Demonstraţie.
O să pornim în demonstraţie de la un arbore cu număr maxim de chei ca în exemplul
următor.
Exemplu

Dacă arborele are înălţimea h, atunci numărul de noduri este minim când rădăcina
conţine o cheie şi celelalte noduri conţin t-1 chei. În acest caz sunt 2 noduri la primul nivel, 2t
la al doilea nivel, şi aşa mai departe până la nivelul h unde sunt 2th-1.

n  1+ (t - 1)2t-1 =1 + 2(t-1)((th-1)/(t-1))= 2th - 1


i=1,h

5.5 Operaţii în arbori balansaţi.


Pentru următorii algoritmi vom presupune că rădăcina arborelui este în memoria
principală, deci nu avem CIT_DISK pentru ea, dar este nevoie de SCR_DISK dacă avem
actualizări ale câmpurilor rădăcinii. Mai presupnem că orice alt nod are nevoie să fie citit ca
să avem acces la câmpurile lui.
Căutarea în arborii balansaţi.
Algoritmul este recursiv şi se apelează prima dată cu B_TREE_CAUT(Rad(T), k ,rez),
unde k este cheia cautată, rez conţine rezultatul căutării adică perechea (y,i) care înseamnă că
nodul y are a i-a cheie KEY(y)=k sau rez=Nil dacă cheia nu este în arbore.

50
B- TREE- CAUT( x,k,rez)
i=l
atât timp cat i<n(x) şi k> KEYi(x)
i=i+l

Sciclu
Daca in(x) şi k = KEYi(x) atunci
rez = (x, i)
return
sdaca
Daca Frunza(x) atunci
rez = Nil
Return
altfel
Cheama CIT_DISK(ci(x))
Cheama B_TREE_CAUT(ci(x), k, rez)
return
sdaca

b.Construcţia unui arbore balansat.


Pentru aceasta vom creea mai întâi un arbore vid şi vom insera pe rând în el noile chei.
Avem nevoie mereu de locuri libere pe disc pe care le fumizează ALOC_NOD().

B_TREE_CRE(T)
x = ALOC_NOD( )
Frunza(x) = True
n(x) = 0
SCR_DISK(x)
Rad(T) = x
Return

Dacă un nod este plin, ca să putem insera în continuare, el trebuie rupt în două, ca
înexemplul următor:

Exemplu

51
Nodul plin are 2t - 1 chei şi cheia din mijloc (indice t) se duce în părinte, presupus
neplin.
Dacă se face ruperea rădăcinii atunci arborele creşte în înălţime cu 1. Procedura
B_TREE_RUP are ca intrare un nod intern neplin - x (aflat deja în memoria principală), un
index - i şi un nod y = ci(x) care este un descendent plin al lui x.

B_TREE_RUP(x, k, y)
z = ALOC_NOD( )
Frunza(z) = Frunza(y)
n(z) = t-1
Pentru i = 1, t-1
KEYi(z) = KEYi + t(y)
spentru
Daca nu Frunza(y) atunci
Pentru i=1,t
Ci(z) = Ci+t(z)
spentru
sdaca
n(y) = t-1
Pentru i = n(x)+1,k+l,-1
Ci+l(X) = Ci(x)
spentru
Ci+l(X)= z

Pentru i = n(x), k, -1
KEYi+l(X) = KEYi(x)
spentru
KEYk(x)=KEY t(y)
n(x) = n(x) +1
SCR_D ISK( x)
SCR_DISK(y)
SCR_DISK(z)
return

Inserarea în arborii balansaţi.


Putem să construim acum inserarea care începe cu cazul în care rădăcina este plină
exemplificat mai jos.

Exemplu

52
Cheia k trebuie inserată în arborele T, la locul ei.

B-TREE_INSERT(T, k)
r=Rad(T)
daca n(r) = 2t-1 atunci
s = ALOC_NOD( )
Rad(T) = s
Frunza(T) = False
n(s) = 0
cl(S) = r
cheama B_TREE_RUP(s, 1, r)
cheama B_TREE_INS_NEPLIN(s,k)
altfel
cheama B- TREE_INS_NEPLIN (r,k)

Sdaca
Return

Procedura B_TREE_INS_NEPLIN parcurge arborele în jos până la locul unde trebuie


făcută inserarea.

B- TREE_INS_NEPLIN(x, k)
i = n(x)
Daca Frunza(x) atunci
atata timp cat i  1 şi k<KEYi(x)
KEYi+1(x) = KEYi(x)
i=i-1
Sciclu
KEYi+1(X) = k
n(x) = n(x) + 1
SCR_DISK(x)
atata timp cat i  1 şi k<KEYi(x)
i=i-1
sciclu
i=i+l

53
CIT_DISK(ci(x))
Daca n(ci(x))=2t-l atunci
Cheama B_TREE_RUP(x,i,ci(x))
Daca k> KEYi( x) atunci
i=i+ 1
sdaca
sdaca

Cheama B_TREE_INS_NEPLIN(ci(x), k)
return

Exemplu

(a) arborele iniţial

(b) este inserat B

( c ) este inserat Q

(d) este inserat L

54
( e) este inserat F

Să ne reamintim...
Un arbore balansat (echilibrat) T este un arbore cu rădăcina Rad(T) cu
următoarele proprietăţi :
1.Fiecare nod are următoarele câmpuri:
a) n( x) numarul de chei de stocate în x
b) cele n( x) chei memorate în ordine crescătoare
KEY1(x),KEY2(x),...,KEYn(x)(x).
c)F(x) cu valoare adevarat daca x este frunză şi fals dacă x nu este
frunză
d) Dacă x este nod intern (Frunza(x) este fals) atunci x mai conţine
n(x)+ 1
pointeri Cl(X),C2(X) ,... ,Cn(x)+l(X) la copiii (descendenţii) lui x
2.Cheile din x separă cheile din descendenţi adică dacă kj este o cheie
oarecare din descendentul de la adresa Cj( x) cu j{1,2,...,n( x)+ 1}
atunci:
k1KEY1(x)k2KEY2(X) ... KEY n(x)(x)kn(x)+l
3.Fiecare frunză are aceeaşi “adâncime” care este înălţimea arborelui.
4.Există un număr maxim şi un număr minim de chei pe care le poate
conţine un nod care sunt în legătură cu t  2 numit gradul minim al lui T.
a)Fiecare nod, în afară de rădăcină, are cel puţin t-1 chei şi deci,
dacă este intern, are cel puţin t descendenţi. Dacă arborele este nevid,
rădăcina trebuie să aibă cel puţin o cheie .
b)Fiecare nod poate conţine cel mult 2t-1 chei (un nod intern are
cel mult 2t descendenţi). Spunem ca un nod este plin, dacă are exact 2t-1
chei.

Ştergerea unei chei dintr-un arbore balansat.


Aceasta este o operaţie similară cu inserarea, dar ceva mai complicată.
B_TREE_STERG(x, k) şterge din subarborele T începând în nodul x, cheia k. Grija este ca
numărul de chei din nodurile parcurse (altul decât rădăcină) să fie t (gradul minim), adică cu 1
mai mult decât de obicei ca să putem şterge o cheie. Aşa că, uneori, o anumită cheie trebuie să
coboare într-un nod descendent înainte de a-l parcurge. Dacă în acest mod rădăcina x rămâne

55
fără chei atunci singurul descendent ci(x) va fi noua rădăcină şi x dispare, micşorând astfel
înalţimea arborelui cu 1.

I. Dacă nodul este frunză


a) ştergerea se face natural dacă numărul de chei din nod este mai mare decât t-1,
b) dacă numărul de chei este chiar t-1 va trebui să se execute o fuzionare cu scopul de a
rezolva încălcarea proprietăţii t  1  n( x)  2t  1
Exemplu: În arborele exemplul următor ştergerea lui S nu ar încălca nici o proprietate deci se
poate face natural. Dar dacă am dori să ştergem cheia V aceasta ar aduce probleme pentru că
ar rămâne mai puţin d 2 chei. În acest caz va trebui să căutăm un frate stâng sau drept, potrivit
pentru a face o fuzionare (să aibă t-1 chei). În cazul în care nu există astfel de fraţi se va face
o rotaţie.
A. Am găsit un frate care are t-1 chei
În acest caz cheile din nodul din care s-a făcut ştergerea cheia părinte şi cheile fratelui vor
fuziona şi vor forma un nou nod care va avea:
- t-2 chei din nodul în care s-a făcut ştergerea plus
- 1 cheie părinte plus
- t-1 chei din nodul frate deci în total vor fi 2t-2 noduri adică un număr de chei care respectă
proprietatea t  1  n( x)  2t  1

Exemplu

Înainte de ştergerea cheii V

.Faceţi, în acest arbore, ştergerea cheii Y

Exemplu

56
B+ arbore după ştergerea cheii V

.Cum ar arăta după ştergerea cheii Y

B. Fraţii au mai mult de t-1 chei


Realizez o rotaţie în care o cheie a fratelui ia locul părintelui iar părintele coboară în nodul în
care trebuie să efectuez ştergerea. După această procedură atât fratele cât şi nodul în care se
efectuează ştergerea vor avea numărul potrivit de chei.
Exemplu:
În arborele de mai sus ştergerea lui E ne pune în situaţia în care nici unul din fraţi nu are t-1
chei, alegem fratele stâng şi efectuăm rotaţia (C urcă, D coboară), după care-l ştergem pe E.
(Să observăm că aici cuvântul rotaţie are altă semnificaţie decât cea legată de arborii binari de
căutare). Arborele va arăta astfel:

Exemplu

B+ arbore după rotaţie

Faceţi, aici ştergerea cheii E

II. Dacă cheia de şters se află într-un nod interior şi are mai mult de t-1 chei atunci:
a) dacă unul dintre fii cheii de şters are mai mult de t-1 chei atunci realizez o rotaţie în care o
cheie succesoare sau predecesoare a cheii de şters îi ia locul, cheia de şters coboară în fiul
stâng, respectiv drept, procedura se reia până când cheia de şters ajunge într-o frunză, moment
în care se vor aplica regulile de la I.
Exemplu:
În figura următoare ştergerea lui R folosind succesorul ne va obliga să executăm o rotaţie (S
urcă , R coboară):

57
Exemplu

Faceţi ştergerea cheii T

După ştergere arborele va arăta ca în figura ce urmează

Exemplu

B+ arbore după ştergere

Cum arată arborele după ştergerea cheii T

b) ambii fii ai cheii de şters au exact t-1 chei atunci realizez o fuziune a acestora împreună cu
cheia de şters după care procedura se reia până când cheia de şters ajunge într-o frunză,
moment în care se vor aplica regulile de la I.
Exemplu:
În figura următoare ştergerea lui X se face prin fuzionarea dintre X şi nodurile fii după care se
poate şterge cheia X, obţinându-se arborele din figura a doua

58
Exemplu

Exemplu

B+ arbore după ştergere

III. Dacă cheia de şters se află într-un nod interior şi are exact t-1 chei atunci
a) unul dintre fii cheii de şters are mai mult de t-1 chei atunci o cheie succesoare sau
predecesoare a cheii de şters va urca în nodul cu pricina iar cheia de şters va coborî în fiul LS
sau LD (rotaţie) şi procedura se reia până când cheia de şters ajunge într-o frunză, moment în
se vor aplica regulile de la I
Exemplu:
Ştergerea după succesor a lui U, din exemplul următor, ne obligă să facem mai întâi o rotaţie.

Exemplu

B+ arbore

59
Exemplu

B+ arbore după ştergere

b) ambii fii ai cheii de şters au exact t-1 chei atunci se face fuziunea cu unul din fraţii săi şi
coborârea unei chei din nodul părinte după care se reia procedura de ştergere până când cheia
va ajunge într-o frunză. În acest caz se poate ajunge la micşorarea înălţimii arborelui dat.
Exemplu:
Ştergerea lui S, din exemplul următor, va necesita fuzionarea dintre nodul curent şi fratele
acestuia urmată de coborârea unui cheii părinte, ceea ce va duce la micşorarea înălţimii arbo-
relui .

Exemplu

B+ arbore

Exemplu

Figura 7.1.13: B+ arbore după fuzionare

60
Pentru ştergerea lui S folosim regula II. b) adică S va coborî şi va fuziona cu fii săi din nodul
rezultat S va fi şters natural conform regulii I cazul a)..

Exemplu

B+ arbore după ştergere

Să ne reamintim...
1) Fuzionarea poate duce la depăşirea numărului de noduri admise dar este clar
că în acel nod se află şi cheia care urmează a fi ştearsă aşa că sigur până când ea va
ajunge la nivelul frunzei această încălcarea a proprietăţilor B+ se va remedia.
2) Ştergerea rădăcinii se face ca în cazurile II şi III dar în loc de t-1 ne vom raporta
la 1 pentru ea şi la t-1 pentru fii săi. Aşadar regulile vor fi
II. Dacă cheia de şters se află în rădăcină care are mai mult de o cheie atunci:
a) dacă unul dintre fii cheii de şters are mai mult de t-1 chei atunci realizez o rotaţie
în care o cheie succesoare sau predecesoare a cheii de şters îi ia locul, cheia de şters
coboară în fiul stâng, respectiv drept, procedura se reia până când cheia de şters
ajunge într-o frunză, moment în care se vor aplica regulile de la I,
b) ambii fii ai cheii de şters au exact t-1 chei atunci realizez o fuziune a acestora
împreună cu cheia de şters după care procedura se reia până când cheia de şters
ajunge într-o frunză, moment în care se vor aplica regulile de la I.
III. Dacă cheia de şters se află în rădăcină care are exact o cheie atunci:
a) unul dintre fii cheii de şters are mai mult de t-1 chei atunci o cheie succesoare
sau predecesoare a cheii de şters va urca în nodul cu pricina iar cheia de şters va
coborî în fiul LS sau LD (rotaţie) şi procedura se reia până când cheia de şters

61
ajunge într-o frunză, moment în se vor aplica regulile de la I
b) ambii fii ai cheii de şters au exact t-1 chei atunci se face fuziunea dintre fii şi
cheia din rădăcină apoi se reia procedura de ştergere până când cheia va ajunge într-
o frunză. În acest caz se ajunge la micşorarea cu o unitate a înălţimii arborelui dat.
.

5.6 Rezumat
Am văzut cum se realizează in decăii pentru bazele de date cu arbori balansaţi b+.
Un arbore balansat (echilibrat) T este un arbore cu următoarele proprietăţi :
1.Fiecare nod are următoarele câmpuri:
a) n( x) numarul de chei de stocate în x
b) cele n( x) chei memorate în ordine crescătoare
KEY1(x),KEY2(x),...,KEYn(x)(x).
c)F(x) cu valoare adevarat daca x este frunză şi fals dacă x nu este
frunză
d) Dacă x este nod intern atunci x mai conţine n(x)+ 1
pointeri Cl(X),C2(X) ,... ,Cn(x)+l(X) la copiii (descendenţii) lui x
2.Cheile din x separă cheile din descendenţi adică dacă kj este o cheie
oarecare din descendentul de la adresa Cj( x) atunci:
k1KEY1(x)k2KEY2(X) ... KEY n(x)(x)kn(x)+l
3.Fiecare frunză are aceeaşi “adâncime” care este înălţimea arborelui.
4.Există un număr maxim şi un număr minim de chei pe care le poate conţine
un nod care sunt în legătură cu t  2 numit gradul minim al lui T.
a)Fiecare nod, în afară de rădăcină, are cel puţin t-1 chei şi deci, dacă
este intern, are cel puţin t descendenţi. Dacă arborele este nevid, rădăcina
trebuie să aibă cel puţin o cheie .
b)Fiecare nod poate conţine cel mult 2t-1 chei (un nod intern are cel
mult 2t descendenţi). Spunem ca un nod este plin, dacă are exact 2t-1 chei.

5.7 Test de autoevaluare a cunoştinţelor


5.7.1. Fiind dat arborele din figură stabiliţi valoarea lui t astfel încât arborele să fie
un B+ arbore corect definit.

Arbore B+
5.7.2
Inseraţi succesiv în arborele din figură cheile A, Q, K, C şi Ţ ştiind că t=3

62
Arbore B+ în care se vor insera cheile A, Q, K, C şi Ţ
Rezultatele le găsiţi la sfârşit, la pag 111.

63
Unitatea de învăţare 6 Heap-uri binare.

Introducere
Am văzut deja în UI 2. cum se poate memora un arbore binar într-un vector.
Dacă acest arbore binar are proprietatea că pentru orice A şi B, dacă B este copilul
lui A atunci cheia(A) ≥ cheia(B) se numeşte heap Max.
Heap Min este structura de date de tip arbore care are proprietatea că pentru
orice A şi B, dacă B este copilul lui A atunci cheia(A) ≤ cheia(B).

6.2 Competenţe
La sfârşitul acestei unităţi de învăţare studenţii vor fi capabili să:
 Facă operaţii cu heap-uri binare
 sorteze vectori cu un nou algoritm cu complexitate minimă
 facă operaţii cu cozi de priorităţi

Durata medie de studiu individual


Parcurgerea de către studenţi a acestei unităţide învîţare se face în 2 ore.

6.3 Definirea heap-urilor binare.


Să vedem un exemplu

Exemplu

Heap max binar

Daţi un exemplu de heap min binar

6.4 Operaţii cu heap-uri binare.

64
Operaţiile care se execută asupra unui heap sunt:
 Ştergerea max sau a min într-un Heap-Max respectiv Heap Min
 Creşterea sau descreşterea unei chei într-un Heap Max respectiv Heap Min
 Inserarea unei noi chei în heap
 Reuniunea a două heap-uri
Păstrarea poprietăţii de max sau min într-un Heap se face cu procedura de heapificare
aplicată nodului a cărui cheie încalcă proprietatea de heap.
Heapificarea constă în secvenţa de paşi:
P1- determin maximul dintre fii chei date
P2- schimb cheia dată cu maximul găsit
Paşii se vor repeta până când cheia dată devine frunză sau nu mai încalcă proprietatea de
heap.

Exemplu
Începem cu următorul arbore

Începând de la sfârşit spre început se determină cheia care încalcă proprietatea de


heap. Se calculează maximul dintre cheile fii:
Max(14,7)=14
Apoi se face schimbul dintre cheia de heapificat şi maximul determinat la pasul
anterior (14 şi 4), vezi exemplul următor.
Exemplu

65
Nodul cu cheia 4 încalcă proprietatea de heap
Max(2,8)=8
Se schimbă locul cheilor 8 şi 4

Exemplu

Nodul cu cheia 4 a devenit frunză, deci s-a terminat heapificarea arborelui dat.

Să ne reamintim...
Dacă acest arbore binar are proprietatea că pentru orice A şi B, dacă B este
copilul lui A atunci cheia(A) ≥ cheia(B) se numeşte heap Max.
Heap Min este structura de date de tip arbore care are proprietatea că pentru
orice A şi B, dacă B este copilul lui A atunci cheia(A) ≤ cheia(B).

Efectuaţi heapificarea unui vector.

Se poate observa că timpul de execuţie al heapificării depinde de înălţimea nodului în

 2 
arbore. În heap pentru orice înălţime h avem  h 1  noduri de înălţime h. Cunoscând aceasta
2 
putem calcula timpul de execuţie.
h   log 2 n 
 n   h   log 2 n  h 
T ( n)    2 h 1   O(h)  O n  2 h 
h 0  h 0 

66
h   log 2 n  1
h  h 2 2
  h 
 
Dar, , aşadar algoritmul de heapificare este de complexitate
h 0 2 h 0 2 1  1 2
h

2
O(n).

HEAPIFY(A ,i)
L = 2*i
R = 2*i + 1
Dacă L <= HeapL(A) şi A(L) > A(i) atunci
Imax = L
altfel
Imax = i
Sfârşitdacă
Dacă R <= HeapL(A) şi A(R) > A(imax) atunci
Imax=R
Sfârşitdacă
Dacă Imax  I atunci
A(i)  A(imax)
Sfârşitdacă
Cheamă HEAPIFY(A, Imax)
Return

Structura de Heap este foarte utilă. HeapSort-ul este un excelent algoritm de sortare.
Folosim, pentru sortare algoritmul de heapificare şi cel de construcţie a unui heap, în modul
următor:

HeapSort(a, n)
ConstruieşteHeap(a, n)
Pentru i = n, 2,−1
a(1) ↔ a(i)
Heapify(a, i − 1, 1)
Sfârşitpentru
Return

67
Sortarea cu HeapSort se face cu complexitatea
O(n) + nO(log2 n) =O(n log2 n).
Heapsort este un excelent algoritm de sortare, dar o implementare bună a QuickSort–ului
duce la sortări mai rapide. Heap–ul este însă foarte util în ţinerea în evidenţă dinamică a
cozilor de priorităţi unde o complexitate de n care s–ar putea obţine printr–un algoritm cu
inserţie este înlocuită cu o complexitate de logn păstrând coada într–un heap. Cea mai
utilizată aplicaţie a unui Heap este coada de priorităţi.
6.5 Coada de priorităţi.
Coada de priorităţi este o structură de date care păstrează elementele unei mulţimi S în
care fiecărui element îi este asociată o valoare numită prioritate.
Operaţii asupra unei cozi de priorităţi:
1) Introducerea unui element x în S - Insert(S,x)
2) Determinarea elementului cu cea mai mare cheie- Maxim(S)
3) Extragerea elementului cu cea mai mare cheie -Extract_Max(S)
Una dintre aplicaţiile cozii de priorităţi este gestionarea proceselor în programarea
partajată. Coada de priorităţi păstrează lista proceselor care trebuie să fie efectuate şi
priorităţile acestora. Când un proces s-a încheiat sau s-a întrerupt se introduce un nou proces,
alegerea acestuia se face în funcţie de prioritatea ataşată. Deci se va folosi Extract_Max(S)
pentru alegerea procesului cu cea mai mare prioritate şi Insert(S ,x) pentru a-l introduce în
lucru. O coadă de priorităţi poate fi folosită şi în simularea conducerii evenimentelor.
Algoritmii care implementează operaţiile de extragere şi inserare asupra unei cozi.

Extract_Max(A,max)
Daca HeapL(A) < 1 atunci
EROARE “ heap vid”
Sfârşitdacă
max = A(l)
A(l) = A(HeapL(A) )
HeapL(A) = HeapL(A) - 1
Cheamă Heapify(A,l)
Return

68
Evident că, deoarece heapul s-a stricat doar la vârf, Heapify(A, l) va parcurge doar o
singură dată arborele de la rădăcină la o frunză, deci complexitatea va fi O(lg n).

Insert(A,cheie)
HeapL(A) = HeapL(A) + 1
i= HeapL(A)
Atât timp cât i> 1 şi A(Par(i)) < cheie
A(i) = A(Par(i))
i= Par(i)
A(i) = cheie
Sfârşitciclu

Această procedură va parcurge doar o singură dată arborele de la rădăcină la o frunză, deci
complexitatea va fi O(lg n).

Exemplu

Figura ilustrează operaţia Insert asupra Heap Max-ului din exemplul anterior
în care s-a inserat un nod cu cheia 15.

Inseraţi, în acest exemplu, nodul cu cheia 40.

6.6 Rezumat
Am văzut cum poate fi folosit heapul la sortare şi la coadă de priorităţi.
arbore binar are proprietatea că pentru orice A şi B, dacă B este copilul lui A
atunci cheia(A) ≥ cheia(B) se numeşte heap Max.

Heap Min este structura de date de tip arbore care are proprietatea că pentru orice A
şi B, dacă B este copilul lui A atunci cheia(A) ≤ cheia(B).

69
6.7. Test de autoevaluare a cunoştinţelor
6.7. 1. Cum se obţine un Heap Max din şirul (5, 3, 2, 1, 10, 4, 15, 11, 9, 6).
6.7. 2. Arătaţi cum se sortează şirul de mai sus cu Heapsort.
6.7. 3. Inseraţi (Ins) şi scoateţi (Scot), pe rând, într-o coadă de priorităţi elementele:
Ins 3, Ins 2, Ins 4 Scot, Ins 7, Ins1, Scot, Ins 2.
Arătaţi evoluţia heap-ului sub formă de arbore binar.
Rezultatele le găsiţi la sfârşit, la pag 112.

Unitatea de învăţare 7. Heapuri binomiale..

7.1 Introducere
Am văzut în structurile anterioare că tutem face operaţii de căutare, inserare şi
ştergere cu complexitate foarte bună. Vom arătra, în aceasă lecţie, cum arată o
structură care fce reuniuni de structuri în timp optim.

70
Heap-ul binomial este o reuniune de arbori binomiali în care:
 fiecare subarbore binomial îndeplineşte şi condiţia de heap (min sau
max).
 există cel mult un arbore binomial a cărui rădăcină are un grad dat
(adică nu pot exista doi arbori binomiali de acelaşi grad).

7.2 Competenţe
La sfârşitul acestei unităţi de învăţare studenţii vor fi capabili să:
Descrie un arbore binomial
Facă operaţii de
 Creare
 Inserare
 Ştergere
 Reuniune
 Divizare
Pentru un heap biomial

Durata medie de studiu individual


Parcurgerea de către studenţi a acestei unităţide învîţare se face în 2 ore.

7.3 Arbori binomiali.


Deoarece un heap binomial este o colecţie de arbori binomiali, vom prezenta mai intâi
arborii binomiali şi demonstra unele proprietăţi esenţiale ale acestora. Arborele binomial B k
este un arbore ordonat definit recursiv. După cum se vede în figură, arborele binomial B 0
constă dintr-un singur nod. Arborele binomial Bk constă din doi arbori binomiali Bk-1 care sunt
înlănţuiţi: rădăcina unui dintre ei este fiul situat cel mai în stânga rădăcinii celuilalt arbore.
Figura prezintă arborii binomiali de la B0 la B4.

Lema următoare conţine câteva proprietăţi ale arborilor binomiali.


Arborele binomial Bk are:
1. 2k noduri,
2. înălţimea k,
3. exact noduri,
 k  la adâncimea i, pentru i=0,1,…,k.

i

 

71
4. rădăcina de grad k, grad mai mare decât al oricărui alt nod; mai mult, dacă fii rădăcinii sunt
numerotaţi de la stânga spre dreapta prin k-1, k-2,…,0 atunci fiul i este rădăcina subarborelui
Bi .
Demonstraţie
Demonstraţia este inductivă în raport cu k. Pasul iniţial pentru fiecare proprietate îl constituie
arborele binomial B0. Verificare prorpietăţilor pentru B0 este imediată. Presupunem că lema
are loc pentru arborele Bk-1.

Faceţi demonstraţia prin inducţie a proprietăţilor arborilor binari.

Corolar
Gradul maxim al nodurilor unui arbore binomial având n noduri este lg n.
Demonstraţie
Rezultă imediat din prorietăţile 1 şi 4 ale lemei de mai sus.
Proprietatea 3 a lemei justifică termenul de arbore binomial prin faptul că k sunt
 
coeficienţii binomiali.  
i
7.4 Heap-uri binomiale
Un heap binomial H este format dintr-o mulţime de arbori binomiali care satisfac următoarele
proprietăţi de tip binomial.
1. Fiecare arbore binomial din H satisface proprietatea de ordonare a unui heap: cheia unui
nod este mai mare sau egală decât cheia părintelui său.
2. Există cel mult un arbore binomial în H a cărui rădăcină are un grad dat.
Conform primei proprietăţi, rădăcina unui arbore cu proprietatea de heap ordonat, conţine cea
mai mică cheie din arbore.
Proprietatea a doua implică faptul că un heap binomial H având n noduri conţine cel
mult [lg n]+1 arbori binomiali. Pentru o justificare a acestei afirmaţii se observă că
reprezentarea binară a lui n are [lg n]+1 biţi, fie aceştia <b [lg n], b[lg n]-1,…,b0>, astfel încât
n   i  0 bi 2i . Din proprietatea 1 a lemei de mai sus rezultă că arborele binomial B i apare în
[lg n ]

H dacă şi numai dacă bitul bi=1. Astfel heap-ul H conţine cel mult [lg n]+1 arbori binomiali.

= Exemplu

72
În figura de mai jos este prezentat un heap binomial H având 13 noduri. Reprezeantarea binară a numărului 13 este 1101, iar H
conţine arborii binomiali cu proprietatea de heap B3, B2 şi B0 având 8, 4 şi respectiv un nod, în total fiind 13 noduri.

.Construiţi un heap binomial cu 15 noduri.

Reprezentarea heap-urilor binomiale


După cum ilustrează şi exem plul de mai sus, fiecarea arbore binomial al unui heap
binomial este memorat conform reprezentării stânga-fiu, dreapta-frate. Fiecare nod are un
câmp cheie plus alte informaţii specifice aplicaţiei care foloseşte heap-ul. În plus, fiecare nod
x conţine pointerii p[x] spre părintele lui, fiu[x] spre fiul situat cel mai în stânga şi frate[x]
spre fratele lui x, situat imediat în dreapta. Dacă nodul x este o rădăcină atunci p[x]=NIL.
Dacă nodul x nu are fii atunci fiu[x]=NIL, iar dacă x este fiu situat cel mai în dreapta, atunci
frate[x]=NIL. Fiecare nod conţine de asemenea câmpul grad[x], care reprezintă numărul fiilor
lui x.
Rezultă din figură că rădăcinile arborilor binomiali conţinuţi de un heap binomial sunt
păstrate într-o listă înlănţuită pe care o vom numi în continuare listă de rădăcini. La o
traversare a listei de rădăcini gradul rădăcinilor formează un şir strict crescător. Din a doua
proprietate de heap binomial, rezultă că gradele rădăcinilor unui heap binomial având n
noduri formează o submulţime a mulţimii {0,1,…,[lg n]}. Câmpul frate are semnificaţii
diferite după cum nodurile sunt rădăcini sau nu. Dacă x este rădăcină atunci frate[x] referă

73
rădăcina următoare în lista de rădăcini. (dacă x este ultima rădăcină din listă atunci, ca de
obicei, frate[x]=NIL.)
Un heap binomial dat H este referit prin pointerul cap[H] spre prima rădăcină din lista
de rădăcini a lui H. Dacă heap-ul binomial H nu are elemente, atunci cap[H]=NIL.

Operaţii pe heap-uri binomiale

Crearea unui heap binomial nou

Pentru a crea un heap binomial vid, procedura CREEAZĂ-HEAP-BINOMIAL va


aloca şi returna un obiect H, pentru care cap[H]=NIL. Timpul de execuţie este (1).

Găsirea cheii minime

Procedura HEAP-BINOMIAL-MIN returnează un pointer y la nodul cu cea mai mică


cheie dintr-un heap binomial H având n noduri. Această implementare presupune că nu există
chei cu valoarea .
HEAP-BINOMIAL-MIN(H,y)
1: y=NIL
2: x=cap[H]
3: min=
4: cât timp xNIL execută
5: dacă cheie[x]<min atunci
6: min=cheie[x]
7: y=x
8: sfârşit daca
9: y=frate[x]
10: sfârşit cât timp
11: return
Cheia minimă a unui heap binomial se află într-o rădăcină deoarece este un heap
ordonat. Procedura HEAP-BINOMIAL-MIN verifică toate rădăcinile (în număr de cel mult
[lg n]+1) şi reţine minimul curent în min, respectiv un pointer la acest minim în y. Apelată
pentru heap-ul binomial dinexemplul de mai sus, procedura va returna un pointer la nodul
care conţine cheia 1.
Timpul de execuţie al procedurii HEAP-BINOMIAL-MIN este O(lg n) deoarece
există cel mult [lg n]+1 rădăcini verificate.

Reuniunea a două heap-uri binomiale

Operaţia de reuniune a două heap-uri binomiale este folosită de aproape toate celelalte
operaţii rămase. Procedura HEAP-BINOMIAL-REUNEŞTE înlănţuie repetat arborii
binomiali care au rădăcini de acelaşi grad. Procedura următoare leagă arborele B k-1 având
nodul rădăcină y la arborele Bk-1 având nodul rădăcină z; mai precis, z va fi părintele lui y.
Nodul z devine astfel rădăcina unui arbore Bk.
BINOMIAL-LEGĂTURĂ(y,z)
1: p[y]=z
2: frate[y]=fiu[z]
3: fiu[z]=y
4: grad[z]=grad[z]+1
5: return

74
Procedura BINOMIAL-LEGĂTURĂ plasează nodul y în capul listei înlănţuite care
conţine fiii nodului z într-un timp O(1). Reprezentarea stânga-fiu, dreapta-frate a fiecărui
arbore binomial asigură succesul acestei proceduri deoarece fiecare arbore binomial are
proprietatea de ordonare a arborelui: fiu cel mai din stânga al rădăcinii unui arbore B k este
rădăcina unui arbore Bk-1.
Procedura HEAP-BINOMIAL-REUNEŞTE reuneşte două heap-uri binomiale H1 şi H2
şi returnează heap-ul rezultat. Pe parcursul efectuării operaţiei, reprezentările heap-urilor H1 şi
H2 sunt distruse. Procedura foloseşte pe lângă procedura BINOMIAL-LEGĂTURĂ încă o
procedură auxiliară ANSAMBLU-BINOMIAL-INTERCLASEAZĂ, care interclasează listele
de rădăcini ale heap-urilor H1 şi H2 într-o singură listă simplu înlănţuită ordonată crescător
după gradul nodurilor.

Exemplu

Iată un exemplu de reuniune

75
.Faceţi, similar, un exemplu de reuniune.

Procedura HEAP-BINOMIAL-REUNEŞTE se desfăşoară în două faze. În prima fază se


interclasează (prin apelul HEAP-BINOMIAL-INTERCLASEAZĂ) listele de rădăcini ale
heap-urilor binomiale H1 şi H2 într-o listă simplu înlănţuită H care este ordonată crescător în
raport cu gradul nodurilor rădăcină. Lista formată poate conţine cel mult două rădăcini cu
acelaşi grad. Astfel, în faza a doua sunt unite toate rădăcinile care au acelaşi grad, astfel încât
să nu existe două noduri cu acelaşi grad. Deoarece lista înlănţuită H este ordonată după grad,
operaţiile de înlănţuire din faza a doua sunt efectuate rapid.
Detaliem cele două fraze ale procedurii. Liniile 1-3 încep prin interclasarea celor două
liste ale heap-urilor binomiale H1 şi H2 într-o singură listă de rădăcini H. Listele de rădăcini
ale lui H1 şi H2 sunt ordonate strict crescător după grad, iar HEAP-BINOMIAL-
INTERCLASEAZĂ returnează o listă de rădăcini H, ordonată crescător după grad. Dacă
listele H1 şi H2 au împreună m noduri, atunci timpul de execuţie pentru HEAP-BINOMIAL-
INTERCLASEAZĂ este O(m), datorat examinării repetate a rădăcinilor din capul listelor şi
adăugării rădăcinii având gradul mai mic în lista de rădăcini rezultat, eliminând această
rădăcină din lista dată la intrare.
HEAP-BINOMIAL-REUNEŞTE(H1,H2,H)
1: Cheama CREEAZĂ-HEAP-BINOMIAL(H )
2: Cheama HEAP-BINOMIAL-INTERCLASEAZĂ(H1,H2,H)
3: eliberează obiectele H1,H2, dar nu şi listele referite de ele
4: dacă cap[H]=NIL atunci
5: return
6: sfârşit dacă
7: prec-x=NIL
8: x=cap[H]
9: urm-x=frate[x]
10: cât timp urm-xNIL
11: dacă (grad[x]grad[urm-x]) sau (frate[urm-x]NIL şi grad[frate[urm-x]]=grad[x]) atunci
11: prec-x=x cazurile 1 şi 2
12: x=urm-x  cazurile 1 şi 2
13: altfel
14: dacă cheie[x]cheie[urm-x] atunci
15: frate[x]=frate[urm-x]  cazul 3
16: BINOMIAL-LEGĂTURĂ(urm-x,x)  cazul 3
17: altfel
18: dacă prec-x=NIL atunci
19: cap[H]=urm-x  cazul 4
20: altfel
21: frate[prec-x]=urm-x  cazul 4
22: sfârşit dacă
23: BINOMIAL-LEGĂTURA(x,urm-x)  cazul 4
24: x=urm-x  cazul 4
25: sfârşit dacă
26: urm-x=frate[x]  cazul 4
27: sfârşit dacă
28: sfârşit dacă
29: sfârşit cât timp
30: return

76
În continuare procedura HEAP-BINOMIAL-REUNEŞTE iniţializează câţiva pointeri
în lista de rădăcini H. Dacă heap-urile binomiale date la intrare sunt vide, atunci în liniile 4-5
se iese din procedură. Începând cu linia 6 ne situăm în cazul în care H conţine cel puţin o
rădăcină. Din acest punct se păstrează 3 pointeri în lista de rădăcini:
- x indică rădăcina curentă examinată,
- prec-x indică rădăcina precedentă lui x în lista de rădăcini: frate[prec-x]=x,
- urm-x indică rădăcina următoare lui x în listă: frate[x]=urm-x.
H poate conţine iniţial cel mult două rădăcini cu un grad dat: deoarece H 1 şi H2 sunt heap-uri
binomiale, ele nu au două rădăcini având acelaşi grad. Mai mult, procedura
HEAP-BINOMIAL-INTERCLASEAZĂ ne garantează că dacă H conţine două rădăcini
având acelaşi grad, atunci ele sunt adiacente în lista de rădăcini.
În timpul execuţiei procedurii HEAP-BINOMIAL-REUNEŞTE, de fapt, pot exista 3
rădăcini având acelaşi grad. Vom vedea când se produce această situaţie. La fiecare iteraţie a
ciclului cât timp din liniile 9-24 se decide dacă se poate lega x şi urm-x în funcţie de gradul
lor şi de gradul lui frate[urm-x]. Un invariant al acestui ciclu este faptul că la fiecare reluare a
corpului ciclului atât x cât şi urm-x sunt diferiţi de NIL.

77
Cazul 1, prezentat în figura a se produce atunci când grad[x]grad[urm-x], adică x este
rădăcina unui arbore Bk şi urm-x este rădăcina unui arbore Bl pentru un l>k. Această situaţie
este tratată în liniile 11-12. Deoarece nu trebuie să legăm x şi urm-x, nu rămâne decât să
deplasăm pointerii în listă. Actualizarea pointerului urm-x pentru a referi nodul ce urmează
noului nod x este efectuată în linia 24, deoarece aceasta este comună tuturor cazurilor.
Cazul 2, prezentat în figura b, are loc atunci când x este prima rădăcină din cele 3 care
au acelaşi grad, adică atunci când grad[x]=grad[urm-x]=grad[frate[urm-x]]
Acest caz este tratat similar cu cazul 1: efectuăm doar o deplasare a pointerilor în listă. Testul
din linia 10 este comun cazurilor 1 şi 2, la fel cum liniile 11-12 tratează amândouă cazurile.
Cazurile 3 şi 4 se produc atunci când x este prima rădăcină din 2 rădăcini succesive
având acelaşi grad, adică grad[x]=grad[urm-x]grad[frate[urm-x]].
Aceste cazuri apar la iteraţia următoare după fiecare caz, dar unul din ele urmează imediat
după cazul 2. În cazurile 3 şi 4 vom înlănţui x şi urm-x. Aceste cazuri diferă între ele după
cum x sau urm-x au cheia mai mică, fapt ce determină care din noduri va fi rădăcină în
procesul de legare a lor.
În cazul 3, prezentat în figura c, cheie[x]cheie[urm-x], astfel că urm-x va fi legat la
linia x. Linia 15 şterge urm-x din lista de rădăcini, iar în linia 16 urm-x devine fiul situat cel
mai în stânga lui x.
În cazul 4, prezentat în figura .d cheia mai mică o are urm-x, deci este legat la urm-x.
Liniile 17-21 şterg x din lista de rădăcini. Există două subcazuri, după cum x este (linia 19)
sau nu (linia 21) prima rădăcină din listă. În linia 22, x devine fiul situat cel mai în stânga lui
urm-x, iar linia 23 actualizează x pentru iteraţia următoare.
Pregătirea iteraţiei următoare a ciclului cât timp este aceeaşi pentru ambele cazuri 3 şi
4. x referă un arbore Bk+1 obţinut prin negarea a doi arbori B k. După operaţia
HEAP-BINOMIAL-INTERCLASEAZĂ în lista de rădăcini existau zero, unu sau doi arbori
Bk+1, deci x este acum prima rădăcină din lista de rădăcini pentru un număr de unu, doi sau trei
arbori Bk+1. În cazul existenţei unui singur arbore (x referindu-l pe acesta), la iteraţia
următoare se va produce cazul 1: grad[x]grad[urm-x]. Dacă x referă primul arbore din doi
existenţi atunci la iteraţia următoare are loc unul din cazurile 3 sau 4. În sfârşit, dacă x referă
primul arbore din trei existenţi atunci la iteraţia următoare are loc cazul 2.
Timpul de execuţie pentru HEAP-BINOMIAL-REUNEŞTE este O(lg n), unde n este
numărul total de noduri din heap-urile binomiale H1 şi H2. Justificăm acest rezultat după cum
urmează: fie n1 şi n2 numărul nodurilor heap-urilor H1 şi respectiv H2 astfel încât n=n1+n2.
Atunci numărul maxim de rădăcini conţinute de H 1 şi H2 este [lg n1]+1, respectiv [lg n2]+1.
Astfel imediat după apelul HEAP-BINOMIAL-INTERCLASEAZĂ, H conţine cel mult
[lg n1]+[lg n2]+22[lg n]+2=O(lg n) rădăcini. Rezultă că timpul de execuţie pentru
HEAP-BINOMIAL-INTERCLASEAZĂ este O(lg n). Fiecare iteraţie a ciclului cât timp se
execută într-un timp O(1) şi pot exista cel mult [lg n 1]+[lg n2]+2 iteraţii deoarece de la fiecare
iteraţie fie pointerii avansează cu o poziţie în lista H, fie se elimină o rădăcină din lista de
rădăcini. Astfel, timpul total de execuţie este O(lg n).

Inserarea unui nod

Procedura următoare inserează nodul x în heap-ul binomial H. Se presupune că nodul


x este creat şi câmpul cheie[x] este iniţializat.
HEAP-BINOMIAL-INSEREAZĂ(H,x)
1: Cheama CREEAZĂ-HEAP-BINOMIAL(H’ )
2: p[x]=NIL
3: fiu[x]=NIL
4: frate[x]=NIL

78
5: grad[x]=0
6: cap[H’]=x
7:Cheama HEAP-BINOMIAL-REUNEŞTE(H,H’,H)
8: return
Procedura creează un heap binomial H’ cu un nod într-un timp O(1) pe care îl reuneşte
apoi cu heap-ul binomial H având n noduri într-un timp O(lg n). Procedura
HEAP-BINOMIAL-REUNEŞTE eliberează spaţiul alocat heap-ului binomial temporar H’.

Extragerea nodului având cheia minimă

Procedura următoare extrage nodul având cheia minimă din heap-ul binomial H şi
returnează un pointer la nodul extras.
HEAP-BINOMIAL-EXTRAGE-MIN(H)
1: caută rădăcina x cu cheia minimă în lista de rădăcini şi şterge x din lista de rădăcini a lui H
2: Cheama CREEAZĂ-HEAP-BINOMIAL(H’)
3: inversează ordinea memorării fiilor lui x în lista înlănţuită asociată şi atribuie lui cap[H’]
capul listei rezultate
4: Cheama HEAP-BINOMIAL-REUNEŞTE(H,H’,H)
5: return

Exemplu

79
HEAP-BINOMIAL-EXTRAGE-MIN se execută într-un timp O(lg n) deoarece fiecare din
liniile 1-4 se execută într-un timp O(lg n).

Descreşterea unei chei

Procedura HEAP-BINOMIAL-DESCREŞTE-CHEIE(H,x,k)
1: dacă k>cheie[x] atunci
2: eroare “cheia nouă este mai mare decât cheia existentă”
3: sfârşit dacă
4: cheie[x]=k
5: y=x
6: z=p[y]
7: cât timp zNIL şi cheie[y]<cheie[z]
8: interschimbă cheie[y]cheie[z]
9:  dacă y şi z au şi alte câmpuri atunci interschimbă şi aceste câmpuri
10: y=z
11: z=p[y]
12: sfârşit cât timp
Această procedură descreşte o cheie în mod similar cu metoda aplicată pentru un heap
binar: prin “ridicarea” cheii în heap. După ce procedura se asigură că noua cheie nu este mai
mare decât cea curentă şi apoi actualizează cheia curentă a lui x, urmează un proces de căutare
în sus, iar y referă iniţial nodul x. La fiecare iteraţie a ciclului cât timp, în liniile 6-10, se
compară cheie[y] cu cheia părintelui z a lui y.Dacă y este chiar rădăcina sau
cheie[y]cheie[z], atunci arborele binomial este un heap ordonat. În caz contrar nodul y
încalcă proprietatea de ordonare pentru heap, astfel cheile lui y şi z se interschimbă, împreună
cu alte informaţii, apoi procedura deplasează y şi z cu un nivel mai sus în arbore şi continuă
iteraţiile.
Timpul de execuţie HEAP-BINOMIAL-DESCREŞTE-CHEIE este O(lg n). Numărul
maxim de iteraţii pentru ciclul cât timp (liniile 6-10) este [lg n] deoarece, din proprietatea 2 a
lemei enunţate mai sus rezultă că înălţimea maximă a lui x este [lg n].

Exemplu

80
Ştergerea unei chei

Ştergerea cheii şi a altor informaţii asociate unui nod x aparţinând unui heap binomial
H se poate desfăşura fără dificultate într-un timp O(lg n). Implementarea următoare presupune
că nodurile din heap-ul binomial nu au chei având valoarea -.
HEAP-BINOMIAL-ŞTERGE(H,x)
1: HEAP-BINOMIAL-DESCREŞTE-CHEIE(H,x,-)
2: HEAP-BINOMIAL-EXTRAGE-MIN(H)
După ce în procedura HEAP-BINOMIAL-ŞTERGE se atribuie valoarea - cheii
nodului x, acesta devine nodul având cheia minimă în heap-ul binomial. Urmează apoi ca
această cheie şi eventual alte informaţii asociate să fie ridicate până la o rădăcină prin apelul
HEAP-BINOMIAL-DESCREŞTE-CHEIE. Această rădăcină este apoi eliminată din H prin
apelul HEAP-BINOMIAL-EXTRAGE-MIN.
Timpul de execuţie pentru HEAP-BINOMIAL-ŞTERGE este O(lg n).

7.6 Rezumat
B-arborii, care sunt arbori echilibraţi folosiţi la memorarea pe disc
magnetic. Deoarece discul magnetic operează mult mai încet decât memoria RAM,
performanţele B-arborilor vor fi măsurate nunumai prin timpul consumat cu

81
operaţiile de căutare dinamice, ci şi prin numărul de accese la disc efectuate. Pentru
fiecare operaţie numărul de accese la disc este proporţional cu înălţimea B-arborelui.
Heap-urile binomiale execută operaţiile: INSEREAZĂ, MINIMUM,
EXTRAGE-MIN şi REUNEŞTE în cazul cel mai defavorabil, în timp O(lg n), unde
n este numărul total de elemente din heap-ul de intrare (sau în cele două heap-uri de
intrare în cazul REUNEŞTE). Pe structura de date heap binomial se pot executa şi
operaţiile ŞTERGE şi DESCREŞTE-CHEIE.

7.7. Test de autoevaluare a cunoştinţelor


7.7.1. Construiţi prin inserări succesive heap-min-ul binomial având cheile 10, 1, 12,
25, 18
7.7.2. Ştergeţi minimul din heap-min-ul binomial dat în figura de mai jos.

Rezultatele le găsiţi la sfârşit, la pag 115.

82
Unitatea de învăţare 8 Structura datelor pe disc magnetic.

8.1 Introducere
De modul în care sunt păstrate datele pe memoria externă depinde
regăsirea informaţiei dorite în forma dorită într-un timp acceptabil. Dacă problema
formei se poate rezolva mai uşor, problema obţinerii datelor în timp util este mai
greu de rezolvat şi organizarea va fi subordonată rezolvării acestei probleme.

8.2 Competenţe
La sfârşitul acestei unităţi de învăţare studenţii vor fi capabili să:
 calculeze timpul de transfer al datelor
 organizeze optim fişierele

Durata medie de studiu individual


Parcurgerea de către studenţi a acestei unităţide învîţare se face în 2 ore.

8.3 Tipuri de fişiere pe disc


Memoria principală ese o memorie foarte rapidă care conţine programele şi datele,
transferate din memoria secundară cu care se lucrează la un moment dat; ea mai poate conţine
câtiva megabaiţi de date dar, în general, este prea mică pentru totalitatea datelor.
Memoria secundară este realizată fizic pe suport magnetic disc( mai des) şi bandă.
Discul magnetic este cel mai folosit pentru ca asigura un acces rapid la date şi poate realiza
accesul direct; banda magnetică deşi mult mai ieftină, este prea lentă şi se foloseşte mai des
pentru arhivare.
Partea de hard a calculatorului care rezolvă sarcinile de scriere-citire a dlscului
magnetic este unitatea de disc. În unitate se află un pachet de unul sau mai multe discuri pe
un ax comun într-o mişcare permanentă de rotaţie cu o mare viteză. În figură se poate observa
componenta discului cu faţa magnetizată organizată pe piste (cecuri concentrice), cu
mecanismul de acces care prin mulţimea de capete generează din pistele parcurse
concomitent de capete aşa numitul cilindru. Această structură fizică permite accesuI direct la
o anumită înregistrare (noţiune logică) dacă se specifică numarul de cilindru, numărul de
suprafaţă şi numărul de înregistrare.

83
8.4 Factorii de performanţă ai discului.
Timpul de cautare(A), este timpul necesar poziţionării dispozitivului de acces
(împreună cu capetele de citire-scriere) pe cilindrul cerut. În general mişcarea pâna la
cilindrul alăturat nu va dura la fel de mult ca mişcarea de la primul la ultimul cilindru. De
obicei pen~ acestt~mp se foloseşte o valoare medie dată de timpul poziţionare de la primul
cilimdru la mljlocul discului. 12 sau 20 de milisecunde sunt timpi tipici de căutare în funcţie
de modelul de unitate de disc.

84
Timpul de activare al capetelor este timpul necesar pentru a determina electronic
care din capetele de citire-scriere va fi activ (adică pe ce suprafaţă se va face operaţia de
intrare-ieşire) acest timp este în general foarte mic în comparaţie cu ceilalţi timpi şi se
neglijează în calcule.
Intervalul de rotaţie este timpul necesar discului în mişcare de rotaţie să ajungă la
blocul care trebuie citit sau scris astfel ca tranferul de date să poată începe. Acest interval
depinde de doi factori: viteza de rotaţie a discului şi poziţia relativă a noului bloc dată de
poziţia de moment a discului. Fizic acest timp poate varia între zero şi timpul de revoluţie al
discului; deci în medie se va consuma un timp egal cu R/2.
Rata de transfer al datelor (D) se referă la timpul necesar transferului datelor de pe
suprafaţa magnetică în memoria principală. Acesta este în funcţie de viteza de rotaţie a
discului şi de densitatea datelor inregistrate. Acest timp este în general exprimat în mii de
baiţi pe secundă. Timpul de transfer al datelor este timpul în care se speră să se ajungă la
adresă şi să se realizeze transferul; deci formula de calcul va fi:
T=A+R/2+L/D
unde A este timpul de căutare, R este timpul de revoluţie (rotaţie completă), L este lungimea
blocului în baiţi şi D este rata de transfer a datelor.

Exemplu de calcul pentru inregistrari accesate direct: Sa presupunem


că o instituţie are depuse datele pe un disc câte trei înregistrări per bloc, (factor
de blocare 3) şi fiecare înregistrare are 200 de baiţi. Rata de transfer a datelor este
de 806000 baiţi pe secundă. Timpul mediu de căutare este de 30 milisecunde.
Discul se roteşte cu 7200 rotaţii pe minut. Care va fi timpul de transfer al datelor?
Să fixăm mai întâi variabilele:
A=0.03 secunde
Viteza de revoluţie pe secundă va fi R=7200/60= 120 R=1/120=0.0083 secunde
R/2= 0.00415
L/D=600/806000=0.00074
Deci:
T=0.03+0.00415+0.00074=0.03489 secunde

Refaceţi calculul pentru factorul de blocare 4.

Să presupunem ca în loc de a accesa un bloc, ca în exemplul precedent, avem de


accesat un fişier cu plăţile făcute de la începutul lunii. Are sens să considerăm ca un astfel de
fişier este secvenţial umplut în ordinea în care se fac plăţile şi deci cilindri succesivi sunt
parcurşi pentru scrierea sau citirea unui asemenea fisier secvenţial. Se realizează, evident, în
acest fel o economie de mişcări ale capetelor de citire-scriere: de exemplu, dacă capetele se
afla la inceputul
fişierului, pe primul cilindru ocupat, timpul de căutare va fi nul sau va fi pus o singură dată,
pentru prima căutare, deci el poate fi ignorat. Vor fi numai mici mişcări la trecerea de la o
pistă la urmatoarea (pentru alinieri) care poate fi evaluată în medie cu parcurgerea a jumătate
de pistă. Pe o pistă nouă, o dată început transferul, blocurile pot fi transferate fără interval de

85
rotatie, deci dacă avem de parcurs 8 piste, vom avea numai de 8 ori intervalul de rotaţie,
indiferent de numărul de blocuri transferate.

Exemplu cu înregistrari accesate secvenţial Să presupunem, în


continuare, că trebuiesc transferate 1000 de blocuri de pe fiecare din cele 8 piste,
deci un total de 8000 de blocuri şi dacă factorul de blocaj este tot 3 asta însearnnă
24000 de înregistrări. Vom presupune, ca şi mai înainte, că fiecare înregistrare
are 200 de baiţi deci blocul va fi de 600 de baiţi. Dacă avem de accesat întregul
fişier atunci timpul mediu de acces pe înregistrare va fi:
Timpul total de citire a fişierului= 0.00415*8+0.00074*8000=5.9532, iar

T=5.9532/8000=0.0007415 secunde
Unde Teste timpul mediu de acces la o înregistrare.

Refaceţi calculul pentru factorul de blocare 4.

Să ne reamintim
Timpul de transfer al datelor este timpul în care se speră să se ajungă la
adresă şi să se realizeze transferul; deci formula de calcul va fi:
T=A+R/2+L/D
unde A este timpul de căutare, R este timpul de revoluţie (rotaţie completă), L este
lungimea blocului în baiţi şi D este rata de transfer a datelor.

8.5 Formate ale datelor memorate pe disc.


Formate de pistă. Datele se pot memora pe o pistă cu cheie sau fără cheie. Este
momentul aici să facem diferenţa între înregistrarea logică şi fizică; între orice două
înregistrări de pe o pistă apare un spaţiu ‘liber’, gap, care are o lungime variabilă determinată
de posibilitaţile hard de citire-scriere şi care, evident, ocupă loc pe suportul magnetic. Pentru a
micşora acest spaţiu ocupat neproductiv, se grupează mai multe înregistrări logice într-una
singură fizică pe pistă, grup care se numeşte bloc. Acolo unde nu există confuzie vom folosi
noţiunea de înregistrare şi pentru cea fizică şi pentru cea logică, dar cele două noţiuni nu
coincid decât când blocul conţine o singură înregistrare. Numărul de cilindru, numărul de cap
(de citire-scriere) şi numărul de înregistrare dau o adresă unică pe suportul magnetic pentru
fiecare înregistrare. Ceea ce se va citi sau scrie, la un moment dat, va fi o înregistrare fizică,
addică un bloc (cu probleme rezolvate de soft la sfârşit de fişier), iar ‘desfacerea’ blocului în
înregistrări logice este tot o sarcină a sistemului de operare. Dacă înregistrarea este blocată, cu
cheie atunci cheia înregistrarii fizice (care nu poate fi decât una) va fi cea mai mare cheie
dintre cheile din bloc.
Formate de inregistrare. Datele pot fi memorate, pe disc, într-unul din următoarele
patru formate:
Inregistrări de lungime fixă. Aşa cum spune şi denumirea apare atunci când
înregistrările logice sunt de lungime fixă, deci ele vor da naştere la înregistrări fizice de
lungime fixă blocate sau neblocate.

86
Atunci când înregistrările logice pot avea lungimi care diferă vom avea şi înregistrări
fizice de lugime variabilă (blocate sau nu).
Strucura acestor tipuri de înregistrări este prezentată în figura următoare.

(a) Fixe neblocate .

(b) Fixe blocate

(c) Variabile neblocate.

(d) Variabile blocate

8.5 Rezumat
Am văzut cum este organizat şi cum funcţionează un disc magnetic. Pentru a putea
calcula viteza de acces la înregistrări, avem nevoie de factorii de performanţă ai
discului. Aceştia sunt:
 Timpul de cautare(A),
 Timpul de activare al capetelor
 Intervalul de rotaţie

87
 Rata de transfer al datelor (D)
 timpul de revoluţie al discului (R)
Formula de calcul a timpului de acces este:
T=A+R/2+L/D

Am dat apoi exemple de calcul al timpilor de acces pentru cazul accesului


direct şi secvenţial.
În continuare am văzut care este formatul înregistrărilor în cazurile:
 Fixe neblocate
 Fixe blocate.
 Variabile neblocate.
 Variabile blocate

8.6.Test de autoevaluare a cunoştinţelor


8.6.1.
Să presupunem că o instituţie are depuse datele pe un disc câte patru înregistrări per
bloc şi fiecare înregistrare are 250 de baiţi. Rata de transfer a datelor este de 80000
baiţi pe secundă. Timpul mediu de căutare este de 20 milisecunde. Discul se roteşte
cu 7200 rotaţii pe minut. Care va fi timpul de transfer al datelor în acces direct?
8.6.2.
În aceleaşi condiţii de hard, să presupunem că trebuiesc transferate 1000 de blocuri
de pe fiecare din cele 8 piste, deci un total de 8000 de blocuri. Care va fi timpul de
transfer al datelor în acces secvenţial?
Rezultatele le găsiţi la sfârşit, la pag 116.

88
Unitatea de învăţare 9 Structura relaţională

1.1 Introducere
În cadrul bazelor de date relaţionale, datele sunt organizate sub forma unor tablouri
bidimensionale (tabele) de date, numite relaţii. Asocierile dintre relaţii se
reprezintă explicit prin atribute de legătură. Aceste atribute figurează într-una din
relaţiile implicate în asociere (de regulă, în cazul legăturilor de tip "unu la mulţi")
sau sunt plasate într-o relaţie distinctă, construită special pentru exprimarea
legăturilor între relaţii (în cazul legăturilor de tip "mulţi la mulţi"). O bază de date
relaţională (BDR) reprezintă un ansamblu de relaţii, prin care se reprezintă atât
datele cât şi legăturile dintre date.

1.2 Competenţe
La sfârşitul acestei unităţi de învăţare studenţii vor fi capabili să:
 descrieţi structura relaţională a unei baze de date

Durata medie de studiu individual


Parcurgerea de către studenţi a acestei unităţide învîţare se face în 2 ore.

Operatorii modelului relaţional. Definesc operaţiile care se pot efectua asupra relaţiilor, în
scopul realizarii funcţiilor de prelucrare asupra bazei de date, respectiv consultarea, inserarea,
modificarea şi ştergerea datelor.
Restricţiile de integritate ale modelului relaţional. Permit definirea stărilor
coerente ale bazei de date.
În continuare, vor fi prezentate pe larg aceste componente.

9.4 Structura relaţionala a datelor


Prezentarea structurii relaţionale a datelor impune definirea noţiunilor de: domeniu,
relaţie, atribut şi schemă a unei relaţii.
Domeniul reprezintă un ansamblu de valori, caracterizat printr-un nume. Un domeniu
se poate defini explicit, prin enumerarea tuturor valorilor apartinând acestuia sau implicit, prin
precizarea proprietăţilor pe care le au valorile din cadrul domeniului respectiv.
Să considerăm, de exemplu domeniile D1, D2, D3, definite astfel:
D1: ("F","M")
D2 : (x / x aparţine N, x aparţine [0,100])
D3 :(s/s=şir de caractere)
În cazul lui D1 s-a recurs la o definire explicită, în timp ce pentru D2 şi D3 s-a utilizat
definirea implicită.
Pentru un ansamblu de domenii D1, D2, ..., Dn produsul catezian al acestora
reprezintă ansamblul tuplurilor <v1, v2, ..., vn>, unde: v1 este o valoare apartinând
domeniului D1, v2 este o valoare din D2 s.a.m.d.

89
Exemplu
De exemplu, tuplurile: <"Maria", "F", 50>, <"Vasile", "M",15>,
<"Vasile","M",20>, <"Vasile", "F",100> aparţin produsului cartezian: D3 x D1 x
D2

Daţi alte exemple de triplete care aparţin produsului cartezian: D3 x D1 x D2

Relaţie
Să presupunem că se acordă o anumită semnificaţie valorilor domeniilor D1, D2, D3,
definite anterior.
Să considerăm, de exemplu ca D1 cuprinde valorile referitoare la sexul unei persoane,
D2 conţine valori care exprimă vârsta unei persoane şi D3 cuprinde numele unor persoane.
Numai unele dintre tuplurile produsului cartezian: D3 x D1 x D2 pot avea o
semnificaţie şi anume cele care conţin numele, sexul şi vârsta aceleiaşi persoane.
Dintre cele 202 tupluri care au valoarea "Vasile" pe prima pozitie, numai unul poate avea o
semnificaţie, dacă presupunem că există o singură persoană cu acest nume.
Se desprinde de aici necesitatea definirii unei submulţimi de tupluri, din cadrul
produsului cartezian al domeniilor, submulţime care să cuprindă numai tuplurile cu
semnificaţie.
Relaţia reprezintă un subansamblu al produsului cartezian al mai multor domenii,
subansamblu caracterizat printr-un nume şi care conţine tupluri cu semnificatie. Considerând
de exemplu că nu se cunosc decât două persoane definim realţia R prin tuplurile care descriu
aceste persoane şi anume:
R : (<"Maria", "F", 30>, <"Vasile", "M", 35>)
Într-o relaţie, tuplurile trebuie să fie distincte (nu se admit duplicări ale tuplurilor) .
O reprezentare comodă a relaţiei este tabelul bidimensional (tabela de date în care
liniile reprezintă tuplurile, iar coloanele corespund domeniilor

Exemplu

Relaţie reprezentată sub forma unei tabele de date

Completaţi tabelul cu încă două linii.

Reprezentarea tabelară este preferată adesea altor forme de reprezentare a relaţiilor,


întrucât este uşor de înţeles şi de utilizat.
În prezentarea conceptului de relaţie se recurge uneori la analogii cu alte concepte,
extrem de bine cunoscute în domeniul prelucrării automate a datelor precum cel de fişier.

90
Relaţia poate avea semnificaţia unui fişier, tuplul poate fi considerat drept o înregistrare, iar
valorile din cadrul tuplului pot fi interpretate drept valori ale câmpurilor de înregistrare.
În cadrul modelului relaţional nu interesează decat relaţiile finite, chiar dacă în
construirea relaţiilor se admit domenii infinite. Numărul tuplurilor dintr-o relaţie reprezintă
cardinalul relaţiei, în timp ce numărul valorilor dintr-un tuplu defineşte gradul relaţiei.

Atribut
În timp ce tuplurile dintr-o relaţie trebuie să fie unice un domeniu poate apare de mai
multe ori în produsul cartezian pe baza căruia este definită relaţia.
Să considerăm, de exemplu că pentru o persoana dispunem de urmatoarele date:
nume,sex, vârsta şi numele soţului/soţiei.
O posibilitate de organizare a acestor date o reprezintă relaţia din exemplul următor.

Exemplu
R: D3 D1 D2 D3
“Maria” “F” 30 “Ion”
“Vasile” “M” 35 “Mia”
Relaţia PERS

Completaţi tabelul cu încă două linii.

Relaţia PERS reprezintă un subansamblu al produsului cartezian:


D3 x D1 x D2 x D3.
Semnificaţia valorilor din cadrul unui tuplu se stabileşte în acest caz nu numai pe baza
domeniului de care aparţin valorile, ci şi în funcţie de poziţia ocupată în cadrul tuplului.
Dependenţa faţă de ordine a datelor înseamnă o reducere a flexibiltăţii organizării datelor.
Într-o organizare eficientă, flexibilă, ordinea liniilor şi a coloanelor din cadrul tabelei de date
nu trebuie să prezinte nici o importanţă. Pentru a diferenţia coloanele care conţin valori ale
aceluiaşi domeniu şi a elimina astfel dependenţa de poziţie în cadrul tabelei se asociază
fiecarei coloane un nume distinct, ceea ce duce la apariţia noţiunii de atribut.
Atributul reprezintă coloana unei tabele de date, caracterizată printr-un nume.
Numele coloanei (atributului) exprimă de obicei semnificaţia valorilor din cadrul coloanei
respective.
Schema unei relaţii
Prin schema unei relaţii se întelege numele relaţiei, urmat de lista atributelor, pentru
fiecare atribut precizându-se domeniul asociat. Astfel, pentru o relaţie R, cu atributele A1, A2,
..., An şi domeniile: D1, D2,..., Dm, cu m <= n, schema relaţiei R poate fi reprezentată într-
una din formele prezentate

R(A1:D1, …, An:Dm) sau R(A1:D1, …, An:Dm) sau

A1:D1 … An:Dn

A1:D1 … An:Dn

91
9.6 Rezumat
Am aflat că un atribut este un nume dat unei coloane, nume sugestiv pentru
semnificaţia coloanei. Valorile unui atribut pot fi într-un domeniu care defineşte o
restricţie.Un tuplu este o linie într-un table în care atributele îşi au valorile lor.
Mulţimea tuplelor de aceeaşi formă formează o relaţie.

9.7 Test de autoevaluare a cunoştinţelor


9.7.1 Definiţi schema relaţiei student.
9.7.2 Definiţi schema relaţiei note.
9.7.3 Ce fel de relaţie este între student şi note.
9.7.4 Definiţi schema relaţiei facultate.
9.7.5Ce fel de relaţie este între student şi facultate.
9.7.6 Definiţi schema relaţiei materii.
Rezultatele le găsiţi la sfârşit, la pag 116.

Unitatea de învăţare 10 Algebra relaţională.

92
10.1 Introducere
O bază de date relaţională (BDR) reprezintă un ansamblu de relaţii, prin care se
reprezintă atât datele cât şi legăturile dintre date. Limbajul care se foloseşte pentru
a exprima cereri la baza de date este SQL. La baza limbajului SQL stă algebra
relaţională.
E. F. Codd a introdus algebra relaţionala (AR) cu operaţii pe relaţii, fiecare
operaţie având drept operanzi una sau mai multe relaţii şi producând ca rezultat o
altă relaţie.
Unele operaţii ale AR pot fi definite prin intermediul altor operaţii. În acest
sens, putem vorbi de:
- operaţii de bază, precum: reuniunea, diferenţa, produsul cartezian etc.
- operaţii derivate, ca: intersecţia, diviziunea etc.
Codd a introdus aşa numita AR standard, constituită din 6 operaţii de bază:
reuniunea, diferenţa, produsul cartezian, proiecţia, selecţia şi joncţiunea precum şi
din două operaţii derivate: intersecţia şi diviziunea.
Ulterior, la operaţiile AR standard au fost adăugate şi alte operaţii, aşa
numitele operaţii "adiţionale" sau extensii ale AR standard, precum:
complementara unei relaţii, splitarea (spargerea) unei relaţii, închiderea tranzitivă
etc.

10.2 Competenţe
La sfârşitul acestei unităţi de învăţare studenţii vor fi capabili să:
Definiţi cereri la baza de date în cadrul algebrei relaţionale.

Durata medie de studiu individual


Parcurgerea de către studenţi a acestei unităţide învîţare se face în 3 ore.

10.3 Operatorii modelului relaţional


Modelul relaţional oferă două colecţii de operatori pe relaţii şi anume:
- algebra relaţională;
- calculul relaţional.
La rândul sau, calculul relaţional este de două tipuri:
- calcul relaţional orientat pe tuplu;
- calcul relaţional orientat pe domeniu.
Ne limităm, în cele ce urmează, la elemente de algebră relaţională.
Algebra relaţională şi extensiile sale
E. F. Codd a introdus algebra relaţionala (AR) cu operaţii pe relaţii, fiecare operaţie
având drept operanzi una sau mai multe relaţii şi producând ca rezultat o altă relaţie.
Unele operaţii ale AR pot fi definite prin intermediul altor operaţii. În acest sens,
putem vorbi de:
- operaţii de bază, precum: reuniunea, diferenţa, produsul cartezian etc.
- operaţii derivate, ca: intersecţia, diviziunea etc.

93
Codd a introdus aşa numita AR standard, constituită din 6 operaţii de bază: reuniunea,
diferenţa, produsul cartezian, proiecţia, selecţia şi joncţiunea precum şi din două operaţii
derivate: intersecţia şi diviziunea.
Ulterior, la operaţiile AR standard au fost adăugate şi alte operaţii, aşa
numitele operaţii "adiţionale" sau extensii ale AR standard, precum:comple-
mentara unei relaţii, splitarea (spargerea) unei relaţii, închiderea tranzitivă etc.
În continuare vor fi prezentate principalele operaţii ale AR, precum şi modul lor de
utilizare.
1. Reuniunea. Reprezintă o operaţie a AR definită pe doua relaţii: R1 şi R2 ambele cu
o aceeaşi schemă, operaţie care constă din construirea unei noi relaţii R3, cu schema identică
cu R1 şi R2 şi având drept extensie tuplurile din R1 şi R2 luate impreună o singură dată.
Notaţia uzuală pentru reuniune este: R1 U R2
Reprezentarea grafică a reuniunii este prezentata în exemplu următor.

Exemplu

Reuniunea relaţiilor ORAŞE şi MUNICIPII

.Daţi un exemplu de reuniune între două grupe de studenţi.

Să ne reamintim...
Reuniunea este o operaţie definită pe doua relaţii: R1 şi R2 ambele cu o aceeaşi
schemă, operaţie care constă din construirea unei noi relaţii R3, cu schema identică
cu R1 şi R2 şi având drept extensie tuplurile din R1 şi R2 luate impreună o singură
dată.

Diferenţa. Reprezintă operaţie din AR definită pe doua relaţii: R1 şi R2, ambele cu


aceeaşi schemă, operaţia constând din construirea unei noi relaţii R3, cu schema identică cu a
operanzilor şi cu extensia formată din acele tupluri ale relaţiei R1 care nu se regăsesc şi în
relaţia R2.
Notaţia uzuală pentru operaţia de diferenţă a doua relaţii este: R1-R2
Prezentăm un exemplu de diferenţă a doua relaţii.

94
Exemplu

Diferenţa relaţiilor ORAŞE şi MUNICIPII

Daţi un exemplu de diferenţă între o grupă de studenţi şi cadre didactice (se va


ţine cont că un student la master poate fi şi preparator).

Să ne reamintim...
Diferenţa este o operaţie definită pe doua relaţii: R1 şi R2, ambele cu
aceeaşi schemă, operaţia constând din construirea unei noi relaţii R3, cu schema
identică cu a operanzilor şi cu extensia formată din acele tupluri ale relaţiei R1 care
nu se regăsesc şi în relaţia R2.

Produs cartezian. Reprezintă o operaţie a AR definită pe două relaţii: R1 şi R2, operaţie care
constă din construirea unei noi relaţii R3, a cărei schemă se obţine prin concatenarea
schemelor relaţiilor R1 şi R2 şi a cărei extensie cuprinde toate combinaţiile tuplurilor din R1
cu cele din R2.
Notaţia uzuală pentru desemnarea operaţiei este: R1 X R2

95
Exemplu
ORAŞ:D1 JUDEŢ: D1 TRANSPORT:D3 TARIF:D4
Braşov Braşov tramvai 30
Târgovişte Dâmboviţa tramvai 30
Braşov Braşov autobuz 50
Târgovişte Dâmboviţa autobuz 50
Braşov Braşov troleibuz 50
Târgovişte Dâmboviţa troleibuz 50
ORAŞE: TARIF:
ORAŞ:D1 JUDEŢ:D1 X
Braşov Braşov
Târgovişte Dâmboviţa
TRANSP:D3 TARIF:D3
tramvai 30
autobuz 50
troleibuz 50

Produsul cartezian al relaţiilor ORAŞE şi TARIFE

Daţi un exemplu de produs cartezian între studenţi şi cursuri.

Să ne reamintim...
Produsul cartezian esteo operaţie definită pe două relaţii: R1 şi R2, operaţie care
constă din construirea unei noi relaţii R3, a cărei schemă se obţine prin concatenarea
schemelor relaţiilor R1 şi R2 şi a cărei extensie cuprinde toate combinaţiile
tuplurilor din R1 cu cele din R2.

Proiecţia. Reprezintă o operaţie din AR definită asupra unei relaţii R, operaţie care
constă din construirea unei noi relaţii P, în care se regăsesc unele atribute din R, înseamnă
efectuarea unor tăieturi verticale asupra lui R, care pot avea ca efect apariţia unor tupluri
duplicate ce se cer a fi eliminate.
Prin operaţia de proiecţie se trece de la o relaţie de grad n la o relaţie de grad
p, mai mic decât cel iniţial (p < n) ceea ce explică şi numele de proiecţie atribuit operaţiei.
Notaţia uzuală pentru operaţia de proiecţie este:
ΠAi,Aj,…,Am(R)
În exemplu este exemplificată operaţia de proiecţie a unei relaţii.

96
Exemplu

Proiectia relaţiei ORAŞE pe atributul "Judeţ"

Daţi un exemplu de diferenţă între o grupă de studenţi şi cadre didactice (se va


ţine cont că un student la master poate fi şi preparator).

Să ne reamintim...
Diferenţa este o operaţie din AR definită asupra unei relaţii R, operaţie care
constă din construirea unei noi relaţii P, în care se regăsesc unele atribute din R,
înseamnă efectuarea unor tăieturi verticale asupra lui R, care pot avea ca efect
apariţia unor tupluri duplicate ce se cer a fi eliminate.

5. Selecţia. Roprezintă o operaţie din AR definită asupra unei relaţii R, operaţie care constă
din construierea unei relaţii S, a cărei schemă este identică cu cea a relaţiei R şi a cărei
extensie este constituită din acele tupluri din R care satisfac o condiţie menţionată explicit în
cadrul operaţiei. Întrucât cel mai adesea, nu toate tuplurile din R satisfac, această condiţie,
selecţia înseamnă efectuarea unor tăieturi orizontale asupra relaţiei R, adică eliminarea de
tupluri. Condiţia precizată în cadrul operaţiei de selecţie este în general de forma:

unde: "operator de comparaţie" poate fi: <, <=, >=, > sau <>.
Notaţia folosită în mod uzual pentru desemnarea operaţiei de selecţie este
următoarea:
Σ(conditie)R

97
Exemplu

.Selecţie efectuata asupra relaţiei ORAŞE

Daţi un exemplu de selecţie din studenţi după grupă.

Să ne reamintim...
Selecţia este o operaţie definită asupra unei relaţii R, operaţie care constă din
construierea unei relaţii S, a cărei schemă este identică cu cea a relaţiei R şi a cărei
extensie este constituită din acele tupluri din R care satisfac o condiţie menţionată
explicit în cadrul operaţiei.

6. Joncţiunea (Joinul). Reprezintă o operaţie din AR definită pe două relaţii: R1 şi


R2, operaţie care constă din construirea unei noi relaţii R3, prin concatenarea unor
tupluri din R1 cu tupluri din R2. Se concateneaza acele tupluri din R1 şi R2 care satisfac o
anumita condiţie, specificată explicit în cadrul operaţiei. Extensia relaţiei R3 va contine deci
combinaţiile acelor tupluri care satisfac condiţia de concatenare.
Notaţiiile uzuale pentru desemnarea operaţiei de joncţiune sunt:

Reprezentarea grafică a aeestei operaţii este prezentată în fig. 3.8.

Reprezentarea grafica a operaţiei de joncţiune

98
În general, condiţia de concatenare menţionata în cadrul operaţiei de joncţiune este
de forma:

În funcţie de operatorul de comparaţie din cadrul condiţiei de concatenare, joinul poate


fi de mai multe tipuri. Cel mai important tip de join, în sensul celei mai frecvente utilizări este
equijoinul.

Equijoinul reprezintă joncţiunea dirijată de o condiţie de forma:

Operatia de joncţiune se poate exprima cu ajutorul operaţiilor de produs cartezian şi


selecţie, rezultatul unui join fiind acelaşi cu rezultatul unei selecţii operate asupra unui produs
cartezian, adică:
JOIN (R1,R2, condiţie) = RESTRICT(PRODUCT(R1,R2), condiţie)
Produsul cartezian reprezintă o operaţie laborioasă şi foarte costisitoare, ceea ce face
ca în locul produsului să fie utilizat joinul ori de câte ori acest lucru este posibil. Cu toate că
apare drept o operaţie derivată, joinul este prezentat de obicei drept o operaţie de bază din
AR, dată fiind importanţa sa în cadrul sistemelor relaţionale, în special la construirea
relaţiilor virtuale.
În cadrul fig.3.9. este ilustrată operaţia de equijoin.
Au fost definite numeroase variante ale operaţiei de joncţiune, variante care diferă nu
numai în funcţie de tipul condiţiilor de concatenare, ci şi după modul de definire a schemei şi
respectiv, extensiei relaţiei rezultate prin joncţiune.
Exemplu

Operaţia de equijoin a relaţiilor ORAŞE şi ESTIMARI

Daţi un exemplu de equijoin între grupe şi studenţi.

Joncţiunea naturală. În cazul equijoinului, schema relaţiei conţine toate atributele


celor doi operanzi în toate tuplurile relaţiei rezultat vor exista de aceea cel puţin două valori
egale. În sensul eliminării acestei redundanţe s-a introdus joncţiunea naturală, ca operaţie

99
definită pe două relaţii: R1 şi R2, prin care este construită o noua relaţie R3, a cărei schemă
este obţinută prin reuniunea atributelor din relaţiile R1 şi R2 (atributele cu acelaşi nume se iau
o singură dată) şi a cărei extensie conţine tuplurile obţinute prin concatenarea tuplurilor din
R1 cu tuplurile din R2 care prezintă aceleaşi valori pentru atributele cu acelaşi nume.

Notaţia uzuală pentru joncţiunea naturală este:


Reprezentarea grafică a acestei operaţii este

Exemplu

Operaţia de joncţiune naturală a relaţiilor ORAŞE şi ESTIMĂRI

Daţi un exemplu de joncţiune naturală între cărţi şi edituri.

Să ne reamintim...
Joncţiunea naturală este o operaţie definită pe două relaţii: R1 şi R2, prin care este
construită o noua relaţie R3, a cărei schemă este obţinută prin reuniunea atributelor
din relaţiile R1 şi R2 (atributele cu acelaşi nume se iau o singură dată) şi a cărei
extensie conţine tuplurile obţinute prin concatenarea tuplurilor din R1 cu tuplurile
din R2 care prezintă aceleaşi valori pentru atributele cu acelaşi nume.

7. Intersecţia. Reprezintă o operaţie a AR definită pe două relaţii: R1 şi R2 ambele cu


aceeaşi schemă, operaţie care constă din construirea unei noi relaţii R3, cu schema identică cu
a operanzilor şi cu extensia formată din tuplurile comune lui R1 şi R2.
Notaţile uzuale folosite pentru desemnarea operaţiei de intersecţie sunt:

100
Reprezentarea grafică a operaţiei de intersecţie

Exemplu

Intersecţia relaţiilor ORAŞE şi MUNICIPII

Daţi un exemplu de intersecţie.

Intersecţia reprezintă o operaţie derivată, care poate fi exprimată prin intermediul unor
operaţii de bază. De exemplu, operaţia de intersecţie se poate exprima prin intermediul
operaţiei de diferenţă, cu ajutorul următoarelor echivalenţe:
R1 R2=R1-(R1-R2)
R1 R2=R2-(R2-R1)

101
Să ne reamintim...
Intersecţia este o operaţie definită pe două relaţii: R1 şi R2 ambele cu aceeaşi
schemă, operaţie care constă din construirea unei noi relaţii R3, cu schema identică
cu a operanzilor şi cu extensia formată din tuplurile comune lui R1 şi R2.

10.4 Rezumat
Mulţimea tuplelor de aceeaşi formă formează o relaţie.
Cu aceste relaţii se pot face operaţii care au ca rezultat alte relaţii.Operaţiile
de reuniune, intersecţie şi diferenţă se pot face numai între relaţii care au aceeaşi
schemă şi sunt aceleaşi ca la mulţimi.
Proiecţia are ca rezultat o relaţie numai cu atributele specificate şi ca tuple –
tupele iniţiale din care se elimină dublurile.
Selecţia are ca rezultat o relaţie cu aceeaşi schemă dar numai cu tuplele care
satisfac predicatul de selecţie.
Produsul cartezian are ca rezultat o relaţie cu schema compusă din
reuniunea atributelor celor două scheme şi ca tuple – tuplele compuse din tuplele
primei relaţii la care se concatenează toate tuplele celei de adoua relaţii ca şi în
produsul cartezian a două mulţimi.
Joncţiunea este produsul cartezian numai cu tuplele care satisfac un
predicat. Dacă predicatul este o egalitate atunci avem de a face cu o echijoncţiune.
Echijoncţiunea în care egalitatea este între atributele cu acelaşi nume în cele două
relaţii şi în schema finală apare un atribut comun o singură dată, se va numi
joncţiune naturală.

9.7 Test de autoevaluare a cunoştinţelor


Se dau următoarele relaţii cu schemele lor:
-Scări (Nr_bloc, Scara, Lift)
-Apartamente(Nr_bloc,Scara,Apartament,Suprafaţa,Cutii_poştale, Nr_prize_tv)
- Familii (Nr_mat, Nr_pers, Nr_pers_prez, Nr_chei)
-Locatari
Nr_Mat, Nr_bloc, Scara, Etaj, Apartament,Nume
Să se exprime în algebra relaţională cererile:
1) tabel nominal cu locatarii de pe scara = 3 din bloc = 34
2) tabel nominal cu locatarii de pe scara = 1 din bloc = 34
3) tabel nominal cu locatarii de pe scara = 2 din bloc = 34
4) tabel nominal cu locatarii de pe scările 1,2,3 ale blocului 34
5) lista apartamentelor cu suprafaţa mai mare decât 50 mp
6) tabel nominal cu persoanele care locuiesc pe scara 3 bloc 34 şi nu
locuiesc şi pe scara 1 a aceluiaşi bloc
Rezultatele le găsiţi la sfârşit, la pag 116.

102
11 Răspunsuri la testele de autoevaluare.

11.1.5 Structuri liniare

11.1.5.1 c
11.1.5.2 b
11.1.5.3 Vom extrage succesiv vârful stivei S şi îl vom depune într-o altă stivă T. Extragerile
încetează fie când S devine vidă, fie când x este găsit.
Elementele din T vor fi depuse înapoi în S.
Extrage( S, x )
T =  gasitx = fals
Cât timp S≠  şi gasitx = fals
aS
{scoatem vârful stivei}

103
Dacă a ≠ x atunci
aT
{îl depunem în T}
altfel
gasitx = adevărat
Sfârşit dacă
Sfârşit cât timp
Cât timp T ≠ 
aT
aS
Sfârşit cât timp
Return
Complexitate: cazul cel mai defavorabil este acela în care x nu se găseşte în S. În acest caz, tot
conţinutul lui S este trecut în T şi apoi repus în S. Complexitatea este deci (|S|), unde |S|
reprezintă numărul de elemente aflate iniţial în S.

11.2. Arbori binari


11.2.7.1
(Determinarea predecesorului)
PREDBIN(x, y)
Dacă LS(x) ≠ Nil atunci
Cheamă MAXBIN(LS(x), y)
Return
Sfârşit dacă
y = P(x)
Cât timp (y ≠ Nil) şi (KEY (y) > KEY (x))
y = P(Y )
Sfârşit cât timp
Return
11.2.7.2
CAUTBINREC(Rad, k,Rez, x)
x = Rad
Dacă (x = Nil) sau (k = KEY (x)) atunci
Return
Sfârşit dacă

104
Dacă k < KEY (x) atunci
Cheamă CAUTBINREC(LS(x), k,Rez, x)
Return
altfel
Cheamă CAUTBINREC(LD(x), k,Rez, x)
Return
Sfârşit dacă
11.2.7.3
În figura de mai jos sunt desenaţi toţi arborii obţinuţi în urma inserării succesive a cheilor
date.

11.2.7.4
a) Cheia 45 se află într-un nod care are un singur descendent, deci se şterge şi se reface
legătura dintre părintele cheii şterse şi descendentul acesteia.

Ştergerea unei chei cu un singur descendent

105
b) Cheia 36 se află într-un nod care are doi descendenţi, deci se caută nodul care conţine
predecesorul cheii de şters şi se face schimbul de chei între aceste noduri, apoi se aplică
regula potrivită pentru noua poziţie a cheii de şters, în acest caz ea a devenit o frunză deci
ştergerea se face natural..

Ştergerea unei chei cu doi descendenţi


c) La aceste ştergeri s-au întâlnit toate cele trei cazuri – doi descendenţi, un descendent şi
niciunul.

Ştergerea folosind predecesorul


d) Se poate observa că prin schimbarea regulii de ştergere s-a obţinut alt arbore.

106
Ştergerea folosind succesorul

11.2.7.5
La primul arbore rotaţia în jurul nodului 4 se poate efectua atât spre dreapta cât şi spre stânga.

Rotaţie dreapta, respectiv stânga după 4

La al doilea arbore rotaţia în jurul nodului 4 se poate efectua doar atât spre dreapta.

Rotaţie dreapta după 4

La al treilea arbore rotaţia în jurul nodului 4 se poate efectua atât spre dreapta cât şi spre
stânga.

107
Rotaţie dreapta, respectiv stânga după 4

11.3 Arbori Roşu-negri, Splay, AVL


11.3.6.1

108
11.3.6.2

109
Celelalte ştergeri sunt aproape naturale, la final arborele a arăta astfel:

11.3.6.3

11.3.6.4
În cazul lui 1 N<P<B, deci este left-left.
Pentru 13 avem B<P<N, atunci nepotul este right-right.

110
Nodul 17 este mai mare decât părintele care este mai mic decât bunicul (P<N<B), deci avem
un nod right-left.
Nodul 21 este left-right (B<N<P).

11.4.7 Îmbogăţirea structurilor de date


11.1.7.1
Afirmaţia: ‘dacă am memora în fiecare nod rangul său din arbore, atunci operaţiile RN-
SELECT şi RN-RANG s-ar executa mai rapid, dar inserarea unui nou element minim în
arbore, ar provoca modificarea acestei informaţii (rangul) în fiecare dintre nodurile arborelui’
este adevărată.

11.5.7 Arbori balansaţi B+


11.5.7.1
Numărul minim de chei dintr-un nod este 2, iar cel maxim este 3, deci t-1=2 implică t=3
11.5.7.2
Inserarea cheilor A, Q şi K se face natural pentru că nodurile în care se va face inserarea
nu sunt pline, după inserare arborele va arăta astfel:

B-arborele după inserarea cheilor A, Q şi K


Inserarea lui C însă va produce probleme pentru că nodul este plin are 2·3-1 noduri deja.
Primul pas este să găsim cheia mediană aflată pe poziţia 3. Această cheie este D, cheile A şi B
vor forma un nou nod LS a lui D, iar E şi F vor forma un nou nod LD a lui D, apoi se
inserează cheia C. După inserare arborele va arăta astfel:

B-arborele după inserarea cheii C

Inserarea cheii Ţ va genera divizarea la nivelul nodului dar şi la nivelul părintelui care este
chiar rădăcina. După inserare arborele va arăta astfel:

B-arborele după inserarea cheii Ţ

111
11.6. 7 Heap-uri binare
11.6. 7.1

S-a considerat vectorul A cu 10 elemente şi arborele binar asociat. Conform algoritmului


s-a început heapificarea de la i=5 micşorându-se pasul cu câte o unitate. Trebuie observat că,
atunci când se apelează procedura de heapificare pentru un nod care are subarbori, aceşti
subarbori sunt deja heap-uri.

112
11.6. 7.2

Vectorul sortat este 1, 2, 3, 4, 5, 6, 9, 10, 11, 15

113
11.6. 7.3

Evoluţia cozii de priorităţi după inserare şi scoatere

11.7.7 Heap-uri binomiale


11.7.7.1.

11.7.7.2
Găsim minimul care este 5
Reunim heap-ul rămas cu cel rezultat din ştergerea lui 5

Reuniunea heapurilor obţinute după ştergerea minimului

114
11.8.6 Structura datelor pe disc magnetic
11.8.6.1
A=0.02 secunde
Viteza de revoluţie pe secundă va fi R=7200/60= 120 R=1/120=0.0083 secunde
R/2= 0.00415
L/D=1000/80000=0.010205
Deci:
T=0.02+0.00415+0.010205=0.034355 secunde

11.8.6.2
Timpul total de citire a fişierului= 0.00415*8+0.010205*8000=81.6732, iar
T=81.67/8000=0.0102 secunde

11.9.7 Structura relaţională


11.9.7.1 Definiţi schema relaţiei student.
student=(nr_matricol,Nume,Grupa,Oras,Data_nasterii,adresa,cod_facultate)
11.9.7.2 Definiţi schema relaţiei note. 11.9.7.3 Ce fel de relaţie este între student şi note.
Nota la o materie este de mulţi la unu, iar student la note de unu la mulţi.
11.9.7.4 Definiţi schema relaţiei facultate.
facultate=(cod_facultate,Nume_facultate,adresa,nr_telefon)
11.9.7.5Ce fel de relaţie este între student şi facultate.
o facultate are mai mulţi studenţi.
11.9.7.6 Definiţi schema relaţiei materii.
materii=(cod_materie,Denumiree_materie,an_studiu,Sectie,Cod_profesor)

11.10.7 Algebra relaţională


11.10.7 .1
R1=nume(bloc=34 and scara=3(scari)  (locatari))
11.10.7 .2
R2= nume (bloc=34 and scara=1(scari)  (locatari))
11.10.7 .3
R3= nume (bloc=34 and scara=2(scari)  (locatari))
11.10.7 .4
R = R1  R2  R3
11.10.7 .5
R = suprafaţa > 50(apartamente)
11.10.7.6
R= (R1-R2)

Bibliografie
1) Ciurea E., “Algoritmi, introducere în algoritmica grafurilor”, Editura Tehnică, 2001;
2) Cormen T., Leiserson C., Rivest R., “Introducere în algoritmi”, Editura Agora, 2000;
3) Iacob P., “Introducere în algoritmică”, Editura Tipona, 2005;
4) Iacob P.,”Culegere de probleme de structure de date”,Ed.Lux Libris,2009;

115
5) Iorga V., Opincaru C., Stratan C., Chiriţă A., “Structuri de date şi algoritmi”, Editura
Polirom, 2005;
6) Knuth D., “Sorting and searching”, Vol. 3 din ”The art of computer programming”,
Editura Addison Wesley, 1981;
7) Tomescu I., “Data structures”, Editura Universităţii din Bucureşti, 1997.

116
117

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