You are on page 1of 5

8.

6 ARBORI 2-3-4

Arborii de cutare multici, numiti si arbori B, sunt arbori ordonati si echilibrati


cu urmtoarele caracteristici:

- Un nod contine n valori si n+1 pointeri ctre noduri fii (subarbori); n este
cuprins ntre M/2 si M;numrul maxim de pointeri pe nod M+1 determina
ordinul arborelui B: arborii binari sunt arbori B de ordinul 2, arborii 2-3 sunt
arbori B de ordinul 3, arborii 2-3-4 sunt arbori B de ordinul 4.

- Valorile dintr-un nod sunt ordonate cresctor;

- Fiecare valoare dintr-un nod este mai mare dect valorile din subarborele
stnga si mai mic dect valorile aflate n subarborele din dreapta sa.

- Valorile noi pot fi adugate numai n noduri frunz.

- Toate cile au aceeasi lungime (toate frunzele se afl pe acelasi nivel).

- Prin adugarea unei noi valori la un nod plin, acesta este spart n alte dou
noduri cu cte M/2 valori, iar valoarea median este trimis pe nivelul superior;

- Arborele poate creste numai n sus, prin crearea unui nou nod rdcin.

- La eliminarea unei valori dintr-un nod se pot contopi doua noduri vecine, de
pe acelasi nivel, dac suma valorilor din cele dou noduri este mai mic ca M.

La adugarea unei noi valori ntr-un arbore B se caut mai nti nodul frunz
care ar trebui s contin noua valoare, dup care putem avea dou cazuri:

- dac este loc n nodul gsit, se adaug noua valoare ntr-o pozitie eliberat
prin deplasarea altor valori la dreapta n nod, pentru mentinerea conditiei ca
valorile dintr-un nod s fie ordonate cresctor.

- dac nodul gsit este plin atunci el este spart n dou: primele n/2 valori
rmn n nodul gsit, ultimele n/2 valori se mut ntr-un nod nou creat, iar
valoarea median se ridic n nodul printe. La adugarea n nodul printe pot
aprea iar cele dou situatii si poate fi necesar propagarea n sus a unor valori
pn la rdcin; chiar si nodul rdcin poate fi spart si atunci creste nltimea
arborelui.

Spargerea de noduri pline se poate face :


- de jos in sus (bottom-up), dup gsirea nodului frunz plin;

- de sus n jos (top-down), pe msur ce se caut nodul frunz care trebuie s


primeasc noua valoare: orice nod plin pe calea de cutare este spart anticipat
si astfel se evit adugarea la un nod plin.

Pentru exemplul anterior (cu valorile 3,5,7 in radacina) metoda de sus n jos
constat c nodul rdcin (de unde ncepe cutarea) este plin si atunci l
sparge n trei: un nou nod rdcin cu valoarea5, un nou nod cu valoarea 7 (la
dreapta ) si vechiul nod cu valoarea 3 (la stanga).Spargerea radacinii n acest
caz nu era necesar deoarece nici un nod frunz nu este plin si ea nu sar fi
produs dac se revenea de jos n sus numai la gsirea unui nod frunz plin.

Exemplu de definire a unui nod de arbore B (2-3-4) cu valori ntregi:


#define M 3 // nr maxim de valori in nod (arbore 2-3-4)

typedef struct bnod {

int n; // Numar de chei dintr-un nod

int val[M]; // Valorile (cheile) din nod

struct bnod* leg[M+1]; // Legaturi la noduri fii

} bnod;

Functie de afisare infixat (n ordine cresctoare) a valorilor dintr-un arbore B:

void infix (bnod* r) {

if (r==0) return;

for (int i=0;i<r n;i++) { // repeta ptr fiecare fiu

infix (r leg[i]); // scrie valori mai mici ca r->val[i]

printf("%d ",r val[i]); // scrie valoarea i

infix (r leg[r n]); // scrie valori mai mari ca ultima din nodul r

}
Spargerea unui nod p este mai simpl dac se face top-down pentru c nu
trebuie s tin seama si de valoarea care urmeaz a fi adugat:

void split (bnod* p, int & med, bnod* & nou) {

int m=M/2; // indice median nod plin

med=p->val[m]; // valoare care se duce in sus

p->n=m; // in p raman m valori

nou=make(M-m-1,&(p->val[m+1]),&(p->leg[m+1])); // nod nou cu


m+1,m+2,..M-1

for (int i=m+1;i<M;i++)

p->leg[i]=0; // anulare legaturi din p

Dac nodul frunz gsit p nu este plin atunci insertia unei noi valori x necesit
gsirea pozitiei

unde trebuie inserat x n vectorul de valori; n aceeasi pozitie din vectorul de


adrese se va introduce legtura de la x la subarborele cu valori mai mari ca x:

void ins (int x, bnod* legx, bnod * p) { // legx= adresa subarbore cu valori mai
mari ca x

int i,j;

// cauta pozitia i unde se introduce x

i=0;

while (i<p->n && x>p->val[i]) i++;

for (j = p->n; j > i; j--) { // deplasare dreapta intre i si n

p->val[j] = p->val[j - 1]; // ptr a elibera pozitia i

p->leg[j+1] = p->leg[j];

}
p->val[i] = x; // pune x in pozitia i

p->leg[i+1] = legx; // adresa fiu cu valori mai mari ca v

p->n++; // creste numarul de valori si fii din p

Cutarea nodului frunz care ar trebui s contin o valoarea dat x se poate


face iterativ sau recursiv, asemntor cu cutarea ntr-un arbore binar ordonar
BST. Se va retine si adresa nodului printe al nodului gsit, necesar la
propagarea valorii mediane n sus. Exemplu de functie recursiv:

void findsplit (int x, bnod* & r, bnod* & pp) {

bnod* p=r; bnod* nou, *rnou;

int med; // val mediana dintr-un nod plin

if (p->n==M) { // daca nod plin

split(p,med,nou); // sparge nod cu creare nod nou

if (pp!=0) // daca nu e nodul radacina

ins(med,nou,pp); // pune med in nodul parinte

else { // daca p e nodul radacina

rnou= new bnod; // rnou va fi noua radacina

rnou->val[0]=med; // pune med in noua radacina

rnou->leg[0]=r; rnou->leg[1]=nou;

rnou->n=1; // o singura valoare in noua radacina

r=rnou; pp=rnou; // modifica radacina r pentru noul arbore (mai inalt)

if (x > med) p=nou; // p=nod curent, de unde continua cautarea

// cauta subarborele i al lui p care va contine pe x


int i=0;

while (i<p->n && x > p->val[i]) // determina pozitia lui x in p->val

i++;

if (x==p->val[i]) return ; // daca x exista in p nu se mai adauga

if (p->leg[0]==0 ) // daca p e nod frunza

ins (x,0,p); // atunci se introduce x in p si se iese

else { // daca p nu e nod frunza

pp=p; p=p->leg[i]; // cauta in fiul i al lui p

findsplit(x,p,pp); // apel recursiv ptr cautare in jos din p

Pentru adugarea unei valori x la un arbore B vom folosi o functie cu numai 2


argumente:

void add (int x, bnod* & p) {

bnod* pp=0; // parinte nod radacina

findsplit (x,p,pp); // cauta, sparge si adauga x la nodul gasit

You might also like