Sunteți pe pagina 1din 5

1.5.5.

Arbore binar de căutare (ABC)


1.5.5.1. Noţiune de ABC
Arborii sunt foarte des utilizaţi pentru memorarea şi regăsirea rapidă a unor informaţii. Problema
căutării (localizării) unui nod se poate pune doar într-un arbore binar de căutare.
Un arbore binar de căutare este un arbore binar care trebuie să respecte următoarele proprietăţi:
pentru orice nod n, fiecare din descendenţii din subarborele din stânga va avea valoarea informaţiei mai
mică decât a nodului n, iar fiecare din descendenţii din subarborele din dreapta va avea valoarea
informaţiei mai mare decât a nodului n.
Într-un ABC informaţia din noduri este unică.
Exemple:
7 6
3 9
3 8
1 10
1 5 7 9

2 8
4
4
( a) (b)

În figurile de mai sus avem 2 arbori binari.


Arborele din figura (b) este arbore binar de căutare deoarece respectă regula de mai sus, şi anume că
în orice subarbore stâng valorile sunt mai mici decât ale rădăcinii acestuia şi în orice subarbore din
dreapta, valorile sunt mai mari decât ale rădăcinii respective.
Arborele din figura (a) nu este arbore binar de căutare deoarece nu toate nodurile respectă regula
menţionată. De exemplu, nodul cu informaţia 4 nu are ce “căuta” în subarborele drept, iar cifra 8 nu este
corect plasată.
Observaţie. O proprietate foarte importantă a ABC-ului este aceea că oferă posibilitatea ordonării
crescătoare a valorilor memorate în noduri prin parcurgerea arborelui în inordine.

1.5.5.2. Crearea şi inseratea într-un ABC


Crearea unui ABC se realizează adăugând intr-un arbore iniţial vid, pe rând, câte un nod. Ideea este
următoarea:
- dacă arborele este vid, se creează rădăcina;
- dacă arborele nu este vid, se compară informaţia noului nod cu informaţia din nodul curent. Dacă
este mai mare, se reia procesul pentru subarborele drept; dacă este mai mică se reia procesul
pentru subarborele stâng.
Exemplificăm procesul de inserare (adăugare) a unui nod:
Vom considera arborele din dreapta. Să 62 90
presupunem că dorim să inserăm nodul cu
valoarea 62. Acesta se va insera ca nod frunză. 50 97
Pentru a-l insera va trebui să căutăm o poziţie în 0
20 75
arbore care respectă regula de integritate a
arborilor binari de căutare.
5 25

Vom începe prin compararea nodului de inserat 62 90


(62), cu rădăcina arborelui (90).
Observăm că este mai mic decât ea, deci va 50 97
trebui inserat undeva în subarborele stâng al 0
rădăcinii. 20 75

5 25

1
Vom compara apoi 62 cu 50. Din moment ce 62 90
este mai mare decât 50, nodul 62 va trebui plasat 62
undeva în subarborele drept al lui 50. 50 97
0
20 75

5 25

Se compară apoi 62 cu 75. Deoarece 75 este mai 90


mare decât 62, 62 trebuie să se afle în subarborele
din stânga al nodului 75. 50 97
0
20 75 62

5 25

Dar 75 nu are nici un fiu în partea stângă. Asta


90
înseamnă că am găsit locaţia pentru nodul 62. Tot
ceea ce mai trebuie făcut este să modificăm în 50 97
nodul 75 adresa către fiul din stânga, încât să indice 0
spre 62. 20 75

5 25 62

În prezenţa declaraţiilor:
typedef struct nod
{ int inf; nod *st,*dr;
} ABC;

următoarea funcţie realizează adăugarea unui nod într-un ABC după metoda descrisă mai sus:

void Adauga(ABC* &r, int info) // r-pointer la radacina arborelui;


{ if(!r) //arborele este vid, creez radacina
{ r=new ABC; r->inf=info; r->st=r->dr=0; }
else
if(info<r->inf) Adauga (r->st, info);
else if(info>r->inf) Adauga(r->dr, info);
else cout<<"\ninformatie dublicat\n";}
Parametrii funcţiei Adauga() reprezintă nodul curent la un moment dat. Deoarece se alocă memorie
în heap pentru un nod nou, adresa acestuia este transmisă prin referinţă.

1.5.5.2. Căutarea unei informaţii într-un ABC.


Această operaţie se bazează pe ideea construcţiei arborelui. Se compară informaţia cu cea din
nodul curent. Dacă sunt egale, căutarea se încheie, dacă nu, căutarea continuă în subarborele stâng sau în
subarborele drept după cum valoarea căutată este mai mică, respectiv mai mare decât informaţia din
nodul curent. În cazul în care se ajunge într-un subarbore vid (adresă nulă), informaţia căutată nu se
găseşte în ABC şi se afişează un mesaj. Funcţia următoare implementează acestă metodă de căutare:

void Cauta(ABC *p, int x)


{ if(!p) cout<<"\ninformatia "<<x<<" nu exista in arbore\n";
else if(x<p->inf) Cauta(p->st, x);
else if(x>p->inf) Cauta(p->dr, x);
else cout<<"\ninformatia "<<x<<" exista in arbore\n"; }
2
1.5.5.3. Ştergerea unui nod dintr-un ABC
Ca şi în cazul operaţiei de inserare, ştergerea este precedată de o căutare a nodului cu cheia
(informaţia) dată x în arborele binar. În cazul în care un astfel de nod este găsit –să îl notăm cu p, iar cu t
să notăm părintele său –există trei situaţii posibile:
a. Nodul p este un nod terminal. În acest caz, ştergerea este simplă: înlocuim legăturile spre p cu
NULL. t t
p

`
A1 A1

b. Nodul p are un singur fiu. Înlocuim legătura spre p cu o legătură spre unicul fiu al lui p.
t t
p

A2
`
A1 A2 A1

c. Nodul p are exact doi fii. Vom reduce acest caz la una dintre situaţiile a. sau b., conservând
proprietatea de arbore binar de căutare. Pentru aceasta vom determina nodul cu cea mai mare cheie din
subarborele stâng al lui p, notat max.
Vom înlocui cheia lui p cu cheia nodului max şi vom şterge nodul max, care nu are fiu drept.
Deoarece nodul max este situat în subarborele stâng al lui p, are cheia mai mică decât nodurile din
subarborele drept şi mai mare decât a nodurilor din subarborele stâng, deci arborele astfel obţinut este
arbore binar de căutare.
Se poate proceda în mod analog, păstrând consistenţa arborelui binar de căutare înlocuind cheia lui p
cu cheia nodului cu cea mai mică cheie din subarborele drept al lui p, notat min, nod care nu are fiu stâng
şi ştergând apoi nodul min.
Exemplu. Să ştergem, din arborele binar de căutare următor, nodul cu valoarea 18.
25
Acest nod are doi fii. Vom determina maximul din
18 50 subarborele stâng al nodului cu valoarea 18 (nodul
cu valoarea 12), înlocuim cheia 18 cu cheia 12, apoi
12 20 46 99
ştergem maximul din subarborele stâng (acest nod
7 19 22 49 nu are fiu drept ). Obţinem arborele:

25
Programul următor gestionează operaţiile de creare şi
12 50 prelucrare a unui ABC. Se crează un arbore iniţial din
n valori citite de la tastatură. Prin intermediul unor
7 20 46 99 opţiuni de meniu se poate realiza în mod repetat
adăugarea unui nod în ABC, căutarea unei valori x,
ştergerea unei valori x şi afişarea nodurilor din arbore în
19 22 49
inordine (ordonate crescător după chei):

3
include <iostream>
using namespace std;

typedef struct nod // Definirea pointerului ABC


{ int inf;
nod *st,*dr;
}ABC;
ABC *tns;
void Adauga(ABC* &r,int info) // Adăugare unui nod nou
{ if(!r) //arborele este vid, creez radacina
{ r=new ABC; r->inf=info; r->st=r->dr=0; }
else
if(info<r->inf) Adauga(r->st,info);
else if(info>r->inf) Adauga(r->dr,info);
else cout<<"\ninformatie duplicat\n";
}
void Creare(ABC* &r) // Creare Arbore Binar de Căutare
{ int info,n,i;
cout<<"numar de noduri: "; cin>>n;
for(i=1;i<=n;i++)
{ cout<<"informatia nodului "<<i<<": ";
cin>>info;
Adauga(r,info);
}
}
void Cauta(ABC *p, int x) // Căutarea unei informaţii în ABC
{ if(!p) cout<<"\ninformatia "<<x<<" nu exista in arbore\n";
else
if(x<p->inf) Cauta(p->st,x);
else if(x>p->inf) Cauta(p->dr,x);
else cout<<"\ninformatia "<<x<<" exista in arbore\n";
}
void Stergere(ABC* &r, int x) // Ştergerea unui nod din ABC
{ ABC *p=r, *t=NULL, *max, *tmax, *fiu;
// caut noduri cu cheia x; t indica parintele acestui nod
while (p && p->inf!=x)
{ t=p;
if(x<p->inf) p=p->st;
else p=p->dr;
}
if(!p) return; // cheia x nu se afla I arbore
if(p->st && p->dr) //nodul de sters are 2 fii
{ // determin maximumul din subarborele stang
tmax=p; max=p->st;
while (max->dr)
{ tmax=max; max=max->dr;}
//copiez informatia
p->inf=max->inf;
//nodul maxim devine nod de sters
t=tmax; p=max;
}
//noduri de sters are cel mult un fiu
if(p->st) fiu=p->st;
4
else fiu=p->dr;
if (t)
if(t->st==p) //p este un fiu sters al parintelui sau
t->st=fiu;
else //p este fiul drept al tatalui sau
t->dr=fiu;
else //sterg radacina arborelui
r=fiu;
delete p;
}
void SRD(ABC *r) // Parcurgerea ABC în inordine
{ if(r)
{ SRD(r->st); cout<<r->inf<<" "; SRD(r->dr); }
}
int main()
{ ABC *rad=0; int x,opt;
Creare(rad); //se creaza ABC-ul initial
do{
cout<<"\n\n\tOptiuni:\n 1-Cauta o valoare in ABC\n 2-Adauga un nod in
ABC\n";
cout<<" 3-Sterge un nod din ABC\n 4-Lista nodurilor in inordine\n 5-Iesire\n";
cout<<"optiunea: "; cin>>opt;

switch(opt)
{
case 1: {cout<<"valoarea: "; cin>>x;
Cauta(rad,x); break;}
case 2: {cout<<"valoarea: "; cin>>x;
Adauga(rad,x); break;}
case 3: {cout<<"valoarea: "; cin>>x;
Stergere(rad,x); break;}
case 4: SRD(rad);
}
}while(opt!=5);
}

1.5.6. Exerciţii şi probleme propuse


1. Se consideră arborele din figura următoare:
1 a. Ce înălţime are acest arbore ?
b. Care sunt strămoşii nodului 6 ?
2 3 c. Care sunt descendenţii nodului 2 ?
d. Care sunt nodurile terminale în arbore ?
4 5
e. Care sunt descendenţii direcţi ai nodului 5 ?
f. Care noduri din arbore nu au fiu stâng ?
6 7
g. Care sunt nodurile situate pe nivelul 2 ?
8 9 h. Daţi exemple de două noduri fraţi.

2. Scrieţi o funcţie care să creeze o copie a unui arbore binar.


3. Scrieţi o funcţie care să parcurgă pe niveluri un arbore binar specificat ca parametru.
4. Scrieţi o funcţie care să determine înălţimea unui arbore binar.
5. Scrieţi o funcţie care să numere câte noduri terminale are un arbore binar primit ca parametru.
5

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