Sunteți pe pagina 1din 6

Arbori binari de căutare

1. Ce este un arbore binar de căutare?


Un caz particular de arbori binari sunt arborii de căutare, în care informaţia din fiecare nod este
mai mare decât informaţia din nodul fiului stâng şi mai mică sau egală cu cea din nodul fiului drept.
Un astfel de arbore se poate reprezenta printr-o structură de date înlănţuită, în care fiecare nod este
un obiect. Pe lângă un câmp cheie şi date adiţionale, fiecare obiect nod conţine câmpurile stânga,
dreapta şi p care punctează spre nodurile corespunzătoare fiului stâng, fiului drept şi respectiv
părintelui nodului.
Înt-un arbore binar de căutare, cheile sunt întotdeauna astfel memorate încât ele satisfac
proprietatea arborelui binar de căutare:
Fie x un nod dintr-un arbore binar de căutare. Dacă y este un nod din subarborele stâng al lui x,
atunci cheie[y]  cheie[x]. Dacă y este un nod din subarborele drept al lui x, atunci cheie[x] 
cheie[y].
Exemple:

(a) (b)

2. Operaţii specifice într-un arbore binar de căutare


Arborii de căutare sunt structuri de date ce posedă multe operaţii specifice structurilor dinamice,
precum: CAUTĂ, MINIM, MAXIM, PREDECESOR, SUCCEOSR, INSEREAZĂ şi ŞTERGE.
Proprietatea arborelui binar de căutare ne permite să tipărim toate cheile în ordine crescătoare cu
ajutorul unui algoritm recursiv simplu, numit traversarea arborelui în inordine: se tipăreşte cheia
rădăcinii unui subarbore între valorile din subarborele său stâng şi cele din subarborele său drept.
Similar, o traversare a arborelui în preordine va tipări cheia rădăcinii înaintea cheilor din
subarbori, iar o traversare a arborelui în postordine va tipări cheia rădăcinii după cheile din
subarbori.
Procedura de tipărire a elementelor unui arbore binar de căutare (apelul cu nodul rădăcină):
ARBORE-TRAVERSARE-INORDINE(x)
1. dacă x  NIL atunci
2. ARBORE-TRAVERSARE-INORDINE (stânga[x])
3. afişează cheie[x]
4. ARBORE-TRAVERSARE-INORDINE (dreapta[x])
Spre exemplu, traversarea în inordine a arborelui din exemplul (a) afişează cheile: 2, 3, 4, 5, 8, 9.
2.1. Căutarea
Procedura de căutare a unui nod având cheia cunoscută (un pointer x la rădăcina arborelui şi o
valoare k a cheii) returnează un pointer la nodul având cheia k (dacă există un asemenea nod în
arbore) sau NIL în caz contrar.
ARBORE-CAUTĂ (x, k)
1. dacă x = NIL sau k = cheie[x] atunci
2. returnează x
3. dacă k < cheie[x] atunci
4. returnează ARBORE-CAUTĂ (stânga[x], k)
5. altfel
6. returnează ARBORE-CAUTĂ (dreapta[x], k)
Aceeaşi procedură se poate scrie şi iterativ:
ARBORE-CAUTĂ-ITERATIV(x, k)
1. cât timp x  NIL şi k  cheie[x] execută
2. dacă k < cheie[x] atunci x  stânga[x]
3. altfel x  dreapta[x]
4. returnează x
2.2. Minimul şi maximul
Determinarea elementului având cheia minimă dintr-un arbore binar de căutare se realizează
întotdeauna urmând pointerii fiu stânga începând cu rădăcina şi terminând când se întâlneşte NIL.
Procedura următoare întoarce un pointer la elementul minim din subarborele a cărui rădăcină
este nodul x:
ARBORE-MINIM (x)
1. cât timp stânga[x]  NIL execută
2. x  stânga[x]
3. returnează x
Pseudocodul pentru procedura ARBORE-MAXIM este simetric.
ARBORE-MAXIM (x)
1. cât timp dreapta[x]  NIL execută
2. x  dreapta[x]
3. returnează x
2.3. Succesorul şi predecesorul unui nod
Structura de arbore binar de căutare permite determinarea succesorului unui nod chiar şi fără
compararea cheilor. Procedura următaore returnează succesorul unui nod x dintr-un arbore binar de
căutare (dacă succesorul există), sau NIL, dacă x are cea mai mare cheie din arbore.
ARBORE-SUCCESOR (x)
1. dacă dreapta[x]  NIL atunci
2. returnează ARBORE-MINIM (dreapta[x])
3. y  p[x]
4. cât timp y  NIL şi x = dreapta[y] execută
5. x  y
6. y  p[y]
7. returnează y
Procedura ARBORE-PREDECESOR este similară.
2.4. Inserarea şi ştergerea
Vom folosi procedura ARBORE-INSEREAZĂ pentru a insera o nouă valoare v într-un arbore
binar de căutare T. Procedurii i se transmite un nod z pentru care cheie[z] = v, stânga[z] = NIL şi
dreapta[z] = NIL. Ea va modifica arborele T şi unele dintre câmpurile lui z astfel încât z va fi
inserat pe poziţia corespunzătoare în arbore.
ARBORE-INSEREAZĂ (T, z)
1. y  NIL
2. x  rădăcină[T]
3. cât timp x  NIL execută y  x
4. dacă cheie [z] < cheie[x] atunci x  stânga[x]
5. altfel x  dreapta[x]
6. p[z]  y
7. dacă y = NIL atunci rădăcină[T]  z
8. altfel dacă cheie[z] < cheie[y] atunci stânga[y]  z
9. altfel dreapta[y]  z
Pseudocodul procedurii ARBORE-ŞTERGE permite ştergerea unui nod dat z dintr-un arbore
binar de căutare care primeşte ca argument un pointer la z.
ARBORE-ŞTERGE (T, z)
1. dacă stânga[z] = NIL sau dreapta[z] = NIL atunci
2. y  z
3. altfel y  ARBORE-SUCCESOR(z)
4. dacă stânga[y]  NIL atunci x  stânga[y]
5. altfel x  dreapta[y]
6. dacă x  NIL atunci p[x]  p[y]
7. dacă p[y] = NIL atunci rădăcină[T]  x
8. altfel dacă y = stânga[p[y]] atunci stânga[p[y]]  x
9. altfel dreapta[p[y]]  x
10. dacă y  z atunci cheie[z]  cheie[y] {se copiază şi datele adiţionale ale lui y}
11. returnează y
3. Aplicaţie
Pentru evidenţa elevilor unei şcoli se defineşte un arbore binar de căutare, în care fiecare nod va
memora numărul matricol, numele şi numărul de absenţe ale unui elev. Căutarea în arbore se va
face după numărul matricol al elevilor. Scrieţi un program care, prin intermediul unui meniu,
selectează în mod repetat, atâta timp cât utilizatorul doreşte acest lucru, una din următoarele acţiuni:
- adăugarea unui elev;
- afişarea absenţelor pentru numărul matricol minim;
- afişarea absenţelor pentru numărul matricol maxim;
- modifică numărul de absenţe al unui elev pentru care se cunoaşte numărul matricol;
- afişează toţi elevii al căror nume începe cu litera „B”.

program aplicatie;
type pnod=^nod;
nod=record
nr:integer;
nume:string;
abs:integer;
st, dr: pnod;
end;
var r:pnod; n,op: integer; num:string;
abs1:integer; exista:boolean;
procedure creare (var p:pnod;n:integer; num:string; abs1:integer);
{creeaza un nod al arborelui ce va contine un elev cu
numarul matricol n, numele num si nr. de absente abs1}
begin
if p<>nil then
begin
if n<p^.nr then creare(p^.st, n, num, abs1)
else
if n>p^.nr then creare(p^.dr, n, num, abs1)
else writeln(' elevul exista')
end else begin
new(p); p^.nr:=n;
p^.nume:=num;
p^.abs:=abs1;
p^.st:=nil;p^.dr:=nil;
end;
end;
procedure SRD(p:pnod);
begin
if p<>nil then begin
SRD(p^.st);
writeln(' ',p^.nr,' ',p^.nume,' ',p^.abs);
SRD(p^.dr);
end;
end;
function min(p:pnod):integer;
{ cheia minima se gaseste in nodul cel mai
din stinga, pornind de la radacina}
begin
if p^.st<>nil then min:=min(p^.st)
else min:=p^.abs;
end;
function max(p:pnod):integer;
{cheia maxima se gaseste in nodul cel mai
din dreapta, pornind de la radacina}
begin
if p^.dr<>nil then max:=max(p^.dr)
else max:=p^.abs;
end;
procedure elevi_B(p:pnod);
{ afiseaza elevii care au numele incepind cu litera B}
begin
if p<>nil then begin
if (p^.nume[1]='B') then begin
exista:=true;
writeln(' ',p^.nr,' ',p^.nume,' ',p^.abs);
end;
elevi_B(p^.st); elevi_B(p^.dr);
end
end;
procedure modifica_abs(p:pnod;n:integer);
{ modifica nr. de absente pentru care
se cunoaste numarul matricol}
begin
if p<>nil then begin
if n<p^.nr then modifica_abs(p^.st, n)
else if n>p^.nr then
modifica_abs(p^.dr, n)
else begin
write(' absenta=');
readln(abs1);
p^.abs:=abs1;
end
end
else writeln(' Elevul cu numarul matricol ',n,' nu exista');
end;
begin
r:=nil;
repeat
writeln(' alegeti optiunea:');
writeln(' 1 - ADAUGAREA unui elev');
writeln(' 2 – Absente pentru matricol MINIM');
writeln(' 3 – Absente pentru matricol MAXIM');
writeln(' 4 - MODIFICA numarul de absente');
writeln(' 5 - ELEVII cu numele - B');
writeln(' 6 - LISTA tuturor elevilor');
writeln(' 0 - IESIRE');
writeln;
readln(op);
case op of
1:begin
write(' numar matricol= '); readln(n);
write(' nume elev= '); readln(num);
write(' numar absente= '); readln(abs1);
creare(r,n,num,abs1);
end;
2:begin writeln(' Valoarea absentei pentru matricol MINIM');
writeln(' min=',min(r));
end;
3: begin writeln(' Valoarea absentei pentru matricol MAXIM');
writeln(' max=',max(r));
end;
4: begin write(' numar matricol=');
readln(n);
modifica_abs(r,n);
end;
5:begin exista:=false;
elevi_B(r);
if not exista then
writeln(' nu exista elevi cu numele - B');
end;
6:begin writeln;
writeln(' lista tuturor elevilor');
SRD(r);
end;
end;
until op=0;
readln;
end.