Anda di halaman 1dari 10

Cursul 9.

Structuri de date arborescente


Arborii sunt SD des folosite n manipularea datelor. Se pot defini ca grafe particulare fr cicluri care au
cteva noduri speciale:
-

un nod RADACIN, care nu are predecesor;

noduri interne arborelui, care au att predecesor ct i succesori (unul sau mai muli);

noduri frunz care nu au succesori;

Exemple:
1)arbore ternar complet:

2) arbore oarecare:

Se pot eticheta att nodurile ca n exemplul 2) ct i muchiile (sau arcele).


1. Traversarea arborilor.
Exist 2 modaliti fundamentale de traversare (parcurgere) a arborilor:
n lime (breadth first);
n adncime (depth first).
Traversarea n lime corespunde unei parcurgeri pe nivele: se viziteaz rdcina arborelui i apoi
succesorii si de pe nivelul 1 (de adncime 1) apoi succesorii nodurilor de pe nivelul 2, s.a.m.d.
Traversarea n adncime corespunde unui drum n adncime de la rdcina la o frunz apoi revenirea la
un nivel imediat superior si parcurgerea unui drum pn la alt frunz, s.a.m.d.

Exemplu:

n lime: 1,2,3,4,5,6,7,8,9,10,11

n adncime: 1,2,5,6,10,11,3,4,7,8,9

typedef struct
{ int dim;
int m[Max][Max];
} MAT;
void latime(MAT a, int incep)
{ int coada[n.dim],vizit[n.dim];
int prim,ultim,lin,i,j,n;
n=a.dim;
for(i=1;i<=n;i++) vizit[i]=0;
coada[1]=incep;
vizit[incep]=1;
ultim=1;prim=1;
do
{ lin=coada[prim];
for (j=1;j<=n;j++)
if ((a.m[lin][j]==1) && (vizit[j]==0))
{ coada[++ultim]=j;
vizit[j]=1;
}
prim++;
}
while (ultim<n);
cout<<"parcurgerea in latime incepand cu nodul "<<incep<<" este: ";
for (i=1;i<=n;i++) cout<<setw(2)<<coada[i];
cout<<endl;
}
void adancime(MAT a, int incep)
{ int stiva[a.dim], vizit[a.dim];
int prim,ultim,lin,j, n=a.dim;
for (j=1;j<=n;j++) vizit[j]=0;
prim=1;ultim=1;
stiva[1]=incep;
vizit[incep]=1;
while (prim>0)
{ lin=stiva[prim];
j=1;
while (j<=n)
{ if (a.m[lin][j]==0 || vizit[j]==1) j++;
else { stiva[++ultim]=j;
vizit[j]=1;

prim=ultim+1;
j=n+1;
}
}
prim=prim-1;

}
cout<<"parcurgerea in adancime incepand cu nodul "<<incep<<" este: ";
for (int i=1;i<=n;i++) cout<<setw(2)<<stiva[i];
cout<<endl;

7.1. TAD Arbori binari.


O colecie de elemente are o structur de tip arborescent dac elementele componente sunt n relaie unu la mai
multe, adic un element este n relaie cu mai multe elemente.
Elementele unei astfel de structuri se numesc noduri sau vrfuri. Ele au un unic predecesor numit printe dar mai
muli succesori numii fii. Un arbore este format din mulimea nodurilor i legturile dintre acestea. Un nod al
unui arbore poate fi rdcin (dac nu are predecesor) sau poate fi nod intern (dac are un singur predecesor i
mai muli succesori) sau poate fi nod terminal sau frunz (dac nu are nici un succesor). Un arbore particular este
arborele binar pentru care relaia dintre elemente este de tip unu la dou, adic un element poate avea maxim doi
succesori.
Un arbore binar poate fi definit recursiv ca fiind o mulime (colecie) de noduri vid sau format din nodul
Rdcin, Subarbore_stng i Subarbore_drept.

La reprezentarea n memorie a unui arbore binar, pe lnga informaia propriu-zis se vor memora n fiecare nod i
adresele de legatur spre nodurile succesoare n felul urmtor:

Prin traversarea unui arbore binar vom nelege parcurgerea tuturor vrfurilor arborelui, trecnd o singur dat prin
fiecare nod.
n funcie de ordinea (disciplina) de vizitare a nodurilor unui arbore binar, traversarea poate fi n preordine,
n inordine sau n postordine.
Traversarea n preordine este aceea n care se parcurge mai nti nodul rdcin, apoi subarborele stng i
dup aceea subarborele drept. Deci se parcurge arborele n ordinea (Rdcin, SubarboreStng, SubarboreDrept).
Evident, definiia este recursiv, parcurgerea unui subarbore fiind facut dupa aceai regul, deci ncepnd cu
rdcina. O procedur n Pseudocod corespunzatoare se d n continuare.
Procedur Preordine (R:Arbore);
Daca R<>Null
Atunci
Prelucrare (R.Info);
Preordine (R.ArboreStang);
Preordine (R.ArboreDrept)
Sfarsit Daca
Sfarsit Preordine;

Traversarea n inordine(fixordine) este aceea n care se parcurge mai nti subarborele stng, apoi nodul
rdcin i dup aceea subarborele drept. Deci se parcurge arborele n ordinea (SubarboreStng, Rdcin,
SubarboreDrept). O procedur n Pseudocod corespunzatoare se d n continuare.
Procedur Inordine (R:Arbore);
Daca R<>Null
Atunci
Inordine (R.ArboreStang);
Prelucrare(R.Info);
Inordine (R.ArboreDrept)
Sfarsit Daca
Sfarsit Preordine;

Traversarea n postordine este aceea n care se parcurge mai nti subarborele stng, apoi subarborele drept i
dup aceea nodul rdcin. Deci se parcurge arborele n ordinea (SubarboreStng, SubarboreDrept, Rdcin). O
procedur n Pseudocod corespunzatoare se d n continuare.
Procedur Postordine (R:Arbore);
Daca R<>Null
Atunci
Postordine (R.ArboreStang);
Postordine (R.ArboreDrept)
Prelucrare (R.Info);
Sfarsit Daca
Sfarsit Preordine;

Pentru arborele alturat, ordinea nodurilor corespunztoare cele trei tipuri de traversri este urmtoarea :

Fisierul arbinar.h are urmtoare specificaie:


/*TAD arbore binar avand ca informatie in noduri un caracter
operatii:
- creare arbore binar in preordine
- creare arbore binar pe nivele
- copierea unui arbore binar in alt arbore binar
- verificarea egalitatii a doi arbori binari
- parcurgere recursiva si nerecursiva in preordine
- parcurgere recursiva si nerecursiva in inordine
- parcurgere recursiva si nerecursiva in postordine
- cautare informatie in arborele binar
- eliberarea zonei de memorie alocate dinamic pentru
arbore
*/
class arb;
class nod
{ protected:
char info;
//informatia din nod;
nod *st;
//adresa fiului stang
nod *dr;
//adresa fiului drept
public:
nod(){st=dr=NULL;}
//constructor implicit;
nod(char c)
//constructor;
{info=c;st=dr=NULL;}
friend class arb;
};
class arb
{ protected:
nod* rad;
//functii protejate care sunt apelate
//de functiile de interfata
nod* crepre(nod*);
void inord_rec(nod*);
void preord_rec(nod*);
void postord_rec(nod*);
int egal(nod*,nod*);
nod* copiere(nod*);
void elib(nod*);
nod* cree();
public:
arb(){rad=NULL;} //constructor implicit;
arb(arb&);
//constructor de copiere;
~arb();
//destructor;
void crepreord(); //creare arbore in preordine;
void crenivele(); //creare arbore pe nivele;
void preordine(); //parcurgere nerecursiva in preordine;
void inordine();
//parcurgere nerecursiva in inordine;
void postordine(); //parcurgere nerecursiva in postordine;
void inord_rec(); //parcurgere recursiva in inordine;
void preord_rec(); //parcurgere recursiva in preordine;
void postord_rec();//parcurgere recursiva in postordine;
void nivele();
//parcurgere arbore pe nivele;
int egal(arb&);
//verifica egalitatea a doi arbori
int caut(char c); //cauta in arbore nodul cu informatia c
};

Urmtorul fiier arbinar.cpp are coninutul:


#include <iostream.h>
#include <conio.h>
#include "sc_templ.h"
//vezi seciunea 6.
#include "arbinar.h"
nod* arb::cree()
//citeste informatia, creeaza nod
{ char c;
//arbore si returneaza adresa acestuia
nod* p;
cin>>c;
if(c=='$') return(NULL);
return p=new nod(c);
}

void arb::crepreord()//functie de interfata care realizeaza


//crearea in preordine prin apelarea
{rad=crepre(NULL);} //unei functii recursive;
nod* arb::crepre(nod* p)
//functie recursiva care creeaza
//un arbore binar in preordine
{ if(p==NULL)cout<<"\nDati radacina:";
if(p=cree())
{cout<<"\n Dati fiul stang ($ pentru NULL) al lui "
<<p->info<<": ";
p->st=crepre(p);
cout<<"\n Dati fiul drept ($ pentru NULL) al lui "
<<p->info<<": ";
p->dr=crepre(p);
}
return p;
}
void arb::crenivele()
//creeaza un arbore binar pe
{
//nivele folosind o coada de
nod* p;
//asteptare in care sunt
COADA<nod*> coada(50);
//memorate adrese de noduri
cout<<"\nDati radacina : ";
if(!(p=cree())) { rad=NULL;return ;}
coada.adaug(p);
rad=p;
while(coada.nevida())
{coada.extrag(p);
cout<<"\nDati fiul stang ($ pentru NULL) al lui "
<<p->info <<" : ";
p->st=cree();
if(p->st) coada.adaug(p->st);
cout<<"\nDati fiul drept ($ pentru NULL) al lui "
<<p->info<<" : ";
p->dr=cree();
if(p->dr) coada.adaug(p->dr);
}
}
void arb::preordine()
//parcurgerea nerecursiva in
{ nod* p;
//preordine folosind o stiva de
STIVA<nod*> stiva(50);
//adrese de noduri
if(!rad) { cout<<" Arbore vid"; return; }
stiva.push(rad);
while(stiva.nevida())
{ stiva.pop(p);
cout<<p->info;
if(p->dr) stiva.push(p->dr);
if(p->st) stiva.push(p->st);
}
}
void arb::inordine()
//parcurgerea nerecursiva in
{ nod* p;
//inordine folosind o stiva de
STIVA<nod*> stiva(50);
//adrese de noduri
if(!rad) { cout<<" Arbore vid"; return;}
p=rad;
while(p || stiva.nevida())
{ while(p)
{stiva.push(p);
p=p->st;
}
stiva.pop(p);
cout<<p->info;
p=p->dr;
}
}
typedef struct
{ nod* p;
int k;
} el;

//adresa nod
//indicator cu valori 0 si 1

void arb::postordine()

//parcurgerea nerecursiva in

{ nod* p;
//postordine folosind o stiva in
el x;
//care sunt memorate elemente
STIVA<el> stiva(50);
//de tipul el
if(!rad) { cout<<" Arbore vid"; return;}
p=rad;
while(p || stiva.nevida())
{ while(p)
{ x.p=p;x.k=0;
stiva.push(x);
p=p->st;
}
stiva.pop(x);
p=x.p;
if(x.k==0)
//nu s-a parcurs inca subarborele drept
//al nodului cu adresa p;
{ x.k=1;
//se trece la parcurgerea subarborelui
//drept al nodului cu adresa p
stiva.push(x);
p=p->dr;
}
else
{cout<<p->info;p=NULL;}
}
}
void arb::nivele()
{ nod* p;

//parcurgerea pe nivele folosind o


//coada de asteptare care memoreaza
//adrese de noduri
COADA<nod*> coada(50);
if(!rad) {cout<<" Arbore vid"; return;}
coada.adaug(rad);
while(coada.nevida())
{ coada.extrag(p);
cout<<p->info;
if(p->st) coada.adaug(p->st);
if(p->dr) coada.adaug(p->dr);
}

}
void arb::preord_rec()
{ preord_rec(rad);}

//functia de interfata pentru


//parcurgerea recursiva in
//preordine

void arb::preord_rec(nod* p)//parcurgere recursiva arbore


{ if(p==NULL) return;
//binar in preordine
cout<<p->info;
preord_rec(p->st);
preord_rec(p->dr);
}
void arb::inord_rec()//functia de interfata pentru
{inord_rec(rad);}
//parcurgerea recursiva in inordine
void arb::inord_rec(nod* p)//parcurgere recursiva
{if(p==NULL) return;
//arbore binar in inordine
inord_rec(p->st);
cout<<p->info;
inord_rec(p->dr);
}
void arb::postord_rec()
{postord_rec(rad);}

//functia de interfata pentru


//parcurgerea recursiva in
//postordine

void arb::postord_rec(nod* p)
{ if(p==NULL) return;
postord_rec(p->st);
postord_rec(p->dr);
cout<<p->info;

//parcurgere recursiva
//arbore binar in
//postordine

}
int arb::caut(char x)
//se foloseste parcurgerea in
{ nod* p;
//preordine nerecursiva pentru
STIVA<nod*> stiva(50);
//cautarea nodului cu informatia
if(!rad) return 0;
//x, returneaza 1 la gasire si
stiva.push(rad);
//0 in caz contrar
while(stiva.nevida())
{stiva.pop(p);
if(p->info==x) return 1;
if(p->dr) stiva.push(p->dr);
if(p->st) stiva.push(p->st);
}
return 0;
}
int arb::egal(arb& a) //functia de interfata pentru
//verificarea egalitatii a doi arbori
//binari
{return egal(rad,a.rad);}
//returneaza valoarea 1 daca subarborii cu
//adresele p1 si p2 sunt egali si 0 in
//caz contrar
int arb::egal(nod* p1,nod *p2)
{ if(!p1 && !p2) return 1;
//cei doi subarbori sunt nuli
if( p1 && p2 && (p1->info==p2->info) &&
egal(p1->st,p2->st) && egal(p1->dr,p2->dr)) return 1;
return 0;
}
arb::arb(arb& a)
//constructorul de copiere care apeleaza
{rad=copiere(a.rad);//o functie recursiva care realizeaza
}
//copierea efectiva
nod* arb::copiere(nod* p1) //copiaza arborele cu adresa p1
{ nod* p2;
//intr-un arbore cu adresa p2
if(!p1) return NULL;
//si returneaza p2
p2=new nod(p1->info);
p2->st=copiere(p1->st);
p2->dr=copiere(p1->dr);
return p2;
}
arb::~arb() //destructorul care apeleaza o functie
{elib(rad);} //recursiva pentru dealocarea zonei de memorie
//alocate arborelui
void arb::elib(nod* p)
{ if(p==NULL) return;
elib(p->st);
elib(p->dr);
delete p;
}

//elibereaza zona alocata


//dinamic pentru arbore prin;
//parcurgere recursiva in
//postordine

Fiierul care exploateaz cele 2 fiiere anterioare:


// program client care apeleaza TAD - arbore binar
#include <iostream.h>
#include <conio.h>
#include <stdio.h>
#include "arbinar.cpp"
void main()
{char c;
cout<<"\n..... TAD - ARBORE BINAR - informatia din noduri
un caracter.....\n";
arb arb1, arb2;
cout<<"\n
Creare arbore binar pe nivele";

arb1.crenivele();
cout<<"\n Parcurgere nerecursiva in inordine:\n";
arb1.inordine();
cout<<"\n Parcurgere nerecursiva in preordine:\n";
arb1.preordine();
cout<<"\n Parcurgere nerecursiva in postordine:\n";
arb1.postordine();
cout<<"\n Parcurgere pe nivele:\n";
arb1.nivele();
cout<<"\n\n Dati informatia de cautat in arbore:";
cin>>c;
if(arb1.caut(c))
cout<<"\nNodul cu informatia "<<c<<" exista in arbore";
else
cout<<"\nNodul cu informatia "<<c<<" nu exista in arbore";
arb arb1c(arb1);
cout<<"\n\n S-a copiat arborele binar creat in alt arbore
si se verica egalitatea lor";
if(arb1.egal(arb1c))
cout<<"\n Cei doi arbori sunt egali";
else
cout<<"\n Cei doi arbori sunt diferiti";
cout<< "\n\n Creare arbore binar in preordine \n";
arb2.crepreord();
cout<<"\n Parcurgere recursiva in inordine:\n";
arb2.inord_rec();
cout<<"\n Parcurgere recursiva in preordine:\n";
arb2.preord_rec();
cout<<"\n Parcurgere recursiva in postordine:\n";
arb2.postord_rec();
cout<<"\n\n Se verifica egalitate arbore creat pe nivele cu
cel creat in preordine";
if(arb1.egal(arb2))
cout<<"\n Cei doi arbori sunt egali";
else
cout<<"\n Cei doi arbori sunt diferiti";
}

Pentru arborele din figura urmtoare se obine execuia:

Rezultate:
... TAD - ARBORE BINAR - informatia din noduri un caracter...
Creare arbore binar pe nivele
Dati radacina : A
Dati fiul stang ($ pentru NULL) al
Dati fiul drept ($ pentru NULL) al
Dati fiul stang ($ pentru NULL) al
Dati fiul drept ($ pentru NULL) al
Dati fiul stang ($ pentru NULL) al
Dati fiul drept ($ pentru NULL) al
Dati fiul stang ($ pentru NULL) al
Dati fiul drept ($ pentru NULL) al
Dati fiul stang ($ pentru NULL) al
Dati fiul drept ($ pentru NULL) al
Dati fiul stang ($ pentru NULL) al
Dati fiul drept ($ pentru NULL) al

lui
lui
lui
lui
lui
lui
lui
lui
lui
lui
lui
lui

A
A
B
B
C
C
D
D
E
E
F
F

:
:
:
:
:
:
:
:
:
:
:
:

B
C
D
$
E
F
$
$
$
$
$
$

Parcurgere
Parcurgere
Parcurgere
Parcurgere

nerecursiva in inordine:DBAECF
nerecursiva in preordine:ABDCEF
nerecursiva in postordine:DBEFCA
pe nivele:ABCDEF

Dati informatia de cautat in arbore:E


Nodul cu informatia E exista in arbore
S-a copiat arborele binar creat in alt arbore si se verica egalitatea lor
Cei doi arbori sunt egali
Creare arbore binar in preordine
Dati
Dati
Dati
Dati
Dati
Dati
Dati
Dati
Dati
Dati
Dati
Dati
Dati

radacina:A
fiul stang
fiul stang
fiul stang
fiul drept
fiul drept
fiul drept
fiul stang
fiul stang
fiul drept
fiul drept
fiul stang
fiul drept

($
($
($
($
($
($
($
($
($
($
($
($

pentru
pentru
pentru
pentru
pentru
pentru
pentru
pentru
pentru
pentru
pentru
pentru

NULL)
NULL)
NULL)
NULL)
NULL)
NULL)
NULL)
NULL)
NULL)
NULL)
NULL)
NULL)

al
al
al
al
al
al
al
al
al
al
al
al

lui
lui
lui
lui
lui
lui
lui
lui
lui
lui
lui
lui

A:
B:
D:
D:
B:
A:
C:
E:
E:
C:
F:
F:

B
D
$
$
$
C
E
$
$
F
$
$

Parcurgere recursiva in inordine:DBAECF


Parcurgere recursiva in preordine:ABDCEF
Parcurgere recursiva in postordine:DBEFCA
Se verifica egalitatea arbore creat pe nivele cu cel creat in preordine
Cei doi arbori sunt egali

Anda mungkin juga menyukai