Sunteți pe pagina 1din 93

1

Academia de Studii Economice


Bucureyti
Prof.dr. Ion Gh. Royca
Prof.dr. Bogdan Ghilic-Micu
Conf.dr. Ctlina Cocianu
Conf.dr. Marian Stoica
Lect.dr. Cristian Uscatu
Asist. Marinela Mircea
Programarea calculatoarelor.
Algoritmi n programare
Editura ASE,
Bucureyti 2007
2
1. Structuri dinamice de date. Liste 4
1.1. Reprezentarea listelor 4
1.2. Operaii primitive asupra listelor 5
1.3. Liste circulare 9
1.4. Stive si cozi 12
1.4.1. Stiva 12
1.4.2. Coada 12
2. Grafuri 14
2.1. DeIiniii si reprezentri ale graIurilor 14
2.1.1 Moduri de reprezentare a grafurilor 15
2.1.2. Reprezentarea matriceal 16
2.1.3. Reprezentarea tabelar 17
2.1.4. Reprezentarea prin intermediul listelor 18
2.2. Modaliti de parcurgere a graIurilor 18
2.2.1. Metoda de parcurgere BF (Breadth First) 19
2.2.2. Metoda de parcurgere DF (Depth First) 25
2.2.3. Parcurgerea n adncime n varianta generalizat DFG 29
2.3. Drumuri n grafuri. Conexitate 32
2.3.1 Drumuri; deIiniii 32
2.3.2. Matricea existenei drumurilor; algoritmul Roy-Warshall 34
2.3.3. Componente conexe ale unui graf 35
2.3.4. Drumuri de cost minim 37
2.4. Circuite si cicluri n graIuri si n digraIuri 42
3. Structuri arborescente 48
3.1. Grafuri de tip arbore 48
3.1.1. DeIiniii si caracterizri ale graIurilor arbori 48
3.1.2. Reprezentri si parcurgeri ale arborilor orientai 51
3.1.3. Arbori pariali. Algoritmul Kruskal 57
3.2. Arbori binari 60
3.2.1. Reprezentarea arborilor binari. Modaliti de parcurgere 60
3.2.2. Arbori de sortare 61
3.2.3. Arbori de structur 65
4. Elemente de programare orientat obiect 71
4.1. Modelul de date orientat obiect 71
4.2. Definirea claselor 77
4.3. Constructori 81
4.4. Destructori _______ 84
3
4.5. Funcii prieten 84
4.6. Derivarea claselor 87
4.6.1.Redefinirea atributelor 88
4.6.2. Redefinirea metodelor 89
4.6.3. Constructori si destructori n relaia de mostenire 89
4.6.4. Clase virtuale 90
4.6.5. Funcii virtuale 91
4.6.6. Clase abstracte 91
Bibliografie 93
4
1. Structuri dinamice de date. Liste
Organizarea de tip list corespunde unei structurri lineare a datelor, n sensul c la
nivelul Iiecrei componente exist suIicient inIormaie pentru identiIicarea urmtoarei
componente a coleciei. Datele unei mulimi structurate prin intermediul listelor snt referite de
obicei prin termenii de noduri, celule, componente etc.
1.1. Reprezentarea listelor
Reprezentarea unei liste poate Ii realizat static prin intermediul structurii de date vector.
n acest caz ordinea componentelor este dat de ordinea pe domeniul de valori corespunztor
indexrii si, n consecin, urmtoarea component este implicit speciIicat. Memorarea unei
mulimi de date d
1
, d
2
,, d
n
} prin intermediul unei structuri statice poate Ii realizat n limbajul
C utiliznd un masiv unidimensional.
Principalele dezavantaje ale utilizrii reprezentrii statice rezid din volumul de calcule
necesare eIecturii operaiilor de inserare/eliminare de noduri si din necesitatea pstrrii unei
zone de memorie alocat, indiIerent de lungimea eIectiv a listei.
Aceste dezavantaje pot Ii eliminate prin opiunea de utilizare a structurilor dinamice.
Componentele unei liste dinamice snt omogene, de tip articol. Fiecare nod, considerat separat,
este o structur eterogen, coninnd o parte de inIormaie si cmpuri de legtur care permit
identificarea celulelor vecine. Cmpurile de legtur snt reprezentate de date de tip reIerin
(adres).
n cazul listelor cu un singur cmp de legtur (simplu nlnuite), valoarea cmpului
indic adresa nodului urmtor, n timp ce n cazul listelor cu dubl legtur (dublu nlnuite),
valorile memorate n cmpurile de legtur snt adresele componentelor care preced si, respectiv,
urmeaz celulei. n ambele situaii, cmpul de legtur pentru indicarea celulei urmtoare
corespunztor ultimei componente a listei are valoarea NULL n cazul listelor ,deschise
(lineare) si respectiv indic adresa primei componente din list n cazul listelor ,nchise
(circulare).
Declararea tipurilor de date C pentru deIinirea structurilor de liste dinamice simplu si
respectiv dublu nlnuite este:
a) List simplu nlnuit
t ypedef st r uct nod{
t i p_i nf or mat i e i nf ;
st r uct nod *l eg;
} l i st , *l i st a;
b) List dublu nlnuit
t ypedef st r uct nod{
t i p_i nf or mat i e i nf ;
st r uct nod *l s, *l d;
} l i st , *l i st a;
unde tip_informatie este numele tipului de date C utilizat pentru memorarea Iiecrei date din
mulimead
1
, d
2
,, d
n
}.
n cele ce urmeaz vom considera c t i p_i nf or mat i e este tipul C i nt .
5
1.2. Operaii primitive asupra listelor
Accesul la inIormaia stocat ntr-o variabil de tip list revine la eIectuarea urmtoarelor
operaii primitive: regsirea nodului (dac exist) care corespunde unei chei date (condiie impus
asupra valorii cmpului de inIormaie), inserarea unei noi componente n list, eliminarea
componentei (componentelor) cu proprietatea c valorile cmpurilor de inIormaie satisIac o
anumit cerin si nlocuirea cmpului de inIormaie corespunztor unei componente printr-o
inIormaie dat (modiIicat).
Accesarea componentelor unei liste reprezentat printr-o structur static poate Ii
realizat att secvenial, ct si direct, utiliznd valorile indicelui considerat pentru indexare, n timp
ce accesarea componentelor unei liste dinamice se realizeaz de regul numai secvenial, ncepnd
cu prima component si continund cu urmtoarele, pe baza valorilor cmpurilor de legtur.
Convenional, numim cap al listei dinamice pointerul a crui valoare este adresa primei
componente a listei. n continuare ne vom referi exclusiv la liste dinamice, studiul listelor
reprezentate prin intermediul vectorilor fiind propus cititorului.
1. Parcurgerea datelor memorate ntr-o list
Funcia C parc implementeaz parcurgerea unei liste dinamice n varianta simplu
nlnuit si n cazul listelor dublu nlnuite. Se presupune c declarrile de tip pentru deIinirea
structurilor de liste menionate anterior snt globale, relativ la procedurile descrise n continuare.
a)Lista reprezentat prin structur dinamic simplu nlnuit
voi d par c( l i st a cap)
{ i f ( cap)
{ pr i nt f ( " %i " , cap- >i nf ) ;
par c( cap- >l eg) ;
}
}
b)Lista reprezentat prin structur dinamic dublu nlnuit
voi d par c( l i st a cap)
{ i f ( cap)
{ pr i nt f ( " %i " , cap- >i nf ) ;
par c( cap- >l s) ;
}
}
2. Regsirea unei date ntr-o colecie memorat ntr-o list
Funcia C cauta calculeaz adresa nodului n care este gsit elementul cutat. Dac
valoarea cutat nu se regseste printre elementele listei, Iuncia returneaz valoarea NULL.
a) Lista reprezentat prin structur dinamic simplu nlnuit
l i st a caut a( l i st a cap, i nt i nf o)
{ i f ( cap==NULL) r et ur n NULL;
el se i f ( cap- >i nf ==i nf o) r et ur n cap;
el se r et ur n caut a( cap- >l eg, i nf o) ;
}
b) Lista reprezentat prin structur dinamic dublu nlnuit
l i st a caut a( l i st a cap, i nt i nf o)
{ i f ( cap==NULL) r et ur n NULL;
el se i f ( cap- >i nf ==i nf o) r et ur n cap;
el se r et ur n caut a( cap- >l s, i nf o) ;
}
6
3. Inserarea unei date ntr-o list
Includerea unei noi componente ntr-o list poate Ii realizat, n Iuncie de cerinele
problemei particulare, la nceputul listei, dup ultima component din list, naintea/dup o
component cu proprietatea c valoarea cmpului de inIormaie ndeplineste o anumit condiie.
Deoarece prin inserarea unei componente se poate ajunge la depsirea spaiului disponibil
de memorie, este necesar veriIicarea n prealabil dac este posibil inserarea sau nu (dac se
poate aloca spaiu de memorie pentru componenta de inserat). n continuare ne vom referi la liste
dinamice simplu nlnuite. Operaiile de inserare n cazul listelor dinamice dublu nlnuite pot
Ii realizate similar cazului listelor simplu nlnuite, cu speciIicarea ambelor cmpuri de adres ale
nodurilor.
Pentru exempliIicarea operaiei de inserare snt prezentate Iunciile de inserare la
nceputul listei, inserare dup ultimul element al listei si inserarea unei celule dup un nod cu
inIormaie dat.
Inserarea la nceputul listei
Funcia C inserare_la_inceput returneaz valoarea 1 dac adugarea unui nou element
este posibil (spaiul de memorie este suIicient pentru o nou alocare), altIel returneaz 0. n
cazul n care inserarea este posibil, prin apelul Iuncii este realizat adugarea unui nou nod la
nceputul listei.
i nt i nser ar e_l a_i nceput ( l i st a *cap, i nt i nf o)
{ l i st a nou;
i f ( nou=( l i st a) mal l oc( si zeof ( l i st ) ) )
{ nou- >i nf =i nf o;
nou- >l eg=*cap;
*cap=nou;
r et ur n 1;
}
r et ur n 0;
}
Inserarea dup ultima component a unei liste
Funcia C inserare_la_sfarsit returneaz 1 dac si numai dac este posibil o inserare,
altIel calculeaz 0. Pentru inserarea unui nou nod n list dup ultima celul este necesar calculul
ultimului nod al listei, notat p.
i nt i nser ar e_l a_sf ar si t ( l i st a *cap, i nt i nf o)
{ l i st a nou;
i f ( nou=( l i st a) mal l oc( si zeof ( l i st ) ) )
{ nou- >l eg=NULL; nou- >i nf =i nf o;
i f ( cap==NULL) *cap=nou;
el se
{ f or ( l i st a p=*cap; p- >l eg; p=p- >l eg) ;
p- >l eg=nou;
}
r et ur n 1;
}
r et ur n 0;
}
Inserarea unei informaii dup o celul cu informaie cunoscut
Inserarea unui nou nod ntr-o list identiIicat prin variabila cap dup o celul p cu
inIormaie cunoscut, infod, poate Ii realizat astIel. Este apelat Iuncia de cutare cauta, care
calculeaz nodul p cu proprietatea c inIormaia memorat n p este infodat. Dac p este adresa
7
vid sau dac spaiul de memorie disponibil nu este suIicient, inserarea nu poate Ii realizat. n
caz contrar, este inserat un nou nod ntre celulele p si p->leg.
i nt i nser ar e_dupa_i nf or mat i e( l i st a cap, i nt i nf o, i nt i nf od)
{
l i st a nou, p;
i f ( nou=( l i st a) mal l oc( si zeof ( l i st ) ) )
i f ( p=caut a( cap, i nf od) ) {
nou- >i nf =i nf o;
nou- >l eg=p- >l eg;
p- >l eg=nou;
r et ur n 1;
}
r et ur n 0;
}
4. Eliminarea unei date dintr-o list.
Modificarea coninutului unei liste prin eliminarea uneia sau mai multor componente
poate Ii descris secvenial, astIel nct este suIicient s dispunem de o procedur care realizeaz
eliminarea unei singure componente.
Criteriile de eliminare pot fi formulate diferit, cele mai uzuale Iiind: prima component,
ultima component, prima component care ndeplineste o anumit condiie, respectiv
componenta care precede/urmeaz primei componente care ndeplineste o condiie dat.
n aceste cazuri este necesar veriIicarea existenei n lista considerat a componentei ce
trebuie eliminat. Verificareaasigur si testarea Iaptului c lista prelucrat este vid sau nu.
InIormaia i atasat nodului eliminat din list reprezint dat de iesire pentru orice modul
de eliminare, n cazul n care i nu este cunoscut naintea eliminrii (de exemplu, atunci cnd este
solicitat eliminarea unei celule care conine o inIormaie dat) .
Eliminarea unui nod p poate Ii realizat logic sau fizic. Eliminarea logic a celulei p este
efectuat excluznd p din lista dinamic prin setarea legturii nodului care precede p pe adresa
succesorului lui p, dac p nu este adresa primului element al listei, cap, respectiv prin atribuirea
adresei primului element al listei cu cap->leg, n caz contrar.
Eliminarea cu stergere Iizic unui nod p presupune redenumirea acelui nod n scopul
eliberrii memoriei ocupate de p si eIectuarea operaiilor descrise n cadrul procesului de
eliminare logic.
n continuare snt prezentate urmtoarele tipuri de eliminri, cu stergere Iizic.
Eliminarea primei componente a unei liste
Funcia C elimina_de_la_inceput returneaz 1 dac lista nu este vid, deci eliminarea
primului nod este posibil, altIel returneaz 0. Dac lista conine mcar un nod, este eliminat
prima celul.
i nt el i mi na_de_l a_i nceput ( l i st a *cap, i nt *i nf o)
{ i f ( *cap)
{ l i st a aux=*cap;
*i nf o=aux- >i nf ;
*cap=( *cap) - >l eg;
f r ee( aux) ;
r et ur n 1;
}
r et ur n 0;
}
8
Eliminarea ultimei componente a unei liste
Similar operaiei de inserare a unui nod dup ultima celul a unei liste, eliminarea
ultimului nod presupune determinarea acelei celule p cu proprietatea c p->leg este NULL.
Funcia C elimina_ultim returneaz 1 dac lista nu este vid, caz n care este eliminat cu stergere
ultimul nod al listei. Dac lista este vid, Iuncia calculeaz valoarea 0.
i nt el i mi na_ul t i m( l i st a *cap, i nt *i nf o)
{ i f ( *cap)
{ i f ( ( *cap) - >l eg)
{ f or ( l i st a p=*cap; p- >l eg- >l eg; p=p- >l eg) ;
*i nf o=p- >l eg- >i nf ;
f r ee( p- >l eg) ;
p- >l eg=NULL;
}
el se
{ *i nf o=( *cap) - >i nf ;
f r ee( *cap) ;
*cap=NULL;
}
r et ur n 1;
}
r et ur n 0;
}
Eliminarea primei celule a unei liste care are informaia egal cu o informaie dat
Pentru realizarea acestei operaii se poate proceda astfel. Snt calculate aux si p, unde aux
este nodul care precede celulei cu inIormaie dat n lista din care este eIectuat eliminarea
(Iuncia C cautaprecedent) si p=aux->leg.. Dac p este NULL, atunci eliminarea este imposibil.
Dac aux este NULL, atunci eliminarea revine la extragerea cu stergere a primului nod din list,
altIel este eliminat celula p, succesoare a lui aux n list. Funcia C elimina_informatie
implementeaz operaia de eliminare a unui nod cu inIormaie dat, info, din lista identiIicat prin
parametrul cap.
l i st a caut apr ecedent ( l i st a cap, i nt i nf o, l i st a *aux)
{ l i st a p;
i f ( cap==NULL) r et ur n NULL;
el se { f or ( p=NULL, *aux=cap; ( *aux) &&
( ( *aux) - >i nf - i nf o) ; p=*aux, *aux=( *aux) - >l eg) ;
i f ( ( *aux) ==NULL) r et ur n NULL;
r et ur n p;
}
}
i nt el i mi na_i nf or mat i e( l i st a *cap, i nt i nf o)
{ l i st a aux, p;
p=caut apr ecedent ( *cap, i nf o, &aux) ;
i f ( aux==*cap)
{ *cap=( *cap) - >l eg;
f r ee( aux) ;
r et ur n 1;
}
el se
i f ( p)
{ p- >l eg=aux- >l eg;
f r ee( aux) ;
r et ur n 1;
}
r et ur n 0;
}
9
Eliminarea nodului care succede primei componente al crei cmp de informaie
este cunoscut
Funcia C elimina_dupa_informatie returneaz valoarea 1 dac eliminarea este posibil,
altIel calculeaz valoarea 0. n situaia n care inIormaia infodat a Iost gsit n cmpul
corespunztor nodului nodul p (p nu este NULL) si p are succesor n list, este realizat
eliminarea nodului p->leg.
int elimin_dupa_informatie(lista cap,int *info, int
i nf odat )
{ l i st a aux, p;
p=caut a( cap, i nf odat ) ;
i f ( ( p) &&( p- >l eg) )
{ aux=p- >l eg;
p- >l eg=aux- >l eg;
*i nf o=aux- >i nf ;
f r ee( aux) ;
r et ur n 1;
}
r et ur n 0;
}
1.3. Liste circulare
n anumite situaii este preIerabil renunarea la structura de tip linear a listelor si utilizarea
unei legturi de la ultima component ctre capul listei, rezultnd structura de list circular.
Principalul avantaj al utilizrii acestui tip de structur rezid din posibilitatea de accesare
oricrui alt element al listei pornind din oriceelement. Dac nodul cutat este situat dup nodul
curent, este iniiat un proces de cutare similar listelor lineare. n caz contrar, nodul poate Ii
accesat prin parcurgerea listei de la primul su element, care, n procesul de cutare, este atins
dup parcurgerea n ntregime a listei, ncepnd de la nodul curent.
n continuare snt prezentate Iunciile C pentru realizarea unor operaii de baz n lucrul cu
liste circulare.
#i ncl ude<st di o. h>
#i ncl ude<coni o. h>
#i ncl ude<al l oc. h>
t ypedef st r uct nod
{ i nt i nf ;
st r uct nod *l eg;
} l i st , *l i st a;
i nt i nser ar e_l a_i nceput ( l i st a *, i nt ) ;
i nt st er ger e_l a_i nceput ( l i st a *, i nt *) ;
i nt i nser ar e_l a_sf ar si t ( l i st a *, i nt ) ;
i nt st er ger e_l a_sf ar si t ( l i st a *, i nt *) ;
voi d par c( l i st a) ;
l i st a caut a( l i st a, i nt ) ;
voi d mai n( )
{
cl r scr ( ) ;
i nt n, i nf o;
l i st a cap=NULL;
pr i nt f ( " Numar ul de nodur i : " ) ;
scanf ( " %i " , &n) ;
pr i nt f ( " I nt r oducet i i nf or mat i i l e\ n" ) ;
f or ( i nt i =0; i <n; i ++) {
scanf ( " %i " , &i nf o) ;
10
i f ( i nser ar e_l a_i nceput ( &cap, i nf o) ) ;
el se
{pr i nt f ( " \ n Spat i u i nsuf i ci ent \ n" ) ;
r et ur n;
}
}
pr i nt f ( " \ nLi st a r ezul t at a\ n" ) ;
par c( cap) ;
pr i nt f ( " \ n\ nLi st a dupa ext r ager ea pr i mul ui
el ement : \ n" ) ;
i f ( st er ger e_l a_i nceput ( &cap, &i nf o) ) par c( cap) ;
el se pr i nt f ( " \ nEr oar e: l i st a vi da" ) ;
pr i nt f ( " \ n\ nI nf or mat i a nodul ui de i nt r odus l a
sf ar si t : " ) ;
scanf ( " %i " , &i nf o) ;
i f ( i nser ar e_l a_sf ar si t ( &cap, i nf o) ) {
pr i nt f ( " Li st a r ezul t at a\ n" ) ;
par c( cap) ;
}
el se
pr i nt f ( " \ n Spat i u i nsuf i ci ent \ n" ) ;
pr i nt f ( " \ n\ nLi st a dupa ext r ager ea ul t i mul ui
el ement : " ) ;
i f ( st er ger e_l a_sf ar si t ( &cap, &i nf o) ) {
pr i nt f ( " \ nI nf or mat i a ext r asa %i \ nLi st a
r ezul t at a: " , i nf o) ;
par c( cap) ;
}
el se pr i nt f ( " \ nEr oar e: Li st a vi da" ) ;
get ch( ) ;
}
voi d par c( l i st a cap)
{
l i st a p=cap;
i f ( cap) {
pr i nt f ( " %i " , cap- >i nf ) ;
f or ( p=p- >l eg; p- cap; p=p- >l eg)
pr i nt f ( " %i " , p- >i nf ) ;
}
el se pr i nt f ( " \ nLi st a vi da" ) ;
}
l i st a caut a( l i st a cap, i nt i nf o)
{
i f ( cap==NULL) r et ur n NULL;
i f ( cap- >i nf ==i nf o) r et ur n cap;
f or ( l i st a p=cap- >l eg; p! =cap; p=p- >l eg)
i f ( p- >i nf ==i nf o) r et ur n p;
r et ur n NULL; }
i nt i nser ar e_l a_i nceput ( l i st a *cap, i nt i nf o)
{
l i st a nou, ul t i m;
i f ( nou=( l i st a) mal l oc( si zeof ( l i st ) ) ) {
nou- >i nf =i nf o;
nou- >l eg=*cap;
i f ( *cap) {
f or ( ul t i m=*cap; ul t i m- >l eg! =( *cap) ; ul t i m=ul t i m- >l eg) ;
ul t i m- >l eg=nou;
}
el se nou- >l eg=nou;
*cap=nou;
r et ur n 1;
11
}
r et ur n 0;
}
i nt st er ger e_l a_i nceput ( l i st a *cap, i nt *i nf o)
{
i f ( *cap) {
l i st a aux=*cap;
*i nf o=aux- >i nf ;
f or ( l i st a ul t i m=*cap;
ul t i m- >l eg! =( *cap) ; ul t i m=ul t i m- >l eg) ;
i f ( ul t i m==( *cap) ) *cap=NULL;
el se{
*cap=( *cap) - >l eg;
ul t i m- >l eg=*cap;
}
f r ee( aux) ;
r et ur n 1;
}
r et ur n 0;
}
i nt i nser ar e_l a_sf ar si t ( l i st a *cap, i nt i nf o)
{
l i st a nou, ul t i m;
i f ( nou=( l i st a) mal l oc( si zeof ( l i st ) ) ) {
nou- >l eg=*cap; nou- >i nf =i nf o;
i f ( *cap==NULL) {
*cap=nou;
( *cap) - >l eg=*cap;
}
el se{
f or ( ul t i m=*cap; ul t i m- >l eg! =( *cap) ; ul t i m=ul t i m- >l eg) ;
ul t i m- >l eg=nou;
}
r et ur n 1;
}
r et ur n 0;
}
i nt st er ger e_l a_sf ar si t ( l i st a *cap, i nt *i nf o)
{
i f ( *cap) {
i f ( ( *cap) - >l eg! =( *cap) ) {
f or ( l i st a pul t i m=*cap;
pul t i m- >l eg- >l eg! =( *cap) ; pul t i m=pul t i m- >l eg) ;
*i nf o=pul t i m- >l eg- >i nf ;
f r ee( pul t i m- >l eg) ;
pul t i m- >l eg=( *cap) ;
}
el se{
*i nf o=( *cap) - >i nf ;
f r ee( *cap) ;
*cap=NULL;
}
r et ur n 1;
}
r et ur n 0;
}
12
1.4. Stive yi cozi
Asa cum a rezultat din subcapitolele precedente, operaiile de inserare si eliminare snt
permise la oricare dintre componentele unei liste. O serie de aplicaii pot Ii modelate utiliznd
liste lineare n care introducerea si respectiv eliminarea inIormaiilor este permis numai la
capete. n acest scop au Iost introduse tipurile de list stiv si coad prin impunerea unui tip de
organizare a aplicrii operaiilor de inserare si eliminare.
1.4.1. Stiva
Se numeste stiv o list organizat astIel nct operaiile de inserare si eliminare snt
permise numai la prima component. Acest mod de organizare corespunde unei gestiuni LIFO
(Last In First Out) a inIormaiei stocate.
Operaiile de baz eIectuate asupra unei stive pot Ii realizate similar cazului listelor
dinamice lineare, innd cont c inserarea/extragerea unui element snt posibile numai n prima
poziie (vezi modulul de inserare la nceputul unei liste si respectiv Iuncia de extragere a
primului nod dintr-o list, prezentate n 1.2).
1.4.2. Coada
Se numeste coad o list organizat astIel nct operaia de inserare este permis la ultima
component, iar operaia de eliminare este permis numai la prima component. Acest mod de
organizare corespunde unei gestiuni FIFO (First In First Out) a inIormaiei stocate.
Implementarea unei liste de tip coad poate Ii eIectuat att printr-o structur static
(masiv unidimensional), ct si printr-o structur dinamic de tip list. Pentru optimizarea
operaiilor de inserare/extragere, n cazul implementrii cozilor prin structuri dinamice lineare,
este necesar utilizarea a dou inIormaii: adresa primei componente si adresa ultimei
componente. Aceste inIormaii pot Ii meninute explicit prin utilizarea a doi pointeri sau prin
utilizarea unui pointer si a unei structuri de list circular.
O variant alternativ de implementare a unei liste de tip coad dinamic este obinut
prin considerarea unei liste circulare, cu memorarea adresei ultimului element.
n continuare snt prezentate operaiile de inserare si extragere a unei inIormaii dintr-o
list liniar de tip coad.
#i ncl ude<st di o. h>
#i ncl ude<coni o. h>
#i ncl ude<al l oc. h>
t ypedef st r uct nod{
i nt i nf ;
st r uct nod *l eg;
} l i st , *l i st a;
i nt i nser ar e( l i st a *, l i st a *, i nt ) ;
i nt ext r ager e( l i st a *, l i st a *, i nt *) ;
voi d par c( l i st a) ;
voi d mai n( )
{
cl r scr ( ) ;
i nt n, i nf o;
l i st a cap=NULL, ul t i m=NULL;
pr i nt f ( " Numar ul de nodur i : " ) ;
scanf ( " %i " , &n) ;
13
pr i nt f ( " I nt r oducet i i nf or mat i i l e\ n" ) ;
f or ( i nt i =0; i <n; i ++) {
scanf ( " %i " , &i nf o) ;
i f ( i nser ar e( &cap, &ul t i m, i nf o) ) ;
el se
{pr i nt f ( " \ n Spat i u i nsuf i ci ent \ n" ) ;
r et ur n;
}
}
pr i nt f ( " \ nCoada r ezul t at a\ n" ) ;
par c( cap) ;
pr i nt f ( " \ n\ nCoada dupa o ext r ager e: \ n" ) ;
i f ( ext r ager e( &cap, &ul t i m, &i nf o) ) par c( cap) ;
el se pr i nt f ( " \ nEr oar e: Coada vi da" ) ;
get ch( ) ;
}
voi d par c( l i st a cap)
{
i f ( cap) {
pr i nt f ( " %i " , cap- >i nf ) ;
par c( cap- >l eg) ;
}
}
i nt ext r ager e( l i st a *cap, l i st a *ul t i m, i nt *i nf o)
{
i f ( *cap) {
l i st a aux=*cap;
*i nf o=aux- >i nf ;
i f ( ( *ul t i m) ==( *cap) ) *cap=*ul t i m=NULL;
el se *cap=( *cap) - >l eg;
f r ee( aux) ;
r et ur n 1;
}
r et ur n 0;
}
i nt i nser ar e( l i st a *cap, l i st a *ul t i m, i nt i nf o)
{
l i st a nou;
i f ( nou=( l i st a) mal l oc( si zeof ( l i st ) ) ) {
nou- >i nf =i nf o; nou- >l eg=NULL;
i f ( *cap==NULL) *cap=*ul t i m=nou;
el se{
( *ul t i m) - >l eg=nou;
( *ul t i m) =nou;
}
r et ur n 1;
}
r et ur n 0; }
14
2. Grafuri
Grafurile snt structuri de date cu aplicaii n multe domenii ale inIormaticii, algoritmii
pentru reprezentarea si prelucrarea graIurilor Iiind considerai Iundamentali n acest domeniu. n
subcapitolul 2.1 snt prezentate principalele noiuni ale domeniului, precum si modalitile uzuale
de reprezentare a structurii de graf. n continuare snt descrise tehnicile de parcurgere a grafurilor
n lime si n adncime. Traversarea n adncime a graIurilor determin obinerea unei clasiIicri
a muchiilor, n Iuncie de care pot Ii derivate diIerite proprieti ale graIurilor. VeriIicarea
conexitii si calculul drumurilor n graIuri snt tratate n subcapitolul 2.3. n finalul capitolului
este studiat problema determinrii circuitelor si ciclurilor n graIuri si digraIuri.
2.1. Definiii yi reprezentri ale grafurilor
Definiia 2.1.1. Se numeste graf sau graf neorientat o structur G=(V,E), unde V este o
mulime nevid iar E este o submulime posibil vid a mulimii perechilor neordonate cu
componente distincte din V.
Elementele mulimii V se numesc vrfuri, iar obiectele mulimii E se numesc muchii.
Dac eE, uv not. v) (u, e = , vrfurile u si v se numesc extremiti ale lui e, muchia e fiind
determinat de vrfurile u si v. Dac e=uvE se spune c vrfurile u, v snt incidente cu muchia e.
Definiia 2.1.2. Fie G=(V,E) graf. Vrfurile u, v snt adiacente n G dac uvE.
Definiia 2.1.3. Graful G=(V,E) este graI Iinit, dac V este o mulime Iinit.
n cadrul acestui capitol vor Ii considerate n exclusivitate graIurile Iinite, chiar dac
acest lucru nu va fi precizat n mod explicit.
Definiia 2.1.4. Fie G
i
=(V
i
,E
i
), i=1,2 grafuri. G
2
este un subgraf al grafului G
1
dac
1 2
V V si
1 2
E E . G
2
este este un graf parial al lui G
1
dac V
2
=V
1
si G
2
este subgraf al lui
G
1
.
Definiia 2.1.5. Un digraf este o structur D=(V,E), unde V este o mulime nevid de
vrfuri, iar E este o mulime posibil vid de perechi ordonate cu componente elemente distincte
din V. Elementele mulimii E snt numite arce sau muchii ordonate. Un graf direcionat este o
structur D=(V,E), unde V este o mulime nevid de vrfuri, iar E este o mulime posibil vid de
perechi ordonate cu componente elemente din V, nu neaprat distincte. Evident, orice digraI este
un graI direcionat.
Terminologia utilizat relativ la digraIuri este similar celei corespunztoare graIurilor.
n continuare vom reIeri prin muchie si elementele mulimii E a unui graI direcionat, n situaia
n care este tratat cazul unui graI oarecare (neorientat sau direcionat).
15
Definiia 2.1.6. Se numeste graf ponderat o structur (V,E,W), unde G=(V,E) este graf si
W este o Iuncie deIinit prin ( ) , 0 E : W . Funcia W este numit pondere si ea asociaz
Iiecrei muchii a graIului un cost/cstig al parcurgerii ei.
Definiia 2.1.7. Fie G=(V,E) un graf, u,vV. Secvena de vrfuri :u
0
,u
1
,..,u
n
este un
u-v drum dac u
0
=u, u
n
=v, u
i
u
i+1
E pentru toi i, n i 0 .
Definiia 2.1.8. Fie G=(V,E) un graf. Elementul vV se numeste vrf izolat dac,
pentru orice eE, u nu este incident cu e.
2.1.1 Moduri de reprezentare a grafurilor
Cea mai simpl reprezentare a unui graI este cea intuitiv, grafic, fiecare vrf este
figurat printr-un punct, respectiv muchiile snt reprezentate prin segmentele de dreapt, orientate
(n cazul digraIurilor) sau nu si etichetate (n cazul graIurilor ponderate) sau nu, avnd ca
extremiti punctele corespunztoare vrIurilor care o determin
Exemple
2.1.1. Fie G=(V,E) graf, cu V={1,2,3,4,5,6}, E(1,2),(1,3),(2,5),(3,5),(5,6)}. O posibil
reprezentare graIic este,
1
2
3
4
5
6
2.1.2. Fie D=(V,E) digraf, V={1,,5}, E={(1,2), (1,3), (1,5), (2,5), (3,5), (4,1), (5,4)}.
Digraful poate fi reprezentat grafic astfel,
1
2
3
5
4
2.1.3. Fie D=(V,E) graI direcionat, V={1,2,3,4,5}, E={(1,2), (1,3), (1,5) (2,5), (3,5),
(4,4)}. Reprezentarea graIic este,
16
1
2
3
4
5
2.1.4. Fie G=(V,E,W) graf ponderat, V={1,2,3,4}, E={(1,2), (1,3), (1,4), (2,3), (2,4)},
W((1,2))5, W((1,3))1, W((1,4))7, W((2,3))4, W((2,4))2. O posibil reprezentare graIic
este:
1
3 2
4
5 1
2
7
4
n scopul reprezentrii graIurilor n memoria calculatorului snt utilizate n general
urmtoarele structuri de date.
2.1.2. Reprezentarea matriceal
GraIurile, digraIurile si graIurile direcionate pot Ii reprezentate prin matricea de
adiacen. Dac G=(V,E ) este graI, digraI sau graI direcionat cu n V = , atunci matricea de
adiacen AM
nxn
({0,1}) are componentele,
( )
_
_
_
=
altfel , 0
E v , v dac , 1
a
j i
ij
,
unde v
i
, v
j
reprezint cel de-al i-lea, respectiv cel de-al j-lea nod din V. n cazul unui graf
neorientat, matricea de adiacen este simetric.
Exemplu
2.1.5. Graful din exemplul 2.1.1, digraful din exemplul 2.1.2 si graIul direcionat din
exemplul 2.1.3 snt reprezentate prin matricele de adiacen,
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
=
0 1 0 0 0 0
1 0 0 1 1 0
0 0 0 0 0 0
0 1 0 0 0 1
0 1 0 0 0 1
0 0 0 1 1 0
A (2.1.1),
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
=
1 1 0 0 0
0 0 0 0 1
1 0 0 0 0
1 0 0 0 0
1 0 1 1 0
A (2.1.2),
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
=
0 0 0 0 0
0 1 0 0 0
1 0 0 0 0
1 0 0 0 0
1 0 1 1 0
A (2.1.3)
n cazul graIurilor ponderate, reprezentarea poate Ii realizat prin matricea ponderilor.
Dac G=(V,E,W) este graf ponderat, n V = , W M
nxn
((0,)) are componentele,
17
( ) ( )
_
_
_
=
altfel ,
E v , v dac , ) v , v ( W
w
j i j i
j , i

unde v
i
, v
j
reprezint cel de-al i-lea, respectiv cel de-al j-lea nod din V, 0 = , dac
ponderea are semniIicaia de cstig, respectiv = n cazul n care se doreste reprezentarea
costurilor ca ponderi ale grafului.
Exemplu
2.1.6. Presupunnd c ponderile reprezint costuri, matricea de reprezentare a graIului
din exemplul 2.1.4. este
_
_
_
_
_
_
_
_
_
_
_
_
_
_

=
2 7
4 1
2 4 5
7 1 5
W .
2.1.3. Reprezentarea tabelar
Reinnd muchiile prin intermediul extremitilor si eventual valoarea ponderii ei, se
obine reprezentarea tabelar, mai economic din punctul de vedere al spaiului de memorie
necesar. Dac graIul conine vrIuri izolate atunci este necesar pstrarea acestora ntr-un vector
suplimentar VS. Mulimea muchiilor este reinut ntr-o matrice A cu E linii si c coloane, unde
c2 dac graIul nu este ponderat, altIel c3. n primele dou coloane se scriu perechile de vrfuri
ce determin muchiile, n cazul graIurilor ponderate cea de-a treia coloan conine valoarea
ponderii muchiei respective.
Exemple
2.1.7. Graful din exemplul 2.1.1 poate fi reprezentat astfel, VS=(4),
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
=
6 5
5 3
5 2
3 1
2 1
A
2.1.8. Digraful din exemplul 2.1.2 este reprezentat prin
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
=
4 5
1 4
5 3
5 2
5 1
3 1
2 1
A .
18
2.1.9. GraIul direcionat din 2.1.3. este reprezentat prin
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
=
4 4
5 3
5 2
5 1
3 1
2 1
A .
2.1.10. Graful ponderat din exemplul 2.1.4. nu are vrfuri izolate, deci este reprezentat
prin intermediul matricei
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
=
2 4 2
7 4 1
4 3 2
1 3 1
5 2 1
A .
2.1.4. Reprezentarea prin intermediul listelor
Aceast reprezentare permite utilizarea economic a spaiului de memorare si, n anumite
cazuri, implementri mai eIiciente pentru anumite clase de algoritmi. Vrfurile grafului snt
memorate ntr-o list, Iiecare nod al listei N coninnd o reIerin spre lista vecinilor vrfului
memorat ca inIormaie n N.
Dac graIul nu este ponderat, el poate Ii reprezentat prin structura list de liste, si anume:
nodurile grafului se trec ntr-o list Lnod, Iiecare celul avnd structura,
inIormaie legtur vecini legtur nod urmtor
unde,
cmpul informaie conine identiIicatorul nodului;
legtur vecini reprezint reIerina spre nceputul listei vecinilor;
legtur nod urmtor conine adresa urmtoarei celule din lista L_nod.
Un graI ponderat poate Ii reprezentat n mod similar, cu diIerena c, Iiecare celul din
lista vecinilor conine si ponderea muchiei respective (muchia care are ca extremiti vrful referit
prin identificatorul de nod din lista vecinilor si respectiv vrIul indicat de inIormaia acelei celule
din Lnod ce conine adresa primului element al listei vecinilor).
2.2. Modaliti de parcurgere a grafurilor
Modalitatea de vizitare a tuturor vrfurilor grafului n care fiecare vrf al grafului este
vizitat o singur dat se numeste parcurgere sau traversare. n acest paragraf snt prezentate
metodele de parcurgere BF (n lime), DF (n adncime) si metoda DF generalizat, notat
DFG.
Primele dou metode de parcurgere snt aplicate graIurilor neorientate respectiv
graIurilor direcionate si presupun selectarea unui vrI iniial v
0
si identiIicarea acelor vrIuri
ale grafului v cu proprietatea c exist cel puin un drum de la vrIul iniial ctre v. Grafurile
cu proprietatea c oricare dou vrIuri snt conectate printr-un drum se numesc grafuri conexe
si snt prezentate n 2.3. Dac graIul este conex, atunci prin aplicarea metodelor de
parcurgere vor Ii identiIicate toate vrIurile graIului. Cele dou modaliti de parcurgere snt
prezentate n continuare n cazul graIurilor neorientate, extinderea la digraIuri si graIuri
direcionate Iiind imediat. Studiul proprietii metodei BF de a calcula distanele minim ntre
19
orice vrI al graIului conectat de vrIul iniial si vrIul iniial este prezentat n cazul grafurilor
oarecare.
Parcurgerea DFG presupune vizitarea tuturor vrIurilor unui graI sau graI direcionat
prin aplicarea metodei DF tuturor vrIurilor care, dup ultima traversare DF, nu au Iost nc
vizitate.
2.2.1. Metoda de parcurgere BF (Breadth First)
Traversarea BF presupune parcurgerea in lime a graIului, n sensul c, vrfurile
grafului snt prelucrate n ordinea cresctoare a distanelor la vrIul iniial (teorema 2.2.1).
Distana de la u la v, notat ( ) v , u , este numrul de muchii ale unui cel mai scurt u-v drum.
La momentul iniial vrf curent este v
0
. Deoarece vrful curent la fiecare moment
trebuie s Iie unul dintre vrIurile aIlate la distan minim de v
0
se poate proceda n modul
urmtor: iniial lui v
0
i se asociaz valoarea 0, j { 0 v d
0
= si Iiecrui vrf
0
v v i se asociaz
valoarea , j { = v d . Dac valoarea asociat vrfului curent este m, atunci Iiecruia dintre
vecinii acestuia de valoare li se asociaz valoarea m+1. Se observ c, dac dup ce toate
vrfurile de valoare m au Iost considerate si nici unui vrf nu i-a Iost recalculat valoarea,
atunci toate vrfurile conectate cu v
0
au fost vizitate, deci calculul se ncheie.
Exemple
2.2.1. Fie graful,
1
2
5
6
7
3
4
si v
0
=1.Valorile calculate prin aplicarea metodei prezentate snt,
vrf
d
1 2 3 4 5 6 7
0 0




1 0 1 1 1 1
2 0 1 1 1 2 2 1
0 1 1 1 2 2 1
20
2.2.2. Fie graful,
1
2
3
4
5 7
6
8
9 10
11
si v
0
1. Se observ c vrfurile 8, 9, 10 si 11 nu snt conectate cu vrIul iniial.
Valorile rezultate prin aplicarea metodei snt:
vrf
d
1 2 3 4 5 6 7 8 9 10 11
0 0
1 0 1 1 1 1
2 0 1 1 2 1 2 1
0 1 1 2 1 2 1
Se observ c valorile lui d calculate n Iinal reprezint numrul de muchii
corespunztor unui cel mai scurt drum care conecteaz vrIul iniial cu vrful respectiv, pentru
vrfurile neconectate cu v
0
valoarea d[v
0
| rezultat la terminarea calculului este .
Fie G=(V,E) un graf, n V = . O alternativ de implementare a metodei BF este
construit prin utilizarea urmtoarelor structuri de date,
A matricea de adiacen a graIului;
o structur de tip coad, C, n care snt introduse vrIurile ce urmeaz a Ii vizitate si
procesate (n sensul cercetrii vecinilor lor);
un vector c cu n componente, unde,
_
_
_
=
, 0
, 1
i
c
Componentele vectorului c snt iniializate cu valoarea 0.
dac i a Iost adugat n coad
altfel
21
Parcurgerea BF poate Ii descris astfel,
coada C este iniializat cu vrful v
0
;
ct timp C , este extras si vizitat un vrf i din coad, apoi snt introdusi n coad
vecinii lui i care nu au Iost deja introdusi (acele vrfuri k cu proprietatea c c[k|0 si a[i][k]=1).
Vrfurile i ce au Iost introduse n coad snt marcate prin c[i]=1.
Exemplu
2.2.3. Pentru graful din exemplul 2.2.1., aplicarea metodei de traversare BF
determin urmtoarea evoluie,
c
t
1 2 3 4 5 6 7
t=1 1 0 0 0 0 0 0
t=2 1 1 1 1 0 0 1
t=3 1 1 1 1 1 0 1
t=4 1 1 1 1 1 1 1
t=5 1 1 1 1 1 1 1
t=6 1 1 1 1 1 1 1
t=7 1 1 1 1 1 1 1
t=8 1 1 1 1 1 1 1
C
t
t=1 1
t=2 2 3 4 7
t=3 3 4 7 5
t=4 4 7 5 6
t=5 7 5 6
t=6 5 6
t=7 6
t=8
Observaie Deoarece graful din exemplul 2.2.1. este conex, traversarea BF realizeaz
vizitarea tuturor vrfurilor grafului. Aplicarea metodei BF grafului din exemplul 2.2.2. nu
determin vizitarea vrIurilor 8,9, 10 si 11, deoarece acestea snt vrfuri neconectate cu vrful
iniial . Cu alte cuvinte, metoda BF aplicat unui graI determin vizitarea tuturor vrfurilor
care snt conectate cu vrIul iniial selectat.
Sursa C pentru implementarea metodei BF este,
#i ncl ude <st di o. h>
#i ncl ude <coni o. h>
#i ncl ude <al l oc. h>
t ypedef st r uct nn
{ i nt i nf ;
st r uct nn *l eg;
} nod, * pnod;
i nt i nser eaza_coada( pnod *head, pnod *t ai l , i nt i nf o)
{
pnod nou;
i f ( nou=( pnod) mal l oc( si zeof ( nod) ) ) {
22
nou- >i nf =i nf o;
nou- >l eg=NULL;
i f ( *head==NULL) *head=nou;
el se ( *t ai l ) - >l eg=nou;
*t ai l =nou;
r et ur n 1;
}
el se r et ur n 0;
}
i nt ext r age_coada( pnod *head, pnod *t ai l , i nt *i nf o)
{
i f ( *head) {
pnod aux=*head;
*i nf o=( *head) - >i nf ;
( *head) =( *head) - >l eg;
f r ee( aux) ;
i f ( *head==NULL) *head=*t ai l =NULL;
r et ur n 1;
}
el se r et ur n 0; }
voi d br eadt h_f i r st ( i nt v0, i nt a[ 10] [ 10] , i nt n)
{
pnod head=NULL;
pnod t ai l =NULL;
i nt c[ 10] ;
f or ( i nt i =0; i <n; c[ i ++] =0) ;
i nt r =i nser eaza_coada( &head, &t ai l , v0) ;
c[ v0] =1;
whi l e( head) {
r =ext r age_coada( &head, &t ai l , &i ) ;
pr i nt f ( " \ n%i " , i +1) ;
f or ( i nt k=0; k<n; k++)
i f ( ( a[ i ] [ k] ==1) &&( c[ k] ==0) ) {
r =i nser eaza_coada( &head, &t ai l , k) ;
c[ k] =1;
}
}
}
voi d mai n( )
{
i nt n, v0, a[ 10] [ 10] ;
cl r scr ( ) ;
pr i nt f ( " Numar ul de var f ur i : " ) ;
scanf ( " %i " , &n) ;
pr i nt f ( " \ nMat r i cea de adi acent a\ n" ) ;
f or ( i nt i =0; i <n; i ++)
f or ( i nt j =0; j <i ; j ++) {
scanf ( " %i " , &v0) ;
a[ j ] [ i ] =a[ i ] [ j ] =v0;
}
f or ( i =0; i <n; i ++) a[ i ] [ i ] =0;
pr i nt f ( " \ nVar f ul i ni t i al " ) ;
scanf ( " %i " , &v0) ;
pr i nt f ( " \ nPar cur ger ea BF a gr af ul ui est e" ) ;
br eadt h_f i r st ( v0, a, n) ;
}
23
n continuare snt prezentate o serie de rezultate prin care este demonstrat proprietatea
parcurgerii BF de a calcula distana minim de la orice vrf v conectat de vrIul iniial v
0
la v
0
.
Lema 2.2.1. Fie G=(V,E) un graI oarecare si V v
0
arbitrar. Atunci, pentru orice
muchie ( ) E v , u , ( ) ( ) 1 u , v v , v
0 0
+ .
Demonstraie Dac u este conectat de v
0
n G, atunci, evident, si v este conectat de v
0
n
G. n acest caz, cel mai scurt drum de la v
0
la v nu poate fi mai lung dect cel mai scurt drum de la
v
0
la u prelungit cu muchia (u,v), deci afirmaia este demonstrat. n situaia n care u nu este
conectat de v
0
n G, atunci, evident, rezult inegalitatea ( ) ( ) 1 u , v v , v
0 0
+ .
Lema 2.2.2 Fie G=(V,E) un graI neorientat sau graI direcionat si V v
0
vrI iniial al
procedurii de traversare BF. Atunci orice V v vizitat, are loc inegalitatea j { ( ) v , v v d
0
.
Demonstraie AIirmaia este demonstrat prin inducie dup ordinea vizitrii BF a
elementelor V v conectate cu
0
v n G.
Dac
0
v v = , rezult j { 0 v d = si, pentru orice { } j { ( ) v , u u d , v \ V u = , deci
aIirmaia este adevrat.
Fie v vrIul vizitat ca rezultat al procesrii vrfului u. Prin aplicarea ipotezei inductive,
j { ( ) u , v u d
0
, a rezultatului lemei 2.2.1 si a procedurii de parcurgere BF obinem,
j { j { ( ) ( ) v , v 1 u , v 1 u d v d
0 0
+ + = .
Deoarece vrful v nu a Iost anterior gsit n lista vecinilor nici unui nod studiat naintea
vrfului u, v este inserat n C.
Lema 2.2.3 Fie G=(V,E) un graI neorientat sau graI direcionat si { }
p 2 1
v ,..., v , v C =
coada calculat la un moment al aplicrii procedurii de parcurgere BF. Atunci urmtoarele
inegalitile snt veriIicate, |Cor,Lei sa|
j { j { 1 v d v d
1 p
+
j { j { 1 p ,..., 1 i , v d v d
1 i i
=
+
.
Teorema 2.2.1. Corectitudinea procedurii BF
Fie G=(V,E) graI neorientat sau graI direcionat si V v
0
vrI iniial al procedurii de
traversare BF. Atunci metoda BF calculeaz toate vrfurile v conectate cu v
0
n G si, pentru orice
V v , v v
0
vizitat, un cel mai scurt v
0
-v drum este format dintr-un v
0
-u drum si muchia (u,v),
unde u este acel vrf prin procesareacruia este determinat vizitarea lui v.
Demonstraie Fie ( ) { } k v , v / V v V
0 k
= = mulimea vrIurilor situate la distan k de
v
0
. Rezultatul teoremei este demonstrat prin inducie dup k, cu ipoteza inductiv,
I
k
:
k
V v , exist un singur moment al execuiei procedurii BF n care este determinat
urmtoarea evoluie,
j { k v d = si C v ;
dac
0
v v , vrful u care determin inserarea lui v n C este element al mulimii
1 k
V

.
Pentru 0 k = , { }
0 0
v V = . La momentul iniial,
0
v C si j { 0 v d
0
= , deci I este
veriIicat.
Verificarea ipotezei I
k
n condiiile n care I
0 ,,
I
k-1
snt adevrate este bazat pe
urmtoarea observaie. Pe tot parcursul execuiei procedurii BF, C O si, dac C u , atunci
24
j { u d si vrful care a determinat procesarea lui u rmn constante.
Din lema 2.2.3. rezult c, dac { }
p 2 1
v ,..., v , v C = , atunci
j { j { 1 p ,..., 1 i , v d v d
1 i i
=
+
. Fie 1 k , V v
k
. Din proprietatea de monotonie si ipoteza I
k-1
,
rezult c v a fost inserat n C dup ce toate vrfurile
1 k
V u

au Iost deja inserate n coad.
Deoarece ( ) k v , v
0
= , obinem c exist un v
0
-v drum de lungime k si
1 k
V u

astfel nct
( ) E v , u . Fr a pierde din generalitate, vom presupune c u este primul vrf din
1 k
V

inserat n
C.
La momentul n care vrful u devine prim element al cozii C, toate vrfurile vecine cu u n
G snt inserate n C, deci si vrful v. Rezult c j { j { k 1 u d v d = + = , unde u este acel vrf care
precede v pe un cel mai scurt v
0
-v drum.
Observaii
1. Demonstrarea teoremei de corectitudine a parcurgerii BF stabileste si o modalitate de
calcul al unui cel mai scurt v
0
-v drum astfel. Pentru orice V v conectat cu v
0
n G, fie j { V v p
vrIul a crui procesare a determinat inserarea lui v n C. Un v
0
-v drum de lungime minim este
v
0
- j { v p drumul cel mai scurt prelungit cu muchia j { ( ) v , v p .
2. Aplicarea metodei BF unui graI oarecare G determin obinerea unui arbore (vezi
capitolul 9) G
p
, numit subgraful predecesorilor definit de BF pe G, unde ( )
p p p
E , V G = si
j { { } { }
0 p
v V v p / V v V U = , j { ( ) { } { }
0 p
v \ V v / E v , v p E = .
Exemplu
2.2.4 Prin aplicarea procedurii BF grafului din 2.2.1, obinem,
1
2
3 4 7
5 6
25
2.2.2. Metoda de parcurgere DF (Depth First)
Ideea metodei DF revine la parcurgerea n adncime a grafurilor. Considernd v
0
vrf
iniial si M mulimea vrIurilor vizitate de procedur, pentru vizitarea vecinilor este considerat
unul din vrIurile din M cu proprietatea c lungimea drumului calculat de metod pn la
vrIul iniial v
0
este maxim.
Implementarea acestei metode poate Ii realizat n mai multe moduri, pentru
meninerea mulimii vrIurilor graIului disponibilizate pn la momentul curent Iiind utilizat
o structur de de date de tip stiv S. La momentul iniial se introduce n stiv v
0
. La fiecare
pas, se preia cu stergere ca vrI curent vrIul stivei S si se introduc n stiv vecinii nc
nevizitai ai vrIului curent. Un vrI se marcheaz ca vizitat n momentul introducerii lui n S.
Calculul continu pn cnd este eIectuat un acces de preluare din stiv si se constat c S este
vid. Pentru gestiunea vrIurilor vizitate, se utilizeaz un vector c cu n componente, unde n
reprezint numrul vrIurilor graIului si, la Iiecare moment, componentele snt:
_
_
_
=
altfel , 0
vizitat fost a i dac , 1
c
i
Componentele vectorului c vor Ii iniializate cu valoarea 0.
Exemple
2.2.5. Pentru graful,
1
2
5
6
7
3
4
si v
0
1, prin aplicarea metodei descrise, rezult urmtoarea evoluie.
c
t
1 2 3 4 5 6 7
t=1 1 0 0 0 0 0 0
t=2 1 1 1 1 0 0 1
t=3 1 1 1 1 0 1 1
t=4 1 1 1 1 0 1 1
26
t=5 1 1 1 1 1 1 1
t=6 1 1 1 1 1 1 1
t=7 1 1 1 1 1 1 1
t=8 1 1 1 1 1 1 1
S
t
t=1 1
t=2 7 4 3 2
t=3 6 4 3 2
t=4 4 3 2
t=5 5 3 2
t=6 3 2
t=7 2
t=8
Ordinea n care snt vizitate vrIurilor corespunztor acestei variante de parcurgere
DF este: 1, 2, 3, 4, 7, 6, 5.
2.2.6. Pentru graful din exemplul 2.2.2 vrfurile 8,9,10 care nu snt conectate cu vrful
iniial nu vor Ii vizitate nici prin aplicarea metodei DF. Ordinea n care snt vizitate vrfurilor
corespunztor acestei variante este: 1, 2, 3, 4, 6, 7, 5.
O variant de implementare a metodei DF rezult prin gestionarea stivei S n modul
urmtor. Iniial vrful v
0
este unicul component al lui S. La Iiecare etap se preia, Ir
stergere, ca vrf curent vrful stivei. Se introduce n stiv unul dintre vecinii vrIului curent
nc nevizitat. Vizitarea unui vrf revine la introducerea lui n S. Dac vrIul curent nu are
vecini nc nevizitai, atunci el este eliminat din stiv si este eIectuat un nou acces de preluare
a noului vrf al stivei ca vrf curent. Calculul se ncheie n momentul n care este efectuat un
acces de preluare a vrIului stivei ca vrI curent si se constat c S este vid. Evident, nici n
cazul acestei variante nu vor Ii vizitate vrIurile care nu snt conectate cu vrIul iniial ales.
27
Exemplu
2.2.7. Pentru graful,
1
2
5
6
7
3
4
si v
0
1, prin aplicarea metodei descrise, rezult urmtoarea evoluie.
c
t
1 2 3 4 5 6 7
t=1 1 0 0 0 0 0 0
t=2 1 1 0 0 0 0 0
t=3 1 1 0 1 0 0 0
t=4 1 1 1 1 0 0 0
t=5 1 1 1 1 0 1 0
t=6 1 1 1 1 0 1 1
t=7 1 1 1 1 0 1 1
t=8 1 1 1 1 0 1 1
t=9 1 1 1 1 0 1 1
t=10 1 1 1 1 1 1 1
t=11 1 1 1 1 1 1 1
t=12 1 1 1 1 1 1 1
t=13 1 1 1 1 1 1 1
t=14 1 1 1 1 1 1 1
S
t
t=1 1
t=2 2 1
t=3 4 2 1
t=4 3 4 2 1
t=5 6 3 4 2 1
t=6 7 6 3 4 2 1
t=7 6 3 4 2 1
t=8 3 4 2 1
t=9 4 2 1
t=10 5 4 2 1
t=11 4 2 1
28
t=12 2 1
t=13 1
t=14
Ordinea n care snt vizitate vrIurile corespunztor acestei variante este: 1, 2, 4, 3, 6,
7, 5.
Urmtoarea surs C implementeaz varianta precedent de parcurgere DF.
#i ncl ude <st di o. h>
#i ncl ude <coni o. h>
#i ncl ude <al l oc. h>
t ypedef st r uct nn{
i nt i nf ;
st r uct nn *l eg;
}nod, * pnod;
i nt i nser eaza_st i va( pnod *head, i nt i nf o)
{
pnod nou;
i f ( nou=( pnod) mal l oc( si zeof ( nod) ) ) {
nou- >i nf =i nf o;
nou- >l eg=*head;
*head=nou;
r et ur n 1;
}
el se r et ur n 0;
}
i nt ext r age_st i va( pnod *head, i nt *i nf o)
{
i f ( head) {
pnod aux=*head;
*i nf o=( *head) - >i nf ;
( *head) =( *head) - >l eg;
f r ee( aux) ;
r et ur n 1;
}
el se r et ur n 0; }
voi d dept h_f i r st ( i nt v0, i nt a[ 10] [ 10] , i nt n)
{
pnod head=NULL;
i nt c[ 10] ;
f or ( i nt i =0; i <n; c[ i ++] =0) ;
i nt r =i nser eaza_st i va( &head, v0) ;
c[ v0] =1;
pr i nt f ( " \ n%i " , v0+1) ;
whi l e( head) {
r =ext r age_st i va( &head, &i ) ;
f or ( i nt k=0; k<n; k++)
i f ( ( a[ i ] [ k] ==1) &&( c[ k] ==0) ) {
r =i nser eaza_st i va( &head, k) ;
c[ k] =1; pr i nt f ( " \ n%i " , k+1) ;
}
}
}
voi d mai n( )
{
i nt n, v0, a[ 10] [ 10] ;
cl r scr ( ) ;
29
pr i nt f ( " Numar ul de var f ur i : " ) ; scanf ( " %i " , &n) ;
pr i nt f ( " \ nMat r i cea de adi acent a\ n" ) ;
f or ( i nt i =0; i <n; i ++)
f or ( i nt j =0; j <i ; j ++) {
scanf ( " %i " , &v0) ; a[ j ] [ i ] =a[ i ] [ j ] =v0;
}
f or ( i =0; i <n; i ++) a[ i ] [ i ] =0;
pr i nt f ( " \ nVar f ul i ni t i al " ) ; scanf ( " %i " , &v0) ;
pr i nt f ( " \ nPar cur ger ea DF a gr af ul ui est e" ) ;
dept h_f i r st ( v0, a, n) ;
}
2.2.3. Parcurgerea n adncime n varianta generalizat DFG
Urmtoarea variant de implementare a parcurgerii n adncime, DFG, determin
vizitarea tutror vrIurilor graIului analizat (considerat neorientat sau direcionat), indiIerent dac
acesta este conex sau neconex.
Fie G=(V,E) un graI oarecare. Vom presupune n continuare c nici un vrI din V nu este
etichetat cu inIormaia 0. Implementare traversrii DFG utilizeaz urmtoarele structuri,
A, matricea de adiacen a graIului;
p, vectorul predecesorilor (vezi 2.2.1);
f, vectorul care marcheaz ncheierea analizrii listei vrfurilor vecinilor nodului
curent;
mark, definit pentru orice V v prin,
0, dac v nu a Iost nc analizat
mark[v]= 1, dac v este procesat la momentul curent
2, dac consultarea lui v este ncheiat
d, definit pentru orice V v prin d[v]=t, unde t este momentul de timp la care este
iniiat analiza vrIului v.
Considernd t variabil public desemnnd momentul prelucrrii, procedura DFG poate fi
descris prin intermediul urmtoarelor Iuncii.
void DFG(graf G)
{
for( V u ){
mark[u]=0;
p[u]=0;
}
t=0;
for( V u )
if(!mark[u])DF_Visit(u);
}
void DF_Visit(varf u)
{
mark[u]=1;
d[u]=t++;
for( V v :A[u][v]==1)
if(!mark[v]){
p[v]=u;
DF_Visit(v);
}
mark[u]=2;
f[u]=t++;
}
30
Prin aplicarea parcurgerii n adncime n varianta generalizat snt obinute inIormaii
suplimentare ale grafului de intrare. Metoda DFG determin obinerea subgraIul predecesorilor,
p
G , de tip graI pdure (componentele conexe vezi 2.3- snt arbori - vezi capitolul 9). Fiecare
component conex a lui
p
G este construit prin executarea modulului DF_Visit. De asemenea,
vrfurile V v , u au proprietatea c j { v p u = dac si numai dac Iuncia DFVisit(v) a Iost
apelat la momentul cutrii n lista vecinilor vrfului u.
O alt proprietate important a metodei de parcurgere DFG este aceea c, dup ncheierea
calculului, este determinat o structur de tip parante: astIel. Dac momentul selectrii vrIului
u pentru procesare este marcat prin (u si momentul ncheierii prelucrrii lui u este notat u),
atunci istoricul traversrii DFG pentru calculul Iiecrui arbore din
p
G poate fi reprezentat prin
intermediul unei expresii corecte din punct de vedere al parantezrii.
Teorema 2.2.2 Corectitudinea parantezrii determinat de aplicarea metodei DFG
Fie G=(V,E) un graI sau un graI direcionat. Prin aplicarea traversrii DFG este obinut
urmtorul rezultat. Pentru orice V v , u , una si numai una din urmtoarele aIirmaii este
adevrat, |Cor,Lei sa|
1) j { j { j { u f , u d si j { j { j { v f , v d snt disjuncte;
2) j { j { j { u f , u d j { j { j { v f , v d si u este un descendent al lui v n arborele corespunztor
din
p
G ;
3) j { j { j { u f , u d j { j { j { v f , v d si u este un ancestor al lui v n arborele corespunztor din
p
G .
Observaie Fie G=(V,E) un graI sau un graI direcionat. Pe baza procedurii DFG poate Ii
realizat urmtoarea clasiIicare a elementelor ( ) E v , u e = ,
1) Muchii de tip arbore n DF- graIul pdure
p
G , etichetate cu T: ( ) v , u are eticheta T
dac procesarea vrIului v a Iost decis ca rezultat al testrii existenei muchiei e;
2) Muchii de tip napoi, cu etichet B: ( ) v , u este muchie B dac v este ancestorul lui u
ntr-o component conex a DF- graIului pdure
p
G ;
3) Muchii de tip nainte, notate cu F: acele muchii ( ) v , u , neetichetate cu T si n care v
este descendent al lui u ntr-o component conex a DF- graIului pdure
p
G ;
4) Muchii de tip trecere, etichetate cu C: toate muchiile ( ) v , u rmase neetichetate dup
ncheierea etichetrii cu T, B si F.
Teorema 2.2.3.
Fie G=(V,E) un graf neorientat. Orice element E e este fie de tip T, fie de tip B.
|Cor,Lei sa|
Teorema 2.2.4. Criteriu de aciclicitate pentru grafuri direcionate
Un graf direcionat este aciclic (vezi 2.4) dac si numai dac nici una din muchii nu este
de tip B. |Cor,Lei sa|
31
Exemple
2.2.8. Pentru graful
1
2
3
4
5 7
6
8
9 10
obinem,
1) ordinea de parcurgere DFG a vrfurilor: 1,2,3,4,6,7,5,8,9,10
2) graIul pdure
p
G ,
1
3
2
4
5 6
7
8
9
10
3) structurile parantez: (1 (2 (3 3) (4 (6 (7 7) 6) (5 5) 4) 2) 1) si (8 (9 (10 10) 9) 8)
4) clasificarea muchiilor,
1
3
2
4
5 6
7
8
9
10
T
T
T
T
T
T
T
T
B
B
B
2.2.9 Fie graful direcionat,
6 1 7 2
5 8 4 3
Prin parcurgerea DFG obinem urmtoarea ordonare: 1,7,6,8,5,2,4,3.
Subgraful predecesorilor este Iormat din urmtoarele componente,
32
1 2
3 4
7
6
5
8
Structurile parantez: (1 (7 (6 (5 5) 6) (8 8) 7) 1) si (2 (4 4) (3 3) 2).
Clasificarea muchiilor grafului direcionat este,
1 2
3 4
7
6
5
8
T
T
T
T
T T
F
B
B
C
C
C
2.3. Drumuri n grafuri. Conexitate
2.3.1 Drumuri; definiii
Una dintre cele mai importante proprieti ale graIurilor o constituie posibilitatea de
accesare, prin intermediul unei secvene de muchii (arce), dintr-un vrI dat a oricrui alt vrf al
grafului, proprietate cunoscut sub numele de conexitate sau conexiune. Asa dup cum a rezultat
n 2.2., dac G=(V,E) este un graf conex, atunci pentru orice vrI iniial v
0
considerat metodele
BF si DF permit vizitarea tuturor vrfurilor din V.
Definiia 2.3.1. Fie G=(V,E) un graf, u,vV. Secvena de vrIuri : u
0
, u
1
,..,u
n
este un u-v
drum dac u
0
=u, u
n
=v, u
i
u
i+1
E pentru toi i, n i 0 . Lungimea drumului, notat l() este
egal cu n. Convenional, se numeste drum trivial, un drum cu l()=0.
Definiia 2.3.2. Fie : u
0
, u
1
,..,u
n
un drum n graful G=(V,E). este un drum nchis dac
u
0
=u
n
; n caz contrar, se numeste drum deschis. Drumul este elementar dac oricare dou
vrfuri din snt distincte, cu excepia, eventual, a extremitilor. Drumul este proces dac,
pentru orice 1 n j i 0 u
i
u
i+1
u
j
u
j+1
.
Evident, orice drum elementar este un proces.
33
Exemplu
2.3.1. Pentru graful,
v
1
v
2
v
3
v
4
v
5

1
: v
1
, v
2
, v
3
, v
2
, v
5
, v
3
, v
4
este un v
1
- v
4
drum care nu este proces;

2
: v
1
, v
2
, v
5
, v
1
, v
3
, v
4
este un v
1
- v
4
proces care nu este drum elementar;

3
: v
1
, v
3
, v
4
este un v
1
- v
4
drum elementar.
Definiia 2.3.3. Fie : u
0
, u
1
,..,u
n
un drum n graful G=(V,E).

: v
0
, v
1
,..,v
m
este un
subdrum al lui dac

este un drum si pentru orice j, m j 0 , exist i, n i 0 astfel


nct u
i
=v
j
.
Observaie Orice drum cu lungime cel puin 1 conine cel puin un drum elementar cu
aceleasi extremiti.
ntr-adevr, dac : u
0
, u
1
,..,u
n
nu este elementar, atunci exist n j i 0 < si i 0 sau
j n astfel nct u
i
=u
j
. Atunci drumul
_
_
_
_
_

=
=
+
+
n j , 0 i dac , u ... u u ... u u
0 j dac , u ... u u
0 i dac , u ... u u
:
n 1 j i 1 0
i 1 0
n 1 j j
'

este de asemenea un u
0
-u
n
drum. Aplicnd n continuare eliminarea duplicatelor vrfurilor n
modul descris, rezult n Iinal un u
0
-u
m
drum elementar.
Exemplu
2.3.2. n graful,
v
1
v
2
v
3
v
4
v
5
v
6
v
7
v
8
v
9
v
10
dac : v
1
, v
2
, v
4
, v
5
, v
3
, v
1
, v
2,
v
5
, v
6
, v
7
, v
8
, v
9,
v
5
, v
9
, v
8
, v
10
, atunci
1
: v
1
, v
2
, v
5
, v
9
, v
8
, v
10
,

2
: v
1
, v
2
, v
4
, v
5
, v
9
, v
8
, v
10
snt v
1
-v
10
subdrumuri elementare.
34
2.3.2. Matricea existenei drumurilor; algoritmul Roy-Warshall
Lema 2.3.1. Fie G=(V,E) un graf, n V = . Dac A este matricea de adiacen asociat
grafului, atunci, pentru orice p1,
) p (
ij
a este numrul v
i
-v
j
drumurilor distincte de lungime p din
graful G, unde ( )
) p (
ij
p
a A = .
Demonstraie
Demonstrarea acestei aIirmaii este realizat prin inducie dup p
Pentru p=1, deoarece pentru orice n j , i 1 exist cel mult un v
i
-v
j
drum de lungime 1
si dac exist, Iie acesta : v
i
, v
j
. Rezult c numrul v
i
-v
j
drumurilor de lungime 1 este egal cu
( ) 1
ij
a .
Presupunem c A
p-1
=
( )
( )
1 p
ij
a

are proprietatea c pentru toi n j , i 1 ,
( )
( )
1 p
ij
a

este
egal cu numrul v
i
-v
j
drumurilor de lungime p-1 n G.
Cum A
p
=A
p-1
A =
( )
( )
p
ij
a , rezult c, n j , i 1 ,

=
p
1 k
kj
) 1 p (
ik
) p (
ij
a a a . Orice v
i
-v
j
drum
de lungime p n G conine un v
i
-v
k
drum de lungime p-1 pentru un anume v
k
adiacent cu v
j
si
reciproc, pentru orice v
k
adiacent cu v
j
oricrui v
i
-v
k
drum de lungime p-1 i corespunde un v
i
-v
j
drum de lungime p.
Din relaia care caracterizeaz elementele
( )
( )
p
ij
a , utiliznd ipoteza inductiv, rezult
aIirmaia enunat mai sus.
Definiia 2.3.4. Fie M
n
(0,1)} mulimea matricelor de dimensiuni nxn, componentele
Iiind elemente din mulimea 0,1}. Pe M
n
(0,1)}se deIinesc operaiile binare, notate si ,
astfel: pentru orice A=(a
ij
), B=(b
ij
) din M
n
({0,1)}, AB=(c
ij
), AB=(d
ij
), unde
n j , i 1 , c
ij
=max{a
ij
, b
ij
}
d
ij
=max{min{a
ik
, b
kj
}, n k 1 }.
Dac A=(a
ij
) M
n
(0,1)}, se noteaz ( ) { } 1 k ; a A
) k (
ij
k
= secvena de matrice deIinit
prin:
( )
2 k , A A A , A A
) 1 k ( k 1
= =

.
Dac A este matricea de adiacen a unui graI G=(V,E), atunci pentru fiecare k,
1 n k 1 ,
_
_
_
=
altfel , 0
k lungime de j la i la de drum exist dac , 1
a
) k (
ij
Matricea
) 1 n ( ) 2 ( ) 1 (
A A A M

= K se numeste matricea existenei drumurilor n
graful G. SemniIicaia componentelor matricei M este:
_
_
_
=
altfel , 1
G n drum v v exist nu dac , 0
m , n j , i 1
j i
ij
35
Exemplu
2.3.3. Pentru graful,
1
2
3
4
_
_
_
_
_
_
_
_
_
_
_
_
_
_
=
_
_
_
_
_
_
_
_
_
_
_
_
_
_
=
_
_
_
_
_
_
_
_
_
_
_
_
_
_
=
_
_
_
_
_
_
_
_
_
_
_
_
_
_
=
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
,
1 1 1 1
1 1 1 1
1 1 0 1
1 1 1 1
,
1 1 1 1
1 1 1 1
1 1 1 0
1 1 0 1
,
0 1 0 1
1 0 0 1
0 0 0 1
1 1 1 0
3 2
M A A A
Observaie Calculul matricei existenei drumurilor permite veriIicarea dac un graI dat
este conex. GraIul este conex dac si numai dac toate componentele matricei M snt egale cu 1.
Algoritmul Roy-Warshall calculeaz matricea existenei drumurilor ntr-un graf G cu n
vrfuri.
voi d Roy_War shal l ( unsi gned char a[ 10] [ 10] , unsi gned n, unsi gned char m[ 10] [ 10] )
{i nt i , j , k;
f or ( i =0; i <n; i ++)
f or ( j =0; j <n; j ++)
m[ i ] [ j ] =a[ i ] [ j ] ;
f or ( j =0; j <n; j ++)
f or ( i =0; i <n; i ++)
i f ( m[ i ] [ j ] )
f or ( k=0; k<n; k++)
i f ( m[ i ] [ k] <m[ k] [ j ] ) m[ i ] [ k] =m[ k] [ j ] ; }
Datele de intrare snt: n, numrul de noduri si A, matricea de adiacen corespunztoare
grafului. Matricea M calculat de algoritm constituie iesirea si este matricea existenei drumurilor
n graful G.
2.3.3. Componente conexe ale unui graf
Definiia 2.3.5. Fie G=(V,E) graf netrivial. Vrfurile u,v V snt conectate dac exist un
u-v drum n G.
Definiia 2.3.6. Dac G este un graI, atunci o component conex a lui G este un subgraf
conex al lui G, maximal n raport cu proprietatea de conexitate.
36
Exemplu
2.3.4. Componentele conexe ale grafului
1
2
3
5
4
6
snt: C1={1,2,3}, C2={4,5}, C3={6}.
Observaii
1) Un graI este conex dac si numai dac numrul componentelor sale conexe este
1.
2) Mulimile de vrIuri corespunztoare oricror dou componente conexe distincte
snt disjuncte. Rezult c mulimile de vrIuri corespunztoare componentelor conexe ale
unui graI Iormeaz o partiie a mulimii vrfurilor grafului.
Problema determinrii componentelor conexe corespunztoare unui graI poate fi
rezolvat n modul urmtor. Iniial, este selectat drept vrf curent un vrf al grafului pentru care
este calculat componenta conex care l conine. Dac exist vrIuri care nu aparin componentei
conexe determinate, este ales drept vrf curent unul dintre aceste vrfuri. n continuare este
aplicat aceeasi metod, pn cnd au Iost gsite toate componentele conexe ale graIului.
Determinarea componentei conexe care conine un vrf v
0
dat poate Ii realizat pe baza
urmtorului algoritm.
Pentru G=(V,E), n V = , n 1 si v
0
V, pasii algoritmului snt:
Pas1: V
0
={v
0
}; E
0
=; i=0;
Pas 2: repet Pas 3 pn cnd V
i
=V
i-1
si E
i
=E
i-1
Pas 3: i=i+1;
{ }
{ }; e cu incident u , V u , E e / e E E
; E uv , V u , V v / v V V
1 i 1 i i
1 i 1 i i


=
=
Iesirea este G
i
=(V
i
,E
i
), componenta conex din care Iace parte v
0
.
Exemplu
2.3.5. Pentru graful,
1
2
7 3
4 5 8 6 9
Aplicarea algoritmului descris pentru v
0
1, determin urmtoarea evoluie:
I V
i
E
i
i=0 {1}
i=1 {1,2,4} {(1,2),(1,4)}
i=2 {1,2,4,7,8,5} {(1,2),(1,4),(2,7),(2,8),(7,8),(4,5),(4,7),(5,8)}
37
2.3.4. Drumuri de cost minim
Definiia 2.3.7. Fie G=(V,E,w) un graf ponderat. Costul drumului : u
1
,u
2
,..,u
n
, notat
L(), este definit prin:
( ) ( )

=
+
=
1 n
1 i
1 i i
u , u w L .
Pentru orice u si v vrfuri conectate n G, u v, w-distana ntre u si v, notat D(u,v), este
deIinit prin,
( ) ( ) { }
uv
D , L min v , u D = , unde D
uv
desemneaz mulimea tuturor u-v drumurilor
elementare din G. Dac
uv
D este astfel nct D(u,v)=L(), drumul se numeste drum de cost
minim.
Observaie Cu toate c este utilizat termenul de w-distan, n general D nu este o
distan n sensul matematic al cuvntului.n particular, dac Iuncia pondere asociaz valoarea 1
Iiecrei muchii a graIului, atunci pentru fiecare pereche de vrfuri distincte ale grafului, costul
D(u,v) este lungimea unui cel mai scurt drum ntre cele dou vrfuri. n acest caz D este o distan
pe mulimea vrfurilor.
Algoritmul Dijkstra
Urmtorul algoritm a Iost propus de ctre E. W. Dijkstra pentru determinarea w-
distanelor D(u
0
,v) si a cte unui u
0
-v drum de cost minim pentru fiecare vrf vu
0
ntr-un graf
ponderat, unde u
0
este prestabilit.
Fie G=(V,E,w) un graf conex ponderat, u
0
V, SV, u
0
S. Se noteaz S \ V S = si
( ) ( ) { } S x ; x , u D min S , u D
0 0
= . Fie vS astfel nct D(u
0
,v)=D(u
0
, S), : u
0
, u
1
,,u
p
v un u
0
-
v drum de cost minim. Evident, 0ip u
i
S si

: u
0
, u
1
,,u
p
un u
0
- u
p
drum de cost minim.
De asemenea,
( ) ( ) { } E uv , S v , S u ); uv ( w u , u D min S , u D
0 0
+ = .
Dac xS, yS astfel nct ( ) ( ) ) xy ( w x , u D S , u D
0 0
+ = , rezult
( ) ( ) ) xy ( w x , u D y , u D
0 0
+ = .
Pentru determinarea a cte unui cel mai ieftin u
0
-v drum, algoritmul consider o etichetare
dinamic a vrfurilor grafului.Eticheta vrfului v este (L(v),u), unde L(v) este lungimea unui cel
mai ieftin u
0
-v drum determinat pn la momentul respectiv si u este predecesorul lui v pe un
astfel de drum.
Pentru (V,E,w) graf conex ponderat, n V = si u
0
V, calculul implicat de algoritmul
Dijkstra poate fi descris astfel:
Pas 1: i=0; S
0
={u
0
}; L(u
0
)=0, L(v)=pentru toi vV, v=u
0
. Dac n1 atunci stop
Pas 2: Pentru toi v i S , dac L(v)~L(u
i
)+w(u
i
v), atunci L(v)=L(u
i
)+w(u
i
v) si etiche-
teaz v cu (L(v),u
i
).
Pas 3: Se determin dminL(v), v i S } si se alege u
i+1
i S astfel nct L(u
i+1
)=d.
Pas 4: S
i+1
=S
i
{u
i+1
}
Pas 5: ii1. Dac in-1, atunci stop. Altfel, reia Pas 2.
Observaie Dac (V,E,w) graf ponderat neconex, atunci, pentru u
0
V, algoritmul lui
Dijkstra permite determinarea w-distanelor D(u
0
,v) si a cte unui u
0
-v drum de cost minim pentru
toate vrfurile v din componenta conex creia i aparine u
0
.
38
Exemplu
2.3.6. Fie graful ponderat,
1
2
3
4
5
1 5
9
2
5
16
Considernd u
0
=1, etapele n aplicarea algoritmului Dijkstra snt:
P1: i=0; S
0
={1}; L(1)=0, L(i)=pentru toi 5 , 2 i = .
P2: 0 S ={2,3,4,5}, u
0
=1
L(2)=>L(1)+5=5 L(2)5, eticheteaz 2 cu 1
L(3)=>L(1)+1=1 L(3)1, eticheteaz 3 cu 1
L(4)=>L(1)+9=9 L(4)9, eticheteaz 4 cu 1
L(5)=, w(1,5)=, deci L(5) nu se modiIic
P3: selecteaz u
1
3, L(3)1, cea mai mic dintre w-distanele calculate la P2
P4: S
1
={1,3}
P5: i=i+1=1 = 4, reia P2
P2: 1 S ={2,4,5}, u
1
=3
Nu se modiIic nici o etichet si nici o w-distan (w(3,i) , pentru toi i din
1 S )
P3: selecteaz u
2
2, L(2)5, cea mai mic dintre w-distanele calculate la P2
P4: S
2
={1,3,2}
P5: i=i+1=2 = 4, reia P2
P2: 2 S ={4,5}, u
2
=2
L(4)=9>L(2)+2=7 L(4)7, eticheteaz 4 cu 2
L(5)=~L(2)1621, eticheteaz 5 cu 2
P3: selecteaz u
3
4, L(4)7, cea mai mic dintre w-distanele calculate la P2
P4: S
3
={1,3,2,4}
P5: i=i+1=3 = 4, reia P2
P2: 3 S ={5}, u
3
=4
L(5) 21~L(4)512, eticheteaz 5 cu 4
P3: selecteaz u
4
5, L(5)12, cea mai mic dintre w-distanele calculate la P2
P4: S
3
={1,3,2,4,5}
P5: i=i+1=4, stop.
Algoritmul calculeaz urmtoarele rezultate:
Vrful v pn la care este
calculat w-distana
1 2 3 4 5
D(1,v), eticheta lui v 0, 1 5, 1 1, 1 7, 2 12, 4
39
Drumurile de cost minim de la vrful 1 la fiecare dintre vrfurile grafului se stabilesc pe
baza sistemului de etichete astfel: drumul de la 1 la un vrf v este dat de: v
1
, eticheta lui v, v
2
eticheta lui v
1
samd, pn se ajunge la eticheta 1. AstIel, v
0
-drumurile de cost minim snt:
pn la 2: 2,1;
pn la 3: 3,1;
pn la 4: 4,2,1;
pn la 5: 5,4,2,1.
Urmtoarea surs C implementeaz algoritmul Dijkstra.
#i ncl ude<st di o. h>
#i ncl ude<coni o. h>
#i ncl ude<al l oc. h>
t ypedef st r uct {
i nt pr edv;
f l oat L;
} et i chet a;
voi d cr eaza( i nt *s, i nt *sb, i nt nv, i nt u0)
{
s[ 0] =u0;
f or ( i nt j =0, i =0; i <nv; i ++)
i f ( i - u0) sb[ j ++] =i ;
}
voi d modi f i ca( i nt *s, i nt *sb, i nt ui , i nt *ns, i nt *nb)
{
s[ *ns] =ui ;
( *ns) ++;
f or ( i nt i =0; i <*nb; i ++)
i f ( sb[ i ] ==ui ) {
f or ( i nt j =i +1; j <*nb; j ++)
sb[ j - 1] =sb[ j ] ;
( *nb) - - ;
r et ur n;
}
}
et i chet a *Di j kst r a( f l oat w[ ] [ 50] , i nt nv, i nt u0)
{
et i chet a *r =( et i chet a *) mal l oc( nv*si zeof ( et i chet a) ) ;
f or ( i nt i =0; i <nv; i ++) r [ i ] . L=1000;
r [ u0] . L=0;
r [ u0] . pr edv=u0;
i nt s[ 50] , sb[ 50] , ns=1, nb=nv- 1;
cr eaza( s, sb, nv, u0) ;
f or ( i =0; i <nv- 1; i ++) {
f l oat dmi n=1000;
f or ( i nt j =0; j <nb; j ++)
f or ( i nt k=0; k<ns; k++)
i f ( r [ sb[ j ] ] . L>r [ s[ k] ] . L+w[ sb[ j ] ] [ s[ k] ] ) {
r [ sb[ j ] ] . L=r [ s[ k] ] . L+w[ sb[ j ] ] [ s[ k] ] ;
r [ sb[ j ] ] . pr edv=s[ k] ;
}
i nt ui ;
f or ( j =0; j <nb; j ++)
i f ( r [ sb[ j ] ] . L<dmi n) {
dmi n=r [ sb[ j ] ] . L;
ui =sb[ j ] ;
}
40
modi f i ca( s, sb, ui , &ns, &nb) ;
}
r et ur n r ;
}
voi d mai n( )
{
i nt n, i , j ;
cl r scr ( ) ;
pr i nt f ( " Numar ul de var f ur i " ) ;
scanf ( " %i " , &n) ;
pr i nt f ( " Mat r i cea ponder i l or : \ n" ) ;
f l oat w[ 50] [ 50] ;
f or ( i =0; i <n; i ++)
f or ( j =0; j <n; j ++)
scanf ( " %f " , &w[ i ] [ j ] ) ;
i nt u0;
pr i nt f ( " \ nVar f ul i ni t i al : " ) ;
scanf ( " %i " , &u0) ;
u0- - ;
et i chet a *r ez=Di j kst r a( w, n, u0) ;
f or ( i =0; i <n; i ++) {
pr i nt f ( " Di st ant a de l a vf . %i l a vf . %i est e %7. 2f \ n" , u0+1, i +1, r ez[ i ] . L) ;
pr i nt f ( " Un dr umde cost mi ni mest e: " ) ;
pr i nt f ( " %i , " , i +1) ;
j =r ez[ i ] . pr edv;
whi l e( j - u0) {
pr i nt f ( " %i , " , j +1) ;
j =r ez[ j ] . pr edv;
}
pr i nt f ( " %i \ n\ n" , u0+1) ;
}
f r ee( r ez) ;
get ch( ) ;
}
n anumite aplicaii este necesar exclusiv determinarea w-distanelor D(v
0
,v), pentru toi
vV. n acest caz algoritmul Roy-Floyd permite o rezolvare a acestei probleme mai simplu de
implementat dect algoritmul Dijkstra.
Algoritmul Roy-Floyd
Pentru (V,E,w) graf ponderat, n V = si W matricea ponderilor, sistemul de w-distane
D(v
0
,v), vV, poate Ii calculat pe baza urmtoarei Iuncii (similar algoritmului Roy-Warshall),
voi d Roy_Fl oyd ( f l oat w[ 10] [ 10] , unsi gned n, f l oat
d[ 10] [ 10] , f l oat MAX)
{i nt i , j , k;
f or ( i =0; i <n; i ++)
f or ( j =0; j <n; j ++)
d[ i ] [ j ] =w[ i ] [ j ] ;
f or ( j =0; j <n; j ++)
f or ( i =0; i <n; i ++)
i f ( d[ i ] [ j ] <MAX)
f or ( k=0; k<n; k++)
i f ( d[ i ] [ k] >d[ i ] [ j ] +d[ j ] [ k] )
d[ i ] [ k] =d[ i ] [ j ] +d[ j ] [ k] ;
}
Matricea D calculat de algoritm este matricea w-distanelor D(u,v) n graful ponderat
conex (V,E,w); pentru orice n j , i 1
41
_
_
_

=
altfel ,
conectate sunt v , v ), v , v ( D
d
j i j i
ij
ntr-adevr, procedura realizeaz calculul dinamic al w-distanei ntre oricare dou vrfuri
i si k, astIel: dac exist un drum i-k drum ce trece prin j ( n j 1 ), cu costul corespunztor
(d
ij
+d
jk
) inferior costului curent (d
ik
), atunci noul drum de la i la k via j este de cost mai mic dect
costul drumului vechi, deci w-distana ntre i si k trebuie reactualizat la d
ij
+d
jk
.
Algoritmul Yen
Algoritmul propus de Yen pentru calculul tuturor w-distanelor ntr-un graf ponderat este
mai eIicient din punctul de vedere al volumului de operaii dect algoritmul Roy-Floyd. Fie
(V,E,w) un graf ponderat si W matricea ponderilor. Pentru determinarea w-distanelor de la vrful
v
k
fixat la celelalte vrIuri ale graIului, algoritmul Yen iniiaz urmtoarele operaii,
Pas 1: D=W
Pas 2: i1; (k)0, b(k)0; (j)0, pentru toi n j 1 , j k
Pas 3: Calculeaz mind
kj
; n j 1 , (j)1};
Determin j
0
astfel nct (j
0
)1 si
0
kj
d =min{d
kj
; n j 1 , (j)1}
B(j
0
)=
0
kj
d , (j
0
)=0
d[k,j] =min{d[k,j],d[k,j0]+d[j0,j]}, pentru toi j, n j 1
i =i +1
Pas 4: Dac in, reia Pas 3, altIel stop.
La terminarea algoritmului componentele vectorului B snt respectiv egale cu w-distana
de la vrful v
k
la orice alt vrf al grafului. ntr-adevr, componentele egale cu 1 ale vectorului
indic, la Iiecare reluare a pasului 3, vrfurile grafului pentru care nu s-a calculat nc w-distana
la vrful v
k
. Dup Iiecare eIectuare a etapei 3, dac j
0
a fost selectat, atunci B(j
0
)=D(v
k
,
0
j
v ).
Exemplu
2.3.7. Fie graful
1
2
3
4
5
4
4
5
2
3
7
1
42
Se consider v
k
=1.
Pas 1:
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_



=
1 4
4 7
1 4 5 2
5 3
4 7 2 3
D
Pas 2: i1, (0,1,1,1,1); B(1)0
Pas 3: j
0
3, B(3)2, (0,1,0,1,1);
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_



=
1 4
4 7
1 4 5 2
5 3
3 6 2 3
D ; i=2
Pas 4: i<5, reia Pas 3
Pas 3: j
0
2, B(2)3, (0,0,0,1,1); nici o modiIicare n matricea D; i=3
Pas 4: i<5, reia Pas 3
Pas 3: j
0
5, B(5)3, (0,0,0,1,0); nici o modiIicare n matricea D; i=4
Pas 4: i<5, reia Pas 3
Pas 3: j
0
4, B(4)6, (0,0,0,0,0); nici o modiIicare n matricea D; i=5
Pas 4: i=5, stop.
2.4. Circuite yi cicluri n grafuri yi n digrafuri
Definiia 2.4.1. Fie G=(V,E) un graf netrivial, u, vV si un u-v drum n G. se
numeste proces dac toate muchiile drumului snt distincte. Drumul este trivial dac : u,u.
Definiia 2.4.2. Drumul este un circuit dac este un proces netrivial nchis.
Definiia 2.4.3. Circuitul : v
1
, v
2
,., v
n
, v
1
cu n3 este un ciclu al graIului, dac, pentru
orice i, j, cu j i , n j , i 1 , rezult v
i
v
j
.
Observaie Orice ciclu este un drum elementar nchis.
Definiia 2.4.4. Graful G este aciclic dac nu exist cicluri n G.
Observaie ntr-un digraf D noiunile de proces, circuit, ciclu snt deIinite ca si n cazul
grafurilor.
43
Exemple
2.4.1. n graful,
v
1
v
2
v
3
v
4
v
5
v
6

1
: v
1
, v
2
, v
3
, v
6
, v
5
este un proces;

2
: v
1
, v
2
, v
3
, v
6
, v
5
, v
3
, v
4
, v
1
este un circuit si nu este ciclu;

3
: v
1
, v
3
, v
5
, v
4
, v
1
este un ciclu.
2.4.2. Drumul : v
1
,v
2
,v
4
,v
3
,v
1
este un ciclu, deci graIul conine cicluri.
v
1
v
3
v
2
v
4
2.4.3. Digraful,
V
1
V
3
V
2
V
4
nu conine cicluri.
Definiia 2.4.5. Fie D=(V,E) un digraI. Funciile grad exterior, od
D
, respectiv grad
interior, id
D
, snt definite prin, N V : id ; N V : od
D D
,
( ) { } E uv , V v / v u od , V u
D
= , ( ) { } E vu , V v / v u id , V u
D
=
Funcia grad, notat deg
D
, este deIinit astIel,
( ) ( ) ( ) u od u id u deg , V u , N V : deg
D D D D
+ = .
Algoritmul Marimont
Procedura Marimont veriIic dac un digraI D=(V,E), n V = , este sau nu aciclic. La
terminarea calculului este aIisat mesajul 'DA, dac digraIul D este aciclic, respectiv 'NU, n
caz contrar. Descrierea pe pasi a algoritmului Marimont este,
Pas 1: V
0
=V, E
0
=E, D
0
=(V
0
,E
0
)
Pas 2: Dac ( ) 1 v od
0
D
pentru toi vV
0
, scrie 'NU, stop (dac toate vrfurile snt
extremiti iniiale ale mcar unui arc, atunci exist cicluri n D
0
); altIel, continu.
Pas 3: Selecteaz vV
0
cu ( ) 0 v od
0
D
= ;V
0
=V
0
\{v}; E
0
=E
0
-{e/ eE
0
, e incident cu v n
D
0
}; D
0
=(V
0
,E
0
)
Pas 4: Dac V
0
, atunci reia pasul 2; altfel scrie DA, stop.
Exemple
2.4.4 Pentru digraful,
44
1
4
2
3
5
e
1
e
4
e
2
e
3
e
5
evoluia algoritmului Marimont este,
Pas 1: V
0
={1,2,3,4,5}, E
0
={e1,e2,e3,e4,e5}
Pas 2: ( ) 0 5 od
0
D
= , continu
1
4
2
3
e
1
e
4
e
2
e
3
Pas 3: Selecteaz vrIul 5, elimin 5 din V
0
, elimin arcul e5 E
0
Pas 4: reia de la pasul 2
Pas 2: ( ) 1 i od
0
D
= pentru toi i din V
0
={1,2,3,4}, scrie NU, stop.
2.4.5. Pentru digraful D:
1
2
3
4 5
6
7
e
1
e
2
e
3
e
4
e
6
e
7
e
8
e
5
e
9
algoritmul Marimont determin urmtoarea secven de operaii:
Pas 1: V
0
={1,2,3,4,5,6,7}, E
0
={e1,e2,e3,e4,e5,e6,e7,e8,e9}
Pas 2: ( ) 0 7 od
0
D
= , continu
Pas 3: Selecteaz vrIul 7, elimin 7 din V
0
, elimin arcele e8 si e9 din E
0
D
0
:
1
2
3
4 5
6
e
1
e
2
e
3
e
4
e
6
e
7
e
5
Pas 4: reia de la pasul 2
Pas 2: ( ) 0 6 od
0
D
= , continu
Pas 3: Selecteaz vrIul 6, elimin 6 din V
0
, elimin arcul e7 din E
0
D
0
:
1
2
3
4 5
e
1
e
2
e
3
e
4
e
6
e
5
45
Pas 4: reia de la pasul 2
Pas 2: ( ) 0 5 od
0
D
= , continu
Pas 3: Selecteaz vrIul 5, elimin 5 din V
0
, elimin arcul e6 din E
0
D
0
:
1
2
3
4
e
1
e
2
e
3
e
4
e
5
Pas 4: reia de la pasul 2
Pas 2: ( ) 0 4 od
0
D
= , continu
Pas 3: Selecteaz vrIul 4, elimin 4 din V
0
, elimin arcele e4, e5 si e3 din E
0
D
0
:
1
2
3
e
1
e
2
Pas 4: reia de la pasul 2
Pas 2: ( ) 0 3 od
0
D
= , continu
Pas 3: Selecteaz vrIul 3, elimin 3 din V
0
, elimin arcul e2 din E
0
D
0
:
1
2
e
1
Pas 4: reia de la pasul 2
Pas 2: ( ) 0 2 od
0
D
= , continu
Pas 3: Selecteaz vrIul 2, elimin 2 din V
0
, elimin arcul e1 din E
0
D
0
: 1
Pas 4: reia de la pasul 2
Pas 2: ( ) 0 1 od
0
D
= , continu
Pas 3: Selecteaz vrIul 1, elimin 1 din V
0
V
0
=
Pas 4: scrie DA, stop.
Algoritmul Marimont poate fi descris n C astfel,
#i ncl ude<st di o. h>
#i ncl ude<coni o. h>
t ypedef st r uct {
i nt vi , vf ; } ar c;
i nt gr ad_ext er i or ( ar c *ar ce, i nt na, i nt v)
{
i nt od=0;
f or ( i nt i =0; i <na; i ++)
46
i f ( ar ce[ i ] . vi ==v) od++;
r et ur n od;
}
voi d el i mi na_var f ( i nt *var f , i nt *nv, i nt v)
{
i nt gasi t =0;
f or ( i nt i =0; ( i <*nv) &&! gasi t ; i ++)
i f ( var f [ i ] ==v) {
gasi t =1;
f or ( i nt j =i +1; j <*nv; j ++)
var f [ j - 1] =var f [ j ] ;
}
( *nv) - - ;
}
voi d el i mi na_ar ce( ar c *ar ce, i nt *na, i nt v)
{
f or ( i nt i =0; i <*na; )
i f ( ( ar ce[ i ] . vi ==v) | | ( ar ce[ i ] . vf ==v) ) {
f or ( i nt j =i +1; j <*na; j ++) {
ar ce[ j - 1] . vi =ar ce[ j ] . vi ;
ar ce[ j - 1] . vf =ar ce[ j ] . vf ;
}
( *na) - - ;
}
el se i ++;
}
i nt ci cl i c( i nt *var f , ar c *ar ce, i nt nv, i nt na)
{
f or ( i nt i =0; i <nv; i ++)
i f ( ! gr ad_ext er i or ( ar ce, na, var f [ i ] ) ) r et ur n 0;
r et ur n 1;
}
i nt Mar i mont ( i nt *var f , ar c *ar ce, i nt nv, i nt na)
{
whi l e( nv) {
pr i nt f ( " \ n\ nGr af ul cur ent \ n" ) ;
pr i nt f ( " Var f ur i : " ) ;
f or ( i nt i =0; i <nv; i ++) pr i nt f ( " %i " , var f [ i ] ) ;
pr i nt f ( " \ nAr ce: " ) ;
f or ( i =0; i <na; i ++) pr i nt f ( " ( %i , %i ) " , ar ce[ i ] . vi , ar ce[ i ] . vf ) ;
get ch( ) ;
i f ( ci cl i c( var f , ar ce, nv, na) ) r et ur n 0;
i nt gasi t =0;
f or ( i =0; ( i <nv) &&! gasi t ; i ++)
i f ( ! gr ad_ext er i or ( ar ce, na, var f [ i ] ) ) {
gasi t =1;
el i mi na_ar ce( ar ce, &na, var f [ i ] ) ;
el i mi na_var f ( var f , &nv, var f [ i ] ) ;
}
}
r et ur n 1;
}
voi d mai n( )
{
i nt n, nv, na;
i nt vf [ 20] , i , j , a[ 20] [ 20] ;
ar c ar ce[ 100] ;
cl r scr ( ) ;
47
pr i nt f ( " Numar ul de var f ur i " ) ;
scanf ( " %i " , &n) ;
f or ( i =0; i <n; i ++)
vf [ i ] =i +1;
nv=n; na=0;
pr i nt f ( " Mat r i cea de adi acent a: \ n" ) ;
f or ( i =0; i <n; i ++)
f or ( j =0; j <n; j ++) {
scanf ( " %i " , &a[ i ] [ j ] ) ;
i f ( a[ i ] [ j ] ) {
ar ce[ na] . vi =i +1;
ar ce[ na] . vf =j +1;
na++;
}
}
i f ( Mar i mont ( vf , ar ce, nv, na) )
pr i nt f ( " \ n\ nDi gr af ul est e aci cl i c" ) ;
el se pr i nt f ( " \ n\ nDi gr af ul est e ci cl i c" ) ;
get ch( ) ;
}
48
3. Structuri arborescente
Una dintre cele mai studiate clase de grafuri snt cele de tip arbore. n acest capitol snt
prezentate principalele caracteristici ale arborilor, algoritmi pentru calculul arborelui parial de
cost minim, arbori direcionai, arbori cu rdcin si arbori binari. Pe lng operaiile primitive
asupra arborilor cutarea unei inIormaii, inserarea unui nod, extragerea unui nod si metode de
parcurgere, snt prezentate dou clase importante de arbori binari: arbori de sortare si arbori de
structur.
3.1. Grafuri de tip arbore
3.1.1. Definiii yi caracterizri ale grafurilor arbori
Structurile cele mai simple si care apar cel mai Irecvent n aplicaii snt cele arborescente
(arbori). GraIurile arbori constituie o subclas a graIurilor conexe.
Definiia 3.1.1 Graful G este arbore dac G este aciclic si conex.
Definiia 3.1.2. Fie G=(V,E) graf arbore. Subgraful H=(V
1
,E
1
) al lui G este subarbore al
lui G dac H este graf arbore.
Exemple
3.1.1. Graful
1
2
3 4
5 6
7
este arbore, deoarece, orice (i,j) E , i=j, exist un i-j drum si graIul nu conine cicluri.
49
3.1.2. Graful
1
2
3
4
5
7
7
nu este arbore, deoarece drumul :1,4,6,2,1 este un ciclu.
3.1.3. Graful
1
2
3
4
5
6
7
8
9
nu este arbore, deoarece conine trei componente conexe: 1,2,3,4,6}, 3} si 7,8}.
Verificarea proprietii unui graI de a Ii arbore poate Ii realizat prin intermediul unor
algoritmi care s veriIice calitile de conexitate si respectiv aciclicitate. De asemenea, veriIicarea
proprietii unui graI de a Ii arbore poate Ii realizat astIel.
Proprietatea 1. Un graf G=(V,E), cu m E , n V = = este graI arbore dac si numai dac
G este aciclic si n=m+1.
Exemple
3.1.4. Graful din 3.1.1 este arbore, pentru c este aciclic si n=7, m=6.
3.1.5. Graful din 3.1.2. nu este arbore pentru c este ciclic.
3.1.6. Graful din exemplul 3.1.3. nu este arbore deoarece este aciclic, dar n=9, m=6.
Proprietatea 2 Un graf G=(V,E), cu m E , n V = = este graI arbore dac si numai dac
G este conex si n=m+1.
Exemple
3.1.7. Graful din 3.1.1. este arbore deoarece este conex si n=m+1.
3.1.8. Graful conex din exemplul 3.1.2. nu este arbore pentru c n6 si m=8.
3.1.9. Graful din 3.1.3. nu este conex, deci nu este graf arbore.
Observaie
Fie G=(V,E) un graI. Urmtoarele aIirmaii snt echivalente,
1. G este graf arbore;
2. G este graf conex minimal: oricare ar fi eE, prin eliminarea muchiei e din E, graful
rezultat nu este conex;
3. G este graI aciclic maximal: prin adugarea unei noi muchii n graI rezult cel puin
un ciclu.
50
Definiia 3.1.3. Se numeste graf asimetric un digraf D=(V,E) cu proprietatea c pentru
orice E v , u dac uvE, atunci vuE. Digraful D este simetric dac , E v , u uvE, dac si
numai dac vuE.
Definiia 3.1.4. Fie D=(V,E) digraf netrivial. Graful G=(V,E), unde E={uv/ uvE sau
vuE} se numeste graf suport al digrafului D.
Definiia 3.1.5. Un arbore direcionat este un graI orientat asimetric si astIel nct graful
suport corespunztor lui este graI arbore.
Definiia 3.1.6. Arborele direcionat T=(V,E) este arbore cu rdcin dac exist rV
astfel nct, pentru orice uV, u r, exist r-u drum n T. Vrful r se numeste rdcina arborelui
direcionat T.
Definiia 3.1.7. Fie T=(V,E) arbore direcionat. Arborele T
1
=(V
1
,E
1
) este subarbore al lui
T dac V
1
V, E
1
E si T
1
este arbore direcionat.
Observaie GraIul suport al unui arbore direcionat este aciclic, deci, pentru orice uV,
u r, r-u drumul din T este unic. De asemenea, un arbore direcionat are cel mult o rdcin.
Rezult c, pentru orice uV, u r, distana de la rdcin la vrful u este egal cu numrul de
muchii ale r-u drumului n T.
Exemple
3.1.10. Arborele direcionat
1
2
3 4
5
6
7 8 9
10
este arbore cu rdcin 1.
3.1.11 Arborele direcionat
1 2
3
4
5 6
7
nu are rdcin.
3.1.12. Arborele
51
1
2
4
5
6
8
10
este un subarbore cu rdcin 1 al arborelui din 3.1.10.
3.1.2. Reprezentri yi parcurgeri ale arborilor orientai
Definiia 3.1.8. Un arbore orientat este un arbore direcionat cu rdcin.
Definiia 3.1.9. Fie T=(V,E), un arbore orientat cu rdcin r. Un vrf v V este
situat pe nivelul i al arborelui T, dac distana de la vrI la rdcin este egal cu i. Rdcina
arborelui este considerat de nivel 0.
Deoarece orice arbore orientat este n particular digraI, reprezentarea arborilor orientai
poate Ii realizat prin utilizarea oricreia dintre modalitile prezentate n 8.1. Datorit
caracteristicilor arborilor orientai pot Ii ns obinute reprezentri mai eIiciente din punct de
vedere al spaiului de memorie solicitat.
Una dintre modaliti este reprezentarea de tip FIU-FRATE, care const n numerotarea
convenional a vrIurilor graIului si memorarea, pentru fiecare vrf i al arborelui, a urmtoarelor
inIormaii,
- FIU(i): numrul atasat primului descendent al vrfului i;
- FRATE(i): numrul atasat vrIului descendent al tatlui vrfului i si care urmeaz
imediat lui i;
- INF(i): inIormaia atasat vrfului i (de obicei valoarea i).
Pentru reprezentarea arborelui snt reinute rdcina si numrul nodurilor. Absena
fiului, respectiv a :fratelui unui vrI este marcat printr-o valoare din aIara mulimii de numere
atasate vrfurilor (de obicei valoarea 0).
Exemplu
3.1.13. Arborele orientat
52
1
2 3 4
5 6 7 8
9 10 11 12 13 14 15 16
este reprezentat astfel,
N16, R1 (rdcina),
FIU=(2,5,0,8,0,9,0,14,0,0,0,0,0,0,0,0)
FRATE=(0,3,4,0,6,7,0,0,10,11,12,13,0,15,16,0)
O alternativ a reprezentrii FIU-FRATE poate Ii obinut prin utilizarea structurile
de date dinamice. Presupunnd c Iiecare vrf al arborelui are cel mult n descendeni, Iiecrui
vrI i este atasat structura,
vector de legturi ctre descendenii vrfului identificator
vrf
adres Iiu 1 adres Iiu n
Urmtoarea surs C implementeaz problema construciei unui arbore orientat,
reprezentat prin intermediul unei structuri dinamice arborescente. Numrul maxim de
descendeni ai unui nod este 4. n cazul unui numr mai mare de descendeni este preIerat n
general reprezentarea FIU-FRATE, datorit dimensiunii spaiului de memorie ocupat.
AIisarea inIormaiilor arborelui creat este realizat prin traversarea n A-preordine (a se vedea
paragraIul urmtor).
#i ncl ude<st di o. h>
#i ncl ude<coni o. h>
#i ncl ude<al l oc. h>
t ypedef st r uct nod{
i nt i nf ;
st r uct nod *f i u[ 4] ;
} ar b, *ar bor e;
voi d i nser ar e_t at a( ar bor e *pt at a, i nt k, i nt i nf o)
{ ar bor e nou=( ar bor e) mal l oc( si zeof ( ar b) ) ;
nou- >i nf =i nf o;
f or ( i nt i =0; i <4; i ++) nou- >f i u[ i ] =NULL;
( *pt at a) - >f i u[ k] =nou;
}
53
voi d i nser ar e( ar bor e *ppr ed)
{ i nt j , i nf o;
ar bor e *pr ed;
f or ( i nt nr =0; ( *ppr ed) - >f i u[ nr ] ; nr ++) {
( *pr ed) =( *ppr ed) - >f i u[ nr ] ;
pr i nt f ( " Numar ul de f i i ai nodul ui %i : " , ( *pr ed) - >i nf ) ;
scanf ( " %i " , &j ) ;
f or ( i nt k=0; k<j ; k++) {
scanf ( " %i " , &i nf o) ;
i nser ar e_t at a( pr ed, k, i nf o) ;
}
}
f or ( nr =0; ( *ppr ed) - >f i u[ nr ] ; nr ++)
i nser ar e( &( ( *ppr ed) - >f i u[ nr ] ) ) ;
}
voi d A_pr eor di ne( ar bor e r )
{
i f ( r ) {
pr i nt f ( " %i " , r - >i nf ) ;
f or ( i nt i =0; i <4; i ++)
A_pr eor di ne( r - >f i u[ i ] ) ;
}
}
voi d mai n( ) {
cl r scr ( ) ;
i nt n, j , i nf o;
ar bor e r adaci na=NULL;
pr i nt f ( " I nt r oducet i i nf or mat i i l e pe ni vel ur i \ n" ) ;
pr i nt f ( " I nt r oducet i r adaci na\ n" ) ;
scanf ( " %i " , &i nf o) ;
r adaci na=( ar bor e) mal l oc( si zeof ( ar b) ) ;
r adaci na- >i nf =i nf o;
f or ( i nt i =0; i <4; i ++) r adaci na- >f i u[ i ] =NULL;
pr i nt f ( " Numar ul de f i i ai nodul ui %i " , r adaci na- >i nf ) ;
scanf ( " %i " , &j ) ;
f or ( i nt k=0; k<j ; k++) {
scanf ( " %i " , &i nf o) ;
i nser ar e_t at a( &r adaci na, k, i nf o) ;
}
ar bor e ppr ed=r adaci na;
i nser ar e( &ppr ed) ;
pr i nt f ( " Par cur ger ea A- pr eor di ne a ar bor el ui : \ n" ) ;
A_pr eor di ne( r adaci na) ;
get ch( ) ; }
Parcurgerea unui arbore orientat revine la aplicarea sistematic a unei reguli de
vizitare a vrIurilor arborelui. Cele mai utilizate reguli de parcurgere a arborilor orientai snt
A-preordine, A-postordine si parcurgerea pe niveluri.
Parcurgerea n A-preordine
Modalitatea de vizitare a vrfurilor n parcurgerea n A-preordine poate Ii descris
astIel. Iniial, rdcina arborelui este selectat drept vrf curent. Este vizitat vrIul curent si
snt identiIicai descendenii lui. Se aplic aceeasi regul de vizitare pentru arborii avnd ca
rdcini descendenii vrIului curent, arborii Iiind vizitai n ordinea precizat prin numerele
atasate vrIurilor rdcin corespunztoare.
54
Exemplu
3.1.14. Pentru arborele orientat din exemplul 3.1.13., prin aplicarea parcurgerii n A-
preordine, rezult: 1,2,5,6,9,10,11,12,13,7,3,4,8,14,15,16.
n reprezentarea FIU-FRATE, implementarea parcurgerii n A-preordine este
realizat prin urmtoarea Iuncie recursiv, cu parametru de intrare rdcina arborelui curent.
void A_preordine (nod R)
{
if (R){
vizit (R);
A_preordine(FIU[R]);
A_preordine(FRATE[R]);
}
}
n sursa prezentat n paragraIul precedent, Iuncia A-preordine implementeaz acest
tip de traversare n cazul arborilor orientai reprezentai prin intermediul structurilor
arborescente.
Parcurgerea A-postordine
Regula de parcurgerea n A-postordine este asemntoare traversrii A-preordine,
singura diIeren Iiind aceea c, n acest tip de traversare, rdcina Iiecrui arbore este
vizitat dup ce au Iost vizitate toate celelalte vrfuri ale arborelui.
Exemplu
3.1.15. Pentru arborele orientat din exemplul 3.1.13. ordinea de vizitare a vrfurilor
este: 5,9,10,11,12,13,6,7,2,3,14,15,16,8,4,1.
Pentru arbori reprezentai prin structuri dinamice de date, implementarea parcurgerii
n A-postordine poate Ii obinut pe baza urmtoarei Iuncii recursive. Parametrul de intrare
al Iunciei A_postordine reprezint rdcina arborelui curent n momentul apelului.
void A_postordine (nod R)
{
if (R) {
for(i=0;i<n;i++) A_postordine(R->leg[i]);
vizit (R);
}
}
Observaie Parcurgerile n A-preordine si A-postordine snt variante de parcurgeri n
adncime (variante ale metodei DF). Ambele metode consider prioritare vrfurile aflate la
distan maxim Ia de rdcina arborelui iniial.
Parcurgerea pe niveluri
Parcurgerea unui arbore orientat pe niveluri const n vizitarea vrfurilor sale n
ordinea cresctoare a distanelor Ia de rdcin.
Exemplu
3.1.16. Pentru arborele definit n exemplul 3.1.13., prin aplicarea parcurgerii pe
niveluri, rezult urmtoarea ordine de vizitare a nodurilor, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16.
Ca si n cazul metodei BF, implementarea parcurgerii pe niveluri este bazat pe
utilizarea unei structuri de coad C. La momentul iniial rdcina arborelui este inserat n C.
55
Atta timp ct timp coada este nevid, este preluat cu stergere un vrf din C, este vizitat si snt
introdusi n coad descendenii si. Calculul este ncheiat cnd C=.
n cazul reprezentrii FIU-FRATE a arborelui de traversat, parcurgerea pe niveluri
poate Ii implementat prin urmtoarea Iuncie.
voi d par cur ger e_pe_ni vel ur i ( nod R, i nt FI U[ ] , i nt FRATE[ ] , i nt n)
{
pt coada C=NULL; push( C, R) ;
whi l e ( C) {
pop( C, v) ; VI ZI T( v) ;
v=FI U[ v] ;
whi l e ( v) {
push( C, v) ; v=FRATE[ v] ;
}
}
}
Observaie Funciile push si pop implementeaz inserarea unuei celule n coad,
respectiv extragerea unui element al cozii.
Exemplu
3.1.17. Pentru arborele de la exemplul 3.1.13., evoluia algoritmului este,
C
t
t=1 1 8
t=2 2 3 4
t=3 3 4 5 6 7
t=4 4 5 6 7
t=5 5 6 7 8
t=6 6 7 8
t=7 7 8 9 1
0
1
1
1
2
1
3
t=8 8 9 1
0
1
1
1
2
1
3
56
t=9 9 1
0
1
1
1
2
1
3
1
4
1
5
1
6
t=10 1
0
1
1
1
2
1
3
1
4
1
5
1
6
t=11 1
1
1
2
1
3
1
4
1
5
1
6
t=12 1
2
1
3
1
4
1
5
1
6
t=13 1
3
1
4
1
5
1
6
t=14 1
4
1
5
1
6
t=15 1
5
1
6
t=16 1
5
t=17
deci vrfurile snt vizitate n ordinea: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16.
Observaie Metoda BF pentru parcurgerea grafurilor este o generalizare a tehnicii de
parcurgere pe niveluri a arborilor orientai.
O alternativ de implementare a parcurgerii pe niveluri poate Ii descris prin
intermediul Iunciilor recursive frati si parc. Coada C este o variabil global si este
iniializat cu rdcina arborelui. Parcurgerea este realizat prin apelul parc(C).
voi d f r at i ( v)
{i f ( v) {push( C, v) ;
frai(FRATE[v]);
}
}
voi d par c( )
{i f ( C) {pop( C, v) ; VI ZI T( v) ;
f r at i ( FI U[ v] ) ; par c( ) ;
}
}
57
3.1.3. Arbori pariali. Algoritmul Kruskal
Definiia 3.1.10. Fie G un graI. SubgraIul parial H este un arbore parial al lui G
dac H este graf arbore.
Definiia 3.1.11. Fie G=(V,E,w) un graI ponderat conex.Dac T=(V,E
0
) este un arbore
parial al graIului G=(V,E), ponderea arborelui T, notat W(T), este deIinit prin
W(T)=

0
E e
) e ( w .
Exemplu
3.1.18. Pentru graful ponderat
1
2
3
4
5 6 2
2
4 3
1
9
12
8
T este un arbore parial de pondere 32.
1
2
2 3 4
6 5
8 9
4 3
Definiia 3.1.12. Arborele parial T
0
T(G) este arbore parial minim pentru G dac
W(T
0
)=min{W(T); TT(G)}, unde T(G) este mulimea arborilor pariali corespunztori
grafului G.
Observaie Dac G este graf finit, atunci T(G) este o mulime Iinit, deci orice graf
Iinit ponderat si conex are cel puin un arbore parial minim.
n continuare este prezentat algoritmul Kruskal pentru determinarea unui arbore
parial minim al unui graI ponderat conex G=(V,E,w).
Pas 1: i=1; E
0
=
Pas 2: Determin Re/eE \ E
i-1
astfel nct graful (V,E
i-1
{e}) este aciclic}
Dac R, atunci stop; altIel, selecteaz e
i
R cu w(e
i
)=min{w(e), eR}; E
i
=E
i-
1
{e
i
}
58
Pas 3: ii1 si reia pasul 2.
Arborele parial de cost minim al graIului G este (V,E
i-1
).
Pentru implementarea algoritmului Kruskal, graful conex ponderat este reprezentat
sub Iorm tabelar, muchiile Iiind ordonate cresctor dup ponderi. Muchiile selectate de
algoritm pot Ii meninute de asemenea ntr-o structur tabelar, sau doar marcate ca fiind
incluse n mulimea de muchii din arborele parial minim a crui construcie este dorit. n
varianta prezentat n continuare muchiile selectate snt aIisate.
VeriIicarea condiiei ca muchia selectat s nu Iormeze nici un ciclu cu muchiile
selectate la etapele precedente este realizat prin utilizarea un vector TATA, deIinit astIel.
Pentru fiecare vrf i (vrfurile grafului fiind numerotate de la 1 la n, unde n este numrul de
noduri ale graIului), componenta TATA |i| este predecesorul su n arborele care conine
vrful i construit pn la momentul curent dac i nu este rdcina acelui arbore, respectiv
TATA[i] este egal cu numrul de vrfuri ale arborelui de rdcin i, n caz contrar.
Componentele vectorului TATA snt iniializate cu valoarea -1.
Calculul care realizeaz adugarea unei noi muchii poate Ii descris astIel. Este
determinat o muchie de cost minim ev1v2 care nu a Iost selectat anterior. Dac vrfurile
v1 si v2 nu aparin aceluiasi arbore, atunci proprietatea de aciclicitate este ndeplinit si
muchia e este adugat la structura curent. Adugarea muchiei e selectate este realizat prin
reunirea arborilor din care fac parte v1 si v2 de rdcini r1, respectiv r2, astIel: dac
TATA[r1]<TATA[r2], atunci arborele rezultat prin reunirea celor doi arbori are ca rdcin
vrful r1, iar vrful r2 devine fiu al lui r1. AltIel, rdcina arborelui rezultat prin reunire Iiind
r2, iar r1 devenind Iiu al rdcinii. Calculul se ncheie dup ce a Iost adugat si cea de-a (n-
1)-a muchie.
Algoritmul Kruskall poate fi implementat prin urmtoarea surs C:
#i ncl ude<st di o. h>
#i ncl ude<coni o. h>
i nt r adaci na( i nt v, i nt *t at a)
{ i nt u=v;
whi l e( t at a[ u] >=0) u=t at a[ u] ;
r et ur n u; }
i nt kr uskal ( i nt a[ ] [ 3] , i nt nm, i nt nv)
{
i nt t at a[ 50] , i , j ;
i nt c=0;
f or ( i =0; i <nv; i ++) t at a[ i ] =- 1;
f or ( j =i =0; i <nv- 1; j ++) {
i nt v1=a[ j ] [ 0] ; i nt v2=a[ j ] [ 1] ;
i nt k=r adaci na( v2, t at a) ; i nt p=r adaci na( v1, t at a) ;
i f ( k- p) {
i f ( t at a[ k] <t at a[ p] ) {
t at a[ k] +=t at a[ p] ; t at a[ p] =k;
}
el se{
t at a[ p] +=t at a[ k] ; t at a[ k] =p;
}
c+=a[ j ] [ 2] ; pr i nt f ( " %i - > %i cost %i \ n" , v1+1, v2+1, a[ j ] [ 2] ) ;
i ++;
}
}
r et ur n c;
}
voi d mai n( )
{
cl r scr ( ) ;
59
i nt nv, nm, a[ 100] [ 3] ;
pr i nt f ( " Numar ul de var f ur i : " ) ; scanf ( " %i " , &nv) ;
pr i nt f ( " Numar ul de muchi i " ) ; scanf ( " %i " , &nm) ;
pr i nt f ( " Mat r i cea de r epr ezent ar e\ n" ) ;
f or ( i nt i =0; i <nm; i ++)
f or ( i nt j =0; j <3; j ++)
scanf ( " %i " , &a[ i ] [ j ] ) ;
f or ( i =0; i <nm; i ++)
f or ( i nt j =0; j <2; j ++) a[ i ] [ j ] - - ;
pr i nt f ( " Ar bor el e de cost mi ni m: \ n" ) ;
i nt cost =kr uskal ( a, nm, nv) ;
pr i nt f ( " \ ncu cost ul %i " , cost ) ;
get ch( ) ;
}
Exemplu
3.1.19. Evoluia determinat de program pentru graIul
1
2 6 5
4 3
2
8 1
4
9
2 3 4
8
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
_
=
9 6 3
8 6 5
8 6 4
4 2 1
4 4 3
3 5 1
2 6 1
2 4 2
1 3 2
A
este:
i, j dup cea de-a t-a iteraie muchia selectat TATA Costul
t=0 (-1,-1,-1,-1,-1,-1)
t=1,i=0,j=0 (2,3) (-1,-2,2,-1,-1,-1) 1
t=2,i=1,j=1 (2,4) (-1,-3,2,2,-1,-1) 2
t=3,i=2,j=2 (1,6) (-2,-3,2,2,-1,1) 2
t=4,i=3,j=3 (1,5) (-3,-3,2,2,1,1) 3
t=5,i=4,j=4 (-3,-3,2,2,1,1)
t=6,i=4,j=5 (1,2) (-5,1,1,2,1,1) 4
MUCHIILE ARBORELUI MINIM: {(2,3),(2,4),(1,6),(1,5),(1,2)} COSTUL:
12
60
3.2. Arbori binari
3.2.1. Reprezentarea arborilor binari. Modaliti de parcurgere
Definiia 3.2.1. Un arbore binar este un arbore orientat cu proprietatea c pentru orice vrf
v, od(v)2. Dac od(v)2, cei doi descendeni snt desemnai ca descendent stng (fiu stnga)
respectiv descendent drept (fiu dreapta). Pentru vrfurile cu od(v)=1, unicul descendent este
specificat fie ca fiu stnga, fie ca fiu dreapta.
Definiia 3.1.2. Se numeste nod terminal orice vrf v al arborelui cu od(v)=0. n caz
contrar nodul v este neterminal.
Reprezentarea unui arbore binar este realizat printr-o structur arborescent. Pentru
fiecare nod N al arborelui binar snt memorate inIormaia asociat lui N si legturile ctre
descendenii lui. Absena unui descendent este reprezentat prin NULL.
identificator
nod
legtur Iiu
stng
legtur Iiu
drept
Definiia 3.2.3. Fie T=(V,E) un arbore binar cu rdcina R. Subarborele stng al lui T este
ST=(V\{R},E\{RS}), unde S este fiul stnga al rdcinii. Subarborele drept al lui T este
DT=(V\{R},E\{RD}), unde D este Iiul dreapta al rdcinii.
Exemplu
3.2.1. Pentru arborele binar,
1
2 3
4 5 6 7
8 9 10
subarborii rdcinii snt:
2
4 5
8
3
6 7
9 10
Subarbore stng Subarbore drept
n plus Ia de metodele A-preordine, A-postordine si pe niveluri, parcurgerile n
preordine (RSD), inordine (SRD) si respectiv postordine (SDR) snt special considerate pentru
arbori binari si au multiple aplicaii. Regula de vizitare pentru aceste tipuri de parcurgere revine la
parcurgerea subarborelui stng si parcurgerea subarborelui drept corespunztori vrfului curent.
La momentul iniial vrful curent este rdcina arborelui. DiIerena dintre cele trei tipuri de
parcurgere este dat de momentul n care devine vizitat Iiecare vrf al arborelui. n parcurgerea
RSD (rdcin-subarbore stng-subarbore drept), fiecare vrf al arborelui este vizitat n momentul
n care este vrf curent; n parcurgerea SRD, vizitarea vrfului curent R este eIectuat dup ce a
fost parcurs subarborele stng al lui R, respectiv n parcurgerea SDR vizitarea Iiecrui vrf este
eIectuat dup ce au Iost parcursi subarborii aIereni lui.
61
Exemplu
3.2.2. Pentru arborele de la exemplul 3.2.1., secvenele de vrfuri rezultate prin
aplicarea parcurgerilor RSD, SRD, SDR snt:
- preordine: 1,2,4,8,5,3,6,9,10,7
- inordine: 4,8,2,5,1,9,6,10,3,7
- postordine: 8,4,5,2,9,10,6,7,3,1.
3.2.2. Arbori de sortare
Definiia 3.2.4. Un arbore de sortare este un arbore binar cu urmtoarele proprieti,
- Iiecrui nod i al arborelui i este atasat o inIormaie INF(i) dintr-o mulime ordonat
de valori;
- pentru fiecare nod i, INF(i) este mai mare dect INF(j), pentru toate nodurile j din
subarborele stng al arborelui cu rdcin i;
- pentru fiecare nod i, INF(i) este mai mic dect INF(j), pentru toate nodurile j din
subarborele drept al arborelui cu rdcin i;
- pentru orice vrfuri i si j daca ij atunci INF(i)INF(j).
Exemplu 3.2.3. Arborele binar
50
30 70
10 40 90
20 80
este arbore de sortare.
Operaiile primitive asupra arborilor de sortare snt inserarea unui nod, stergerea unui nod
si parcurgerea arborelui (n preordine, inordine sau postordine). Inserarea si stergerea de noduri
aplicate unui arbore de sortare trebuie realizate astfel nct arborele rezultat s Iie de asemenea
arbore de sortare.
Observaie Parcurgerea n inordine a unui arbore de sortare determin obinerea
secvenei inIormaiilor asociate vrIurilor arborelui n ordine cresctoare.
Inserarea unui nod ntr-un arbore de sortare
Algoritmul de inserare a unei inIormaii nr n arborele de sortare de rdcin rad este
recursiv si const n eIectuarea urmtoarelor operaii: vrful curent v la momentul iniial este
rdcina arborelui; dac arborele de rdcin v este vid, este generat arborele cu un singur nod, cu
inIormaia atasat nr; altfel:
- dac inIormaia atasat nodului v este mai mare dect nr, atunci vrf curent
devine fiul stnga al lui v;
- dac inIormaia atasat nodului v este egal cu nr, atunci stop;
- dac inIormaia atasat nodului v este mai mic dect nr, atunci vrf curent
devine fiul dreapta al lui v.
62
Exemplu
3.2.4. Aplicarea algoritmul descris pentru inserarea inIormaiei 55 n arborele de sortare
din exemplul 3.2.3. determin urmtoarele operaii,
INF(v)50; 5055, insereaz n subarborele cu rdcina avnd inIormaia atasat 70.
INF(v)70; 70~55, insereaz n subarborele stng cu rdcina NULL.
Este creat nodul cu inIormaie 55, Iiu stng al nodului de inIormaie 70.
Arborele rezultat este
50
30 70
10 40 90
20 80
55
$tergerea unei informaii dintr-un arbore de sortare
Algoritmul pentru stergerea unei inIormaii nr din arborele de sortare de rdcin rad este
recursiv si poate Ii descris astIel. Vrful curent v la momentul iniial este rdcina arborelui.
1. dac arborele este vid atunci stop;
2. altfel
a) dac inIormaia atasat nodului v este mai mare dect nr, atunci vrful curent devine fiul
stnga al lui v;
b) dac inIormaia atasat nodului v este mai mic dect nr, vrful curent devine fiul dreapta al
lui v;
c) dac INF(v)nr atunci:
c1) dac subarborele stng este vid, atunci adresa vrfului v este memorat ntr-o celul
suplimentar aux, v devine fiul dreapta al lui v, iar celula aux este eliberat din memorie;
c2) dac subarborele stng este nevid atunci se determin cel mai mare element din
subarborele stng;
c2.1) dac Iiul stnga al lui v nu are subarbore drept, atunci inIormaia atasat Iiului
stnga se transIer n vrful curent, iar fiul stnga este nlocuit cu Iiul su stnga si este
eliberat memoria corespunztoare celulei v->fius;
c2.2) altIel, se transIer n rdcin inIormaia atasat ultimului nod p determinat la
c2), nodul p este nlocuit cu Iiul su stng si celula corespunztoare lui p este
eliberat din memorie.
Exemplu
3.2.5. Stergerea inIormaiei 70 din arborele de sortare din exemplul 3.2.4. este realizat
astfel:
70~50, decide stergerea din subarborele drept
7070, decide stergerea din arborele curent: rdcina etichetat cu 70; exist subarbore
stng iar acesta nu are subarbore drept- nodul cu inIormaie 70 este etichetat cu 55, iar p este
nlocuit cu subarborele su stng (vid). Arborele rezultat
63
50
30 55
10 40 90
20 80
este arbore de sortare.
Observaie
Punctul c) de la pasul 2 al algoritmului de eliminare a unei inIormaii dintr-un arbore de
sortare poate fi nlocuit cu:
c) dac INF(v)=nr atunci:
c1) dac subarborele drept este vid, atunci adresa vrfului v este memorat ntr-o celul
suplimentar aux, v devine fiul stnga al lui v, iar celula aux este eliberat din memorie;
c2) dac subarborele drept este nevid atunci se determin cel mai mic element din
subarborele drept, altfel
c2.1.) dac Iiul dreapta al lui v nu are subarbore stng, atunci inIormaia atasat Iiului
dreapta este transIerat n vrIul curent, iar Iiul dreapta este nlocuit cu Iiul su
dreapta si este eliberat memoria corespunztoare celulei v->fiud.
c2.2) altIel, se transIer n rdcin inIormaia atasat ultimului nod p determinat la
c2), nodul p este nlocuit cu Iiul su dreapta si celula corespunztoare lui p este
eliberat din memorie.
n urmtoarea surs C snt implementai algoritmii de adugare si stergere n arbori de
sortare.
#i ncl ude<st di o. h>
#i ncl ude<coni o. h>
#i ncl ude<al l oc. h>
t ypedef st r uct nod{
i nt i nf ;
st r uct nod *l , *r ;
} ar b, *ar bor e;
voi d i nser ar e( ar bor e *r adaci na, i nt i nf o)
{
i f ( *r adaci na==NULL) {
ar bor e nou;
nou=( ar bor e) mal l oc( si zeof ( ar b) ) ;
nou- >i nf =i nf o;
nou- >l =nou- >r =NULL;
*r adaci na=nou;
}
el se i f ( ( *r adaci na) - >i nf >i nf o)
i nser ar e( &( ( *r adaci na) - >l ) , i nf o) ;
el se i f ( ( *r adaci na) - >i nf <i nf o)
i nser ar e( &( ( *r adaci na) - >r ) , i nf o) ;
}
i nt ext r ager e( ar bor e *r adaci na, i nt i nf o)
{
64
i f ( *r adaci na==NULL) r et ur n 0;
el se i f ( ( *r adaci na) - >i nf >i nf o)
r et ur n ext r ager e( &( ( *r adaci na) - >l ) , i nf o) ;
el se i f ( ( *r adaci na) - >i nf <i nf o)
r et ur n ext r ager e( &( ( *r adaci na) - >r ) , i nf o) ;
el se{
i f ( ( *r adaci na) - >l ==NULL) {
ar bor e aux=*r adaci na;
*r adaci na=( *r adaci na) - >r ;
f r ee( aux) ;
}
el se{
ar bor e p, p1;
f or ( p=( *r adaci na) - >l ; p- >r ; p1=p, p=p- >r ) ;
i f ( ( ( *r adaci na) - >l ) - >r ==NULL) {
( *r adaci na) - >i nf =p- >i nf ;
( *r adaci na) - >l =p- >l ;
f r ee( p) ;
}
el se{
( *r adaci na) - >i nf =p- >i nf ;
ar bor e aux=p;
p1- >r =p- >l ;
f r ee( aux) ;
}
}
r et ur n 1;
}
}
voi d sr d( ar bor e r adaci na)
{
i f ( r adaci na) {
sr d( r adaci na- >l ) ;
pr i nt f ( " %i " , r adaci na- >i nf ) ;
sr d( r adaci na- >r ) ;
}
}
voi d mai n( )
{
cl r scr ( ) ;
i nt n, i nf o;
ar bor e r adaci na=NULL;
pr i nt f ( " Numar ul de nodur i : " ) ;
scanf ( " %i " , &n) ;
pr i nt f ( " I nt r oducet i i nf or mat i i l e\ n" ) ;
f or ( i nt i =0; i <n; i ++) {
scanf ( " %i " , &i nf o) ;
i nser ar e( &r adaci na, i nf o) ;
}
pr i nt f ( " Par cur ger ea SRD a ar bor el ui de sor t ar e: \ n" ) ;
sr d( r adaci na) ;
pr i nt f ( " \ nI nf or mat i a nodul ui de ext r as: " ) ;
scanf ( " %i " , &i nf o) ;
i f ( ext r ager e( &r adaci na, i nf o) ) {
pr i nt f ( " \ nAr bor el e r ezul t at i n par cur ger e SRD\ n" ) ;
sr d( r adaci na) ;
}
el se pr i nt f ( " \ nI nf or mat i a nu est e i n ar bor e" ) ;
get ch( ) ;
}
65
3.2.3. Arbori de structur
Expresiile aritmetice n care intervin numai operatori binari pot fi reprezentate prin
intermediul arborilor binari n care fiecare nod neterminal are doi fii.
Definiia 3.2.5. Un arbore de structur are vrfurile etichetate astfel:
- fiecare nod neterminal este etichetat cu un simbol corespunztor unuia dintre operatori;
- fiecare nod terminal este etichetat cu un operand.
Construcia arborelui de structur corespunztor unei expresii aritmetice date se
realizeaz pe baza parantezrii existente n expresie si a prioritilor convenional asociate
operatorilor (ordinea operaiilor) astIel nct rdcina Iiecrui subarbore este etichetat cu
operatorul care se execut ultimul n evaluarea subexpresiei corespunztoare acelui subarbore.
Exemplu
3.2.6. Pentru expresia matematic (ab)*(c-d)+e/g, arborele de structur corespunztor
este
+
*
/
+ - g
c b
e
d a
Construcia arborelui de structur pentru o expresie s este realizat n dou etape:
1. atasarea de prioriti operatorilor si operanzilor; prioritile atasate permit eliminarea
parantezelor Ir ca semniIicaia expresiei s se modiIice;
2. construcia propriu-zis.
Prima etap este realizat astIel:
- prioritatea iniial a operatorilor `,`- este 1 (dac expresia nu conine paranteze
atunci n construcie acesti operatori vor Ii primii luai n considerare n ordinea de la
dreapta la stnga);
- prioritatea iniial a operatorilor /`,`* este 10 (dac expresia nu conine paranteze,
acestia snt considerai dup operatorii de prioritate 1 n ordinea de la dreapta la
stnga);
- prioritatea Iiecrui operator este incrementat cu valoarea 10 pentru Iiecare pereche de
paranteze n interiorul crora se aIl;
- prioritatea atasat Iiecrui operand este MAXINT.
Dup stabilirea sistemului de prioriti snt eliminate parantezele din expresie, ordinea de
eIectuare a operaiilor n cadrul expresiei Iiind indicat de vectorul de prioriti atasat.
Construcia arborelui de structur pe baza expresiei s din care au fost eliminate
parantezele si a vectorului de prioriti, poate Ii realizeaz recursiv n modul urmtor (la
momentul iniial expresia curent este expresia dat):
- pentru expresia curent se determin operatorul/operandul de prioritate minim care se
ataseaz ca etichet a rdcinii r a subarborelui de structur corespunztor ei; Iie i
poziia acestuia n cadrul expresiei;
66
- dac expresia are un singur simbol, atunci r->fius=r->fiud=NULL;
- altIel, se consider subexpresiile s1 si s2, constnd din simbolurile de pe poziiile 0 pn
la i-1 si respectiv i+1 pn la lungimea sirului s.; arborii de structur corespunztori
subexpresiilor s1 si s2 se ataseaz ca subarbore stng, respectiv subarbore drept vrfului
r.
Exemplu 3.2.7. Etapele calculului sistemului de prioriti si al arborelui de structur
pentru expresia de la exemplul 3.2.6. pot fi descrise astfel,
Dim vectorul prioritate
1 (MAXINT)
2 (MAXINT,11)
3 (MAXINT,11,MAXINT)
3 (MAXINT,11,MAXINT)
4 (MAXINT,11,MAXINT,10)
4 (MAXINT,11,MAXINT,10)
5 (MAXINT,11,MAXINT,10,MAXINT)
6 (MAXINT,11,MAXINT,10,MAXINT,11)
7 (MAXINT,11,MAXINT,10,MAXINT,11,MAXINT)
7 (MAXINT,11,MAXINT,10,MAXINT,11,MAXINT)
8 (MAXINT,11,MAXINT,10,MAXINT,11,MAXINT,1)
9 (MAXINT,11,MAXINT,10,MAXINT,11,MAXINT,1,MAXINT)
10 (MAXINT,11,MAXINT,10,MAXINT,11,MAXINT,1,MAXINT,10)
11 (MAXINT,11,MAXINT,10,MAXINT,11,MAXINT,1,MAXINT,10,MAXINT)
Dup eliminarea parantezelor, expresia rezultat este sab*c-d+e/g.
Arborele de structur este construit astIel:
n construcie
+
n construcie
*
n construcie
+
n construcie n construcie
*
+
n construcie
+
n construcie
n construcie
n construcie *
+
a
n construcie
+
n construcie
n construcie
67
*
+
b a
n construcie
+
n construcie
*
+ -
b a
n construcie
+
n construcie n construcie
*
+ -
c b a
n construcie
+
n construcie
*
+ -
c b d a
n construcie
+
*
/
+ -
c b d a
n construcie
+
n construcie
*
/
+ -
c b
e
d a
n construcie
+
68
*
/
+ - g
c b
e
d a
+
Observaie Construcia arborelui de structur poate Ii realizat n ipoteza n care expresia
este corect.
Definiia 3.2.6. Se numeste forma polone: direct a unei expresii, expresia rezultat n
urma parcurgerii RSD a arborelui de structur. Se numeste forma polone: invers a unei
expresii, expresia rezultat n urma parcurgerii SDR a arborelui de structur.
Exemplu
3.2.8. Pentru expresia considerat la exemplul 3.2.7., Iorma polonez direct este *ab-
cd/eg. Forma polonez invers a expresiei date este abcd-*eg/+.
Observaie Parcurgerea arborelui n inordine determin secvena de simboluri rezultat
prin eliminarea parantezelor din expresia dat. Restaurarea unei Iorme parantezate poate Ii
realizat printr-o parcurgere SRD si anume n modul urmtor. La momentul iniial vrful curent
este rdcina arborelui de structur. Dac vrful curent v nu este vrf terminal, atunci se genereaz
(s1) eticheta(v)(s2), unde eticheta(v) este operatorul etichet a vrIului, s1 este secvena rezultat
prin traversarea SRD a subarborelui stng, s2 este secvena rezultat prin traversarea SRD a
subarborelui drept. Dac v este vrI terminal atunci este generat secvena eticheta(v).
Evaluarea expresiilor aritmetice pe baza arborilor de structur
Traversarea SRD a arborelui de structur atasat unei expresii aritmetice permite evaluarea
expresiei pentru valorile curente corespunztoare variabilelor. Evaluarea poate Ii eIectuat n mod
recursiv astIel. La momentul iniial vrful curent este rdcina arborelui. Dac v este vrf curent
atunci noua inIormaie asociat lui v este:
- val(eticheta(v)), dac v este vrf terminal;
- val(s1)eticheta(v)val(s2), dac v este neterminal, unde val(s1), val(s2) snt valorile
rezultate prin evalurile subarborilor stng si respectiv drept ai lui v, val(eticheta(v))
este valoarea curent a variabilei, dac eticheta lui v este variabil, respectiv valoarea
constantei, dac eticheta lui v este o constant.
Exemplu 3.2.9. Prin aplicarea metodei de evaluare descrise pentru a=3, b=2, c=5, d=2,
e6 si g2, obinem:
69
3
5 3 2
5 2
6
2 3
18
15
Construcia arborelui de structur asociat unei expresii si evaluarea expresiei pentru
valori date ale operanzilor pot Ii implementate prin intermediul urmtoarei surse C.
#i ncl ude<st di o. h>
#i ncl ude<coni o. h>
#i ncl ude<al l oc. h>
#i ncl ude<val ues. h>
#i ncl ude<st r i ng. h>
#i ncl ude<mat h. h>
t ypedef st r uct nod{
char i nf ;
f l oat v;
st r uct nod *l , *r ;
} ar b, *ar bor e;
voi d pr i or i t at i ( char *s, i nt *pr i or i t at e)
{
i nt i , j , di m;
/ / st abi l i r ea pr i or i t at i l or
f or ( i =j =di m=0; i <st r l en( s) ; i ++)
swi t ch( s[ i ] ) {
case ' ) ' : j - =10; br eak;
case ' ( ' : j +=10; br eak;
case ' +' : {pr i or i t at e[ di m] =j +1; di m++; br eak; }
case ' - ' : {pr i or i t at e[ di m] =j +1; di m++; br eak; }
case ' *' : {pr i or i t at e[ di m] =j +10; di m++; br eak; }
case ' / ' : {pr i or i t at e[ di m] =j +10; di m++; br eak; }
def aul t : {pr i or i t at e[ di m] =MAXI NT; di m++; br eak; }
}
/ / el i mi nar ea par ant ezel or
f or ( i =0; i <st r l en( s) ; )
i f ( ( s[ i ] ==' ) ' ) | | ( s[ i ] ==' ( ' ) ) {
f or ( j =i +1; j <st r l en( s) ; j ++) s[ j - 1] =s[ j ] ;
s[ st r l en( s) - 1] =' \ 0' ; }
el se i ++;
}
voi d cr _ar b_st r ( ar bor e *r ad, unsi gned p, unsi gned u, char *s, i nt *pr i )
{
i nt mi n=pr i [ p] ;
i nt poz=p;
f or ( i nt i =p+1; i <=u; i ++)
i f ( mi n>pr i [ i ] ) {mi n=pr i [ i ] ; poz=i ; }
( *r ad) =( ar bor e) mal l oc( si zeof ( ar b) ) ;
( *r ad) - >i nf =s[ poz] ;
i f ( p==u)
( *r ad) - >l =( *r ad) - >r =NULL;
el se{
70
cr _ar b_st r ( &( ( *r ad) - >l ) , p, poz- 1, s, pr i ) ;
cr _ar b_st r ( &( ( *r ad) - >r ) , poz+1, u, s, pr i ) ;
}
}
voi d f or ma_pol oneza( ar bor e r ad)
{
i f ( r ad) {
pr i nt f ( " %c" , r ad- >i nf ) ;
f or ma_pol oneza( r ad- >l ) ;
f or ma_pol oneza( r ad- >r ) ;
}
}
f l oat eval ( ar bor e r ad)
{
char s[ 1] ;
i f ( r ad) {
i f ( ( r ad- >r ==r ad- >l ) &&( r ad- >l ==NULL) ) r et ur n r ad- >v;
el se{
swi t ch ( r ad- >i nf ) {
case ' +' : r ad- >v=eval ( r ad- >l ) +eval ( r ad- >r ) ; br eak;
case ' - ' : r ad- >v=eval ( r ad- >l ) - eval ( r ad- >r ) ; br eak;
case ' *' : r ad- >v=eval ( r ad- >l ) *eval ( r ad- >r ) ; br eak;
case ' / ' : r ad- >v=eval ( r ad- >l ) / eval ( r ad- >r ) ; br eak;
}
r et ur n r ad- >v;
}
}
}
voi d at r i bui e_ar bor e( ar bor e r ad)
{
i f ( r ad) {
i f ( ( r ad- >r ==r ad- >l ) &&( r ad- >l ==NULL) ) {
pr i nt f ( " %c =" , r ad- >i nf ) ;
f l oat t ;
scanf ( " %f " , &t ) ;
r ad- >v=t ;
}
el se
{at r i bui e_ar bor e( r ad- >l ) ;
at r i bui e_ar bor e( r ad- >r ) ;
}
}
}
voi d mai n( )
{
cl r scr ( ) ;
char s[ 100] ;
i nt p[ 100] ;
ar bor e r adaci na=NULL;
pr i nt f ( " Expr esi a: " ) ;
scanf ( " %s" , &s) ;
pr i or i t at i ( s, p) ;
i nt n=st r l en( s) ;
cr _ar b_st r ( &r adaci na, 0, n- 1, s, p) ;
pr i nt f ( " \ nFor ma pol oneza i nver sa " ) ;
f or ma_pol oneza( r adaci na) ;
pr i nt f ( " \ n Val or i pent r u var abi l e\ n" ) ;
at r i bui e_ar bor e( r adaci na) ;
pr i nt f ( " \ nEval uar ea: %7. 3f " , eval ( r adaci na) ) ;
get ch( ) ;
}
71
4. Elemente de
programare orientat obiect
Programarea orientat obiect (Object Oriented Programming - OOP) reprezint o tehnic
ce s-a impus n anii 90, dovedindu-se beneIic pentru realizarea sistemelor software de mare
complexitate. Noiunea de obiect dateaz din anii `60, odat cu apariia limbajului Simula. Exist
limbaje ca Smalltalk si EiIIel care corespund natural cerinelor programrii orientate obiect,
fiind concepute n acest spirit. Recent au Iost dezvoltate si alte limbaje orientate obiect, fie pentru
programare general, fie pentru realizarea de scripturi J ava, Delphi, C++, Visual Basic .NET,
C#, Python, Ruby. Unele dintre ele oIer n continuare si posibilitatea programri procedurale
(Delphi, C). Toate limbajele Iolosite n prezent oIer si Iaciliti de programare orientat obiect
ADA, Fortran, Cobol, PHP etc. n prezent exist n Iunciune sisteme soItware de mare
anvergur realizate n tehnica programrii orientat obiect, principiile ei fiind suficient de bine
clarificate, astfel nct s se treac din domeniul cercetrii n cel al produciei curente de
programe.
Acest capitol prezint o introducere n lucrul orientat obiect n limbajul C, Ir a
acoperi toat problematica speciIic.
4.1. Modelul de date orientat obiect
OOP reprezint o abordare cu totul diIerit Ia de programarea procedural, devenit
deja clasic. Dac n programarea clasic programatorul era preocupat s rspund la ntrebarea
ce trebuie Icut cu datele?, adic s deIineasc proceduri care s transIorme datele n rezultate,
n OOP accentul cade asupra datelor si legturilor ntre acestea, ca elemente prin care se
modeleaz obiectele lumii reale. Se poate afirma, ntr-o prim analiz, c OOP organizeaz un
program ca o colecie de obiecte, modelate prin date si legturi speciIice, care interacioneaz
dinamic, adic maniIest un anumit comportament, producnd rezultatul scontat. n general,
pentru modelul de date orientat pe obiect, se consider deIinitorii urmtoarele concepte:
abstractizare, obiect, atribut, metod, clas, spaiu propriu, spaiu extins, ncapsulare, mostenire si
polimorfism.
72
Abstractizarea constituie procesul de simpliIicare a realitii prin reinerea
caracteristicilor si comportamentelor eseniale si constituirea lor ntr-un model adecvat rezolvrii
problemelor.
Obiectul este un model inIormaional al unei entiti reale, care posed, la un anumit
nivel, o mulime de proprieti si care are, n timp, un anumit comportament, adic maniIest
reacii speciIice n relaiile cu alte entiti din mediul su de existen. Ca model, un obiect este o
unitate individualizabil prin nume, care conine o mulime de date si Iuncii. Datele descriu
proprietile si nivelul acestora, iar Iunciile definesc comportamentul.
Avnd n vedere proprietile comune si comportamentul similar al entitilor pe care le
modeleaz, obiectele pot Ii clasiIicate n mulimi. O mulime de obiecte de acelasi Iel constituie o
clas de obiecte, descris prin modelul comun al obiectelor sale.
De exemplu, n figura 4.1, numerele complexe, ca perechi de numere reale de forma
(parte real, parte imaginar) pot Ii descrise printr-un model comun, denumit ClasaComplex.
Modelul arat c orice obiect de acest Iel se caracterizeaz printr-o pereche de numere ntregi si
c pe aceast mulime snt definite operaii unare si binare care arat cum ,interacioneaz
obiectele n interiorul mulimii: un numr complex poate da nastere modulului si opusului su,
dou numere complexe pot produce un alt numr complex ca sum, produs etc.
Generaliznd, se poate aIirma c o clas de obiecte se maniIest ca un tip obiect, iar
modelul comun al obiectelor este modelul de definire a tipului obiect. Astfel, obiectele
individuale apar ca maniIestri, realizri sau instanieri ale clasei, adic exemplare particulare
generate dup modelul dat de tipul obiect. AltIel spus, o clas poate Ii considerat ca un tip
special de dat, iar obiectele sale ca date de acest tip.
Fig.4.1. Clas si obiecte mulimea numerelor complexe
Acceptarea acestei semniIicaii pentru clase de obiecte este de natur s simpliIice
descrierea obiectelor si s asigure un tratament al acestora similar tipurilor structurate de date din
limbajele de programare: este suIicient o descriere a tipului obiect si apoi se pot declara
constante si variabile de acest tip. Datele care reprezint proprietile obiectelor se numesc
atribute si snt de un anumit tip (de exemplu ntregi, reale, caractere etc.). Setul de valori ale
atributelor unui obiect la un moment dat Iormeaz starea curent a obiectului respectiv.
Funciile care deIinesc comportamentul obiectelor snt cunoscute ca metode ale clasei. mpreun,
atributele si metodele snt membrii clasei, identiIicabili prin nume. Pentru a pune n eviden
Iaptul c un membru aparine unui obiect se utilizeaz caliIicarea, astfel:
nume_obiect.nume_membru. n figura 4.1, a.P_real reIer valoarea 1.0, iar a.Modul reIer
metoda Modul a obiectului a pentru a produce obiectul rezultat.
Asa cum sugereaz Iigura 4.1, Iiecare obiect trebuie s conin valorile atributelor sale,
deoarece ele deIinesc starea obiectului respectiv. Spaiul de memorie ocupat de atributele unui
obiect se numeste spaiu propriu al obiectului. n multe cazuri, ntre atribute se aIl pointeri care
indic anumite zone de memorie alocate dinamic pentru obiect (de exemplu clasa list are ca
membru atributul cap care conine adresa primului nod al unei liste dinamice simplu nlnuite).
73
Acest spaiu alocat dinamic aparine tot obiectului, dar el se numeste spaiu extins al obiectului.
Gestiunea acestui spaiu extins trebuie asigurat de metodele clasei.
Metodele, care descriu aciuni identice pentru toate obiectele clasei, snt memorate o
singur dat, ntr-o zon comun tuturor obiectelor clasei. ntruct metodele descriu
comportamentele obiectelor, ele nu pot Ii apelate independent, ci numai n legtur cu un anumit
obiect. Despre o metod apelat pentru un anumit obiect se spune c se execut n contextul
obiectului respectiv, iar acesta este numit obiect curent. Apelarea metodei este considerat ca
trimitere de mesaj ctre obiectul curent, iar execuia metodei reprezint rspunsul (reacia)
obiectului curent la mesajul primit.
Faptul c o metod se execut n contextul obiectului curent nseamn c are, n mod
implicit, acces la toate atributele si metodele obiectului. Acestea nu trebuie s apar ca parametri
ai metodei. Pentru a utiliza alte obiecte, din aceeasi clas sau din clase diIerite, metoda trebuie s
aib parametri corespunztori. De asemenea, pentru a simpliIica scrierea, n interiorul unei
metode referirea la membrii obiectului curent se Iace Ir caliIicare.
Pe baza acestor convenii, n Iunciile Conjugat, Suma si Modul, scrise n pseudocod, s-a
speciIicat cu un parametru mai puin dect numrul de operanzi pe care i presupune operaia
respectiv, deoarece un operand este obiectul curent. ReIerirea la atributele obiectului curent se
distinge de celelalte prin lipsa calificrii. Descrierea n pseudocod a metodelor Conjugat, Suma si
Modul din clasa CComplex (figura 4.1) poate Ii Icut astIel:
voi d Conj ugat ( b) ;
begi n b. p_r eal a: =p_r eal a;
b. p_i magi nar a: =- p_i magi nar a;
end;
voi d Suma( b, c) ;
begi n
c. p_r eal a: =p_r eal a+b. p_r eal a;
c. p_i magi nar a: =- p_i magi nar a+b. p_i magi nar a;
end;
f l oat Modul ( ) ;
begi n
Modul =sqr t ( p_r eal a*p_r eal a+p_i magi nar a*p_i magi nar a) ;
end;
Deoarece o clas este un tip de dat, n deIinirea unei clase B se pot declara atribute de
tip A, unde A este la rndul ei o clas. Mai mult, o clas A poate defini atribute de tip A. De
exemplu clasa Carte, din figura 4.2 are atributul Autor de tipul Persoana care este, de asemenea,
o clas. Mai mult, Persoana are atributul Sef care este de acelasi tip (Persoana).
74
Fig.4.2. Atribute de tip clas
DeIinirea atributelor unei clase ca tipuri ale altei clase pune n eviden o relaie ntre
clase si deci ntre obiectele acestora.
Din punct de vedere Iuncional, metodele unei clase au destinaii diverse. n multe cazuri
si depinznd de limbaj, unei clase i se poate deIini o metod (sau mai multe) constructor si o
metod destructor. Un constructor este o metod care creeaz un obiect, n sensul c i aloc
spaiu si/sau iniializeaz atributele acestuia. Destructorul este o metod care ncheie ciclul de
via al unui obiect, elibernd spaiul pe care acesta l-a ocupat.
ncapsularea exprim proprietatea de opacitate a obiectelor cu privire la structura lor
intern si la modul de implementare a metodelor. Ea este legat de securitatea programrii,
furniznd un mecanism care asigur accesul controlat la starea si Iuncionalitatea obiectelor. Se
evit astIel modiIicri ale atributelor obiectelor si transIormri ale acestora care pot s le
deterioreze. Potrivit acestui mecanism, o clas trebuie s aib membrii mprii n dou
seciuni: partea public si partea privat.
Partea public este constituit din membri (atribute si metode) pe care obiectele le oIer
spre utilizare altor obiecte. Ea este interIaa obiectelor clasei respective cu lumea exterioar si
depinde de proiectantul clasei. Modalitatea extrem de constituire a interIeei este aceea a unei
interIee compus numai din metode. Dac se doreste ca utilizatorii obiectelor clasei s poat
prelua si/sau stabili valorile unor atribute ale acestora, interIaa trebuie s prevad metode
speciale, numite accesorii, care au ca unic rol accesul la atribute.
Partea privat cuprinde membri (atribute si/sau metode) care servesc exclusiv obiectelor
clasei respective. De regul, n aceast parte se includ atribute si metode care Iaciliteaz
implementarea interIeei si a Iuncionalitii interne a obiectului.
De exemplu, o stiv, ca tip de dat poate Ii descris de o clas Stiva n care interIaa este
constituit din metodele Push, Pop, Top, Empty, n timp ce pointerul la capul stivei, Cap si
numrtorul de noduri, Contor, ca atribute, snt ,ascunse n partea privat. Ea se serveste de
obiectele altei clase, denumit Nod, ale crei obiecte le nlnuieste n stiv (Iigura 4.3)
75
Fig.4.3. InterIaa obiectelor
Trebuie remarcat c ncapsularea nseamn si Iaptul c utilizatorul metodelor nu trebuie
s cunoasc codul metodelor si nici nu trebuie s Iie dependent de eventuala schimbare a acestuia,
interIaa Iiind aceea care i oIer Iuncionalitatea obiectelor n condiii neschimbate de apelare.
Moytenirea reprezint o relaie ntre clase si este, probabil, elementul deIinitoriu al
OOP. Relaia permite constituirea unei noi clase, numit derivat (sau fiu) pornind de la clase
existente, denumite de ba: (sau printe). Dac n procesul de construire particip o singur clas
de baz, mostenirea este simpl, altIel este multipl.
Se spune c o clas D mosteneste o clas A, dac obiectele din clasa D conin toate
atributele clasei A si au acces la toate metodele acestei clase. Din aceast deIiniie, dac D
mosteneste A, atunci obiectele din D vor avea toate atributele si acces la toate metodele lui A, dar
n plus:
- D poate defini noi atribute si metode;
- D poate redeIini metode ale clasei de baz;
- metodele noi si cele redeIinite au acces la toate atributele dobndite sau nou definite.
n figura 4.4, clasa Cerc mosteneste clasa Punct, deci un obiect de tipul Cerc va avea ca
membri coordonatele x,y mostenite si ca atribut propriu Raza. Funcia Distana, deIinit pentru
calculul distanei dintre punctul curent si punctul p, dat ca parametru, este accesibil si pentru
obiectele Cerc si va calcula distana dintre centrul cercului si un alt punct, primit ca parametru.
Funcia Arie calculeaz aria din interiorul cercului, Iiind nou deIinit. Funcia Desenea: este
redeclarat de clasa Cerc, lucru impus de codul diIerit pe care trebuie s-l aib pentru desenarea
obiectelor din aceast clas (cerc sau alt Iigur).
Fig.4.4. Mostenirea simpl.
76
Dac se au n vedere mulimi de clase, atunci se observ c relaia de mostenire simpl
induce un arbore ierarhic de mostenire pe aceast mulime. Exist o singur clas iniial,
rdcina arborelui, Iiecare clas are un singur ascendent (printe) si orice clas care nu este Irunz
poate avea unul sau mai muli descendeni (Iii). n Iine, cu privire la mostenirea simpl se pot
Iace urmtoarele observaii: dac se aduc modiIicri n clasa de baz, prin adugarea de atribute
si/sau metode, nu este necesar s se modiIice si clasa derivat; mostenirea permite specializarea
si mbogirea claselor, ceea ce nseamn c, prin redeIinire si adugare de noi membri, clasa
derivat are, n parte, Iuncionalitatea clasei de baz, la care se adaug elemente Iuncionale noi;
mostenirea este mecanismul prin care se asigur reutilizarea codului sporind productivitatea
muncii de programare.
Cobornd (de obicei, n reprezentrile graIice ale arborilor de clase, rdcina se aIl n
partea superioar) n arborele ierarhic al claselor de la rdcin ctre Irunze, se poate spune c
ntlnim clase din ce n ce mai specializate. Prin mostenire se realizeaz o specializare a claselor.
n sens invers, de la Irunz ctre rdcin, clasele snt din ce n ce mai generale, avem o relaie de
generalizare. Clasa aIlat la baza ierarhiei este cea mai general.
Limbajele de programare orientate obiect au implementate ierarhii standard extinse de
clase, care corespund necesitilor generale ale programrii. Utilizatorii pot deriva clase noi din
cele standard.
Polimorfismul este un concept mai vechi al programrii, cu diIerite implementri n
limbajele de programare care se bazeaz pe tipuri de date (limbaje cu tip). El si-a gsit extensia
natural si n modelul orientat pe date, implementat prin limbaje cu tip, n care clasa reprezint
tipul de date obiect.
Polimorfismul n limbajele de programare cu tip. Noiunea de polimorIism exprim
capacitatea unui limbaj de programare cu tip de a exprima comportamentul unei proceduri
independent de natura (tipul) parametrilor si. De exemplu, o Iuncie care determin cea mai mare
valoare dintr-un sir de valori este polimorIic dac poate Ii scris independent de tipul acestor
valori. n Iuncie de modul de implementare, se disting mai multe tipuri de polimorIism.
Polimorfismul ad-hoc se materializeaz sub Iorma unor Iuncii care au toate acelasi
nume, dar se disting prin numrul si/sau tipul parametrilor. Acest polimorIism este denumit si
supraincrcare, avnd n vedere semantica speciIic Iiecrei Iuncii n parte.
Polimorfismul de incluziune se bazeaz pe o relaie de ordine parial ntre tipurile de
date, denumit relaie de incluziune sau inIerioritate. Dac un tip A este inclus (inferior) ntr-un
tip B, atunci se poate trimite un parametru de tip A unei Iuncii care asteapt un parametru de tip
B. AstIel, un singur subprogram deIineste Iuncional o Iamilie de Iuncii pentru toate tipurile
inferioare celor declarate ca parametri. Un exemplu clasic este cazul tipului int, inferior tipului
float n toate operaiile de calcul.
Polimorfism parametric const n deIinirea unui model de procedur pentru care chiar
tipurile snt parametri. Acest polimorfism, denumit si genericitate, presupune c procedura se
genereaz pentru Iiecare tip transmis la apel ca parametru.
Cele trei tipuri de polimorIism exist (toate sau numai o parte din ele) n limbajele clasice
de programare, dar unele pot s nu Iie accesibile programatorului.
Polimorfismul n limbajele orientate obiect. Limbajele orientate obiect sau extensiile
obiect ale unor limbaje cu tip oIer, n mod natural, polimorIismul ad-hoc si de incluziune.
Polimorfismul ad-hoc intrinsec reprezint posibilitatea de a deIini n dou clase independente
metode cu acelasi nume, cu parametri identici sau diIerii. Acest polimorIism nu necesit
mecanisme speciale si decurge simplu, din Iaptul c Iiecare obiect este responsabil de tratarea
mesajelor pe care le primeste. PolimorIismul este de aceeasi natur si n cazul n care ntre clase
exist o relaie de mostenire, cu precizarea c, n cazul n care o metod din clasa derivat are
77
parametrii identici cu ai metodei cu acelasi nume din clasa de baz, nu mai este suprancrcare, ci
redeIinire, dup cum s-a precizat mai sus.
Polimorfimsul de incluziune este legat de relaia de mostenire si de aceea se numeste
polimorfism de motenire. ntr-adevr, relaia de mostenire este o relaie de ordine parial, astIel
nct dac clasa D mosteneste direct sau indirect clasa A, atunci D este inferior lui A. n aceste
condiii, orice metod a lui A este aplicabil la obiectele de clas D si orice metod, indiIerent de
context, care are definit un parametru de tip A (printe) poate primi ca argument corespunztor
(parametru actual) un obiect de clas D (fiu).
Observaie: un obiect de clas A nu poate lua locul unui obiect de clas D, deoarece A
'acoper numai parial pe D, care este o extensie si o specializare a lui A.
Legare static i dinamic a metodelor. Legarea static a metodelor se regseste att n
limbajele orientate obiect ct si n cele clasice. Compilatorul poate determina care metod si din
care clas este eIectiv apelat ntr-un anumit context si poate genera codul de apel corespunztor.
Fie o clas A si o clas D, unde D este derivat din A. Fie o metod din clasa A, numit
calculea:, care este redeIinit n clasa derivat, D. Atunci cnd metoda este apelat n contextul
unui obiect static, compilatorul poate determina tipul acelui obiect (ca fiind parte a clasei A sau
D). AstIel, el va sti ce metod s apeleze (a clasei de baz sau cea redeIinit, a clasei derivate). n
acest caz are loc o legare static a metodelor (decizia este luat n momentul compilrii).
Fie un pointer p, definit ca pointer spre clasa A. Datorit polimorIismului, n limbajele
orientate obiect unui obiect din clasa printe, desemnat indirect prin reIerin (pointer) si nu prin
nume, i se poate atribui un obiect fiu. n acest context, p poate primi ca valoare, n timpul
execuiei programului, adresa unui obiect din clasa A sau din clasa D. Nu se poate sti la
momentul compilrii ce se va ntmpla n timpul execuiei programului, ca urmare nu se poate
determina dac, n contextul dat, trebuie apelat metoda clasei de baz sau metoda clasei derivate.
De aceea, n locul din program n care este apelat metoda, compilatorul adaug o secven de
cod care, la momentul execuiei, va veriIica tipul eIectiv al obiectului si, dup caz, va realiza
apelarea metodei adecvate. n acest caz are loc legarea dinamic a metodelor (sau la momentul
execuiei). Legarea dinamic este evident mai costisitoare dect cea static, dar reprezint o
necesitate pentru a asigura elasticitatea necesar n realizarea programelor OOP, obiectele putnd
avea caracter de variabile dinamice.
4.2. Definirea claselor
DeIiniia unei clase este asemntoare cu deIiniia unui articol, ns n locul cuvntului
rezervat struct se Ioloseste cuvntul class:
cl ass nume { descr i er e membr i ; };
Membrii unei clase pot Ii atribute sau metode. Atributele snt descrise asemntor
declaraiilor de variabile independente (si asemntor cmpurilor unui articol struct), specificnd
tipul si numele atributului respectiv. Membrii unei clase pot Ii de orice tip, mai puin de acelasi
tip cu clasa descris (dar pot Ii pointeri ctre clasa descris).
Metodele snt descrise asemntor Iunciilor independente. Ele pot Ii descrise integral n
interiorul clasei (descriind antetul si corpul lor) sau speciIicnd n interiorul clasei doar prototipul
Iunciei, corpul urmnd s Iie descris ulterior, n aIara clasei. Este preIerat a doua variant,
deoarece descrierea clasei este mai compact dect n primul caz. Atunci cnd se descrie ulterior
corpul unei metode, pentru a speciIica apartenena sa la clasa respectiv, numele metodei este
prefixat cu numele clasei din care face parte, folosind operatorul de re:oluie (::), astfel:
tip_rezultat nume_clas::nume_metod(lista parametrilor)
corp metod
78
Mai mult, Iunciile care snt integral descrise n interiorul clasei snt considerate Iuncii
inline
1
, de aceea ele trebuie s Iie simple. Pentru Iunciile mai complexe, ntotdeauna se
recomand s Iie descrise Iolosind a doua variant.
ntruct o clas este un tip de dat, declararea unui obiect se Iace asemntor oricrei
declaraii de dat:
nume_clas nume_obiect;
Atunci cnd se doreste lucrul cu obiecte dinamice, se poate declara o variabil de tip pointer ctre
clas: nume_clas* p_obiect;
Declararea unui obiect mai este numit si instanierea clasei, n sensul c se creeaz o
instan a acelei clase, o entitate concret din mulimea descris de clasa respectiv..
Exemplu
Definirea clasei Complex, care implementeaz entitatea matematic numr complex. Clasa are
atributele p_reala si p_imaginara si o metod pentru aIisarea valorii obiectului afiseaza.
cl ass Compl ex { f l oat p_r eal a, p_i magi nar a;
voi d Af i seaza( ) ;
};
voi d Compl ex: : Af i seaza( )
{ pr i nt f ( " \ n%5. 2f %ci *%5. 2f \ n" , p_r eal a, p_i magi nar a>=0?' +' : ' - ' ,
p_i magi nar a>=0?p_i magi nar a: - p_i magi nar a) ;
}
Compl ex t c;
Metoda afiea: ine cont de semnul prii imaginare. Dac aceasta este negativ, semnul minus
este aIisat naintea simbolului i al prii imaginare. Se declar obiectul tc de tipul Complex.
Accesul la membrii obiectului se face folosind operatorul de calificare:
nume_obi ect . nume_membr u
unde numele obiectului speciIic din ce obiect este accesat atributul respectiv sau n contextul
crui obiect se execut metoda respectiv. Acest mod de accesare este Iolosit atunci cnd se
lucreaz cu obiecte statice. n cazul n care nu avem un obiect ci un pointer ctre un obiect, este
necesar si dereIerenierea pointerului, nainte de accesul la membri. Acest lucru este realizat
folosind operatorul -> n locul operatorului de calificare:
p_obi ect - > nume_membr u
Pentru implementarea conceptului de ncapsulare, n interiorul unei definiii de clas pot
Ii Iolosii modificatori de acces. Acestia snt private, protected si public (urmai de caracterul :
,dou puncte). Domeniul de aciune al unul modiIicator de acces ncepe n locul unde apare el si
1
Apelul Iunciilor inline nu produce un salt n segmentul de cod ctre codul executabil al Iunciei, asa cum
se ntmpl n cazul Iunciilor obisnuite. Pentru aceste Iuncii, compilatorul insereaz n program, n locul
apelului, secvena de cod corespunztoare corpului Iunciei, nlocuind parametrii formali cu valorile
actuale. Funciile inline au un comportament asemntor macrodeIiniiilor.
79
se ncheie la apariia altui modiIicator sau la terminarea descrierii clasei. Implicit, toi membri snt
considerai sub inIluena modiIicatorului private, deci orice membru aflat n afara domeniului de
aciune al unui modiIicator este considerat privat. ModiIicatorul public Iace ca toi membri aIlai
n domeniul su de aciune s poat Ii accesai att de ctre metodele clasei ct si de ctre orice
entitate din afara clasei (membri publici). Modificatorul private Iace ca membrii aIlai n
domeniul su de aciune s poat Ii accesai numai de ctre metodele clasei respective (membri
privai). ModiIicatorul protected este similar cu modificatorul private, dar membrii respectivi pot
Ii accesai si de ctre metodele claselor derivate, dar numai n obiecte aparinnd claselor derivate.
De obicei atributele unei clase snt declarate ca Iiind private iar metodele snt mprite,
unele Iiind publice (interIaa clasei) si unele private (detalii si mecanisme interne de
implementare a clasei. Desi este tehnic posibil ca toi membrii unei clase s Iie privai, un obiect
de acest tip nu poate fi folosit, neavnd o interfa cu mediul exterior lui. De asemenea, toi
membrii unei clase pot Ii publici, dar nu este recomandat aceast tehnic din motive de protecie
si securitate.
Exemplu
n acest context, clasa Complex deIinit n exemplul anterior nu poate Ii Iolosit, toi membrii ei
Iiind privai. Pentru a putea Iolosi obiecte de tipul Complex, metoda afiea: trebuie s Iie
public. Descrierea clasei devine:
cl ass Compl ex { f l oat p_r eal a, p_i magi nar a;
publ i c:
voi d Af i seaza( ) ;
};
voi d Compl ex: : Af i seaza( )
{ pr i nt f ( " \ n%5. 2f %ci *%5. 2f \ n" , p_r eal a, p_i magi nar a>=0?' +' : ' - ' ,
p_i magi nar a>=0?p_i magi nar a: - p_i magi nar a) ;
}
Prin adugarea modiIicatorului de acces public, metoda afiea: este pus la dispoziia mediului
extern, ca interIa a obiectului.
Pentru accesul controlat la atributele private, clasele pot pune la dispoziia mediului
extern metode publice de acces, numite uzual metode accesorii. Acestea au rolul de a prezenta
mediului extern valorile unora dintre atribute (acelea care pot prezenta interes) sau de a modifica
valorile unora dintre atribute, n mod controlat (numai acele atribute pentru care modificarea la
iniiativa mediului extern are sens). Controlul depinde n Iiecare caz de scopul clasei respective.
Exemplu
Adugnd metode accesorii clasei Complex, descrierea acesteia devine:
cl ass Compl ex { f l oat p_r eal a, p_i magi nar a;
publ i c:
voi d Af i seaza( ) ;
f l oat Get R( ) ;
f l oat Get I ( ) ;
voi d Set R( f l oat r ) ;
voi d Set I ( f l oat i ) ;
};
voi d Compl ex: : Af i seaza( )
{ pr i nt f ( " \ n%5. 2f %ci *%5. 2f \ n" , p_r eal a, p_i magi nar a>=0?' +' : ' - ' ,
p_i magi nar a>=0?p_i magi nar a: - p_i magi nar a) ;
}
80
f l oat Compl ex: : Get R( )
{ r et ur n p_r eal a;
}
f l oat Compl ex: : Get I ( )
{ r et ur n p_i magi nar a;
}
voi d Compl ex: : Set R( f l oat r )
{ p_r eal a=r ;
}
voi d Compl ex: : Set I ( f l oat i )
{ p_i magi nar a=i ;
}
Metodele accesorii definite mai sus (GetR, GetI, SetR, SetI) au rolul de a prezenta valorile
atributelor si respectiv de a stabili noi valori pentru ele. n acest exemplu nu se Iace nici un Iel de
control asupra modului n care snt stabilite noile valori.
Folosind descrierile de mai sus, urmtoarea secven de program:
voi d mai n( )
{ Compl ex t c;
Compl ex *pc;
t c. Set R( 5) ;
t c. Set I ( - 4) ;
t c. Af i seaza( ) ;
pc=&t c;
pc- >Af i seaza( ) ;
pc- >Set R( - 2) ;
pc- >Set I ( 3) ;
pc- >Af i seaza( ) ;
}
produce pe ecran urmtorul rezultat:
5. 00- i * 4. 00
5. 00- i * 4. 00
- 2. 00+i * 3. 00
Pentru a evita eventualele confuzii, n interiorul corpului metodelor poate fi folosit
pointerul implicit this atunci cnd se reIer membrii obiectului curent. Acesta este gestionat
automat si are ca valoare adresa obiectului curent. Ca urmare, metoda SetR ar putea Ii rescris
astfel:
voi d Compl ex: : Set R( f l oat r )
{ t hi s - > p_r eal a = r ;
}
Pointerul this poate Ii Iolosit si pentru accesarea metodelor obiectului curent, n acelasi mod.
innd cont de domeniul de valabilitate al declaraiilor de tipuri de date, descrierea unei
clase se Iace de obicei la nceputul Iisierului surs n care urmeaz a Ii Iolosit. Pentru o mai mare
generalitate si reutilizare mai usoar, se preIer ca Iiecare clas nou s Iie descris ntr-un Iisier
surs separat, care s Iie inclus Iolosind directiva #include n programe.
81
4.3. Constructori
Declararea obiectelor are ca eIect alocarea de spaiu n memorie, la Iel ca n cazul
declarrii oricrei variabile. Acest spaiu nu este iniializat ns. Mai mult, n cazul n care
obiectele clasei au si spaiu extins de memorie, acesta nu este alocat automat, obiectul declarat
Iiind astIel incomplet. Atributele unui obiect nu pot Ii iniializate la declarare ntr-o manier
asemntoare datelor de tip articol (struct), deoarece de obicei atributele snt private, deci
inaccesibile din exteriorul obiectului. Pentru rezolvarea problemei iniializrii obiectelor exist
posibilitatea utilizrii unor metode speciale, numite constructori. La terminarea ciclului de via
al obiectelor, este necesar dezalocarea lor. n general aceasta se realizeaz automat, dar n cazul
lucrului cu spaiu extins, ea trebuie gestionat n mod explicit. Problema ncheierii ciclului de
via al obiectelor este rezolvat prin utilizarea unor metode speciale numite destructori.
Constructorii si destructorii nu ntorc nici un rezultat prin numele lor si antetele lor nu precizeaz
nici un tip pentru rezultat (nici mcar void).
Constructorii snt metode care au acelasi nume cu clasa creia i aparin. O clas poate
avea mai muli constructori, cu liste diIerite de parametri (ca tip si/sau numr) metode
suprancrcate. Dac nu este deIinit nici un constructor pentru o clas, compilatorul va genera un
constructor implicit, care nu Iace dect alocarea spaiului propriu al obiectului, n momentul n
care acesta a fost declarat. Ca urmare, n acest caz vom avea obiecte neiniializate, urmnd ca
iniializarea atributelor s se Iac ulterior, prin intermediul metodelor accesorii. n exemplul
anterior, pentru clasa Complex s-a generat un constructor implicit care aloc spaiu pentru
atributele p_reala si p_imaginara. Iniializarea s-a Icut prin intermediul metodelor SetR si SetI.
n cazul n care clasa prezint cel puin un constructor explicit, compilatorul nu mai genereaz
constructorul implicit. Ca urmare nu se vor putea declara obiecte neiniializate dac parametrii
constructorului nu au valori implicite.
Constructorii nu pot Ii apelai explicit, precum metodele obisnuite. Apelul lor se
realizeaz numai la declararea obiectelor. De asemenea, nu se poate determina adresa
constructorilor, asa cum se poate Iace n cazul Iunciilor obisnuite. Am vzut mai sus c
declaraia unui obiect care nu are constructor explicit este identic cu declaraia unei variabile
simple. n cazul n care clasa prezint constructori explicii valorile pentru iniializare snt
transmise acestuia la declararea obiectului, asemntor listei de parametri reali la apelul unei
Iuncii:
nume_clas nume_obiect(lista_valori);
Exemplu
Pentru clasa Complex se poate deIini un constructor care s iniializeze cei doi membri astfel:
cl ass Compl ex { f l oat p_r eal a, p_i magi nar a;
publ i c:
Compl ex( f l oat a, f l oat b) ;
};
Compl ex: : Compl ex( f l oat a, f l oat b)
{ p_r eal a=a;
p_i magi nar a=b;
}
Avnd acest constructor n cadrul clasei, nu putem declara obiecte neiniializate (ca n exemplele
anterioare) ci doar obiecte iniializate:
Compl ex a( 3, 4) ; //a reprezint numarul 3+i*4
Compl ex b( - 1, 3. 2) ; //b reprezint numarul - 1+i *3. 2
Compl ex c; / / i ncor ect
Atunci cnd exist un singur constructor explicit, se aplic regulile transIerului
parametrilor similar ca la Iunciile obisnuite (se realizeaz conversia parametrilor reali ctre
82
tipurile Iormale). Dac snt mai muli constructori, cu liste diIerite de parametri, se alege acela a
crui list de parametri corespunde ca tip si numr cu lista valorilor (expresiilor) precizate la
declararea obiectului.
Pentru constructori, ca si pentru orice alt Iuncie, pot Ii precizate valori implicite ale
parametrilor. Acolo unde la apel lipsesc parametrii actuali, se folosesc valorile implicite. Ca
urmare, la declararea obiectelor pot s nu Iie precizate valori pentru toate atributele.
Exemplu
Se deIineste clasa Complex astfel:
class Complex { float p_reala,p_imaginara;
public:
Complex(float a=0,float b=0);
};
Complex::Complex(float a,float b)
{ p_reala=a;
p_imaginara=b;
}
Putem declara urmtoarele obiecte:
Compl ex a; //a reprezint numarul 0+i*0
Compl ex b( - 1) ; / / b reprezint numarul - 1+i *0
Compl ex c( 2, 3) ; //c reprezint numarul 2+i*3
Dac prototipul constructorului ar Ii Iost Compl ex( f l oat a, f l oat b=0) ; atunci la declaraia
obiectului trebuie precizat obligatoriu valoarea pentru primul parametru (cel care va deveni
valoarea atributului p_reala); ca urmare, dintre declaraiile anterioare ar Ii Iost corecte numai cele
ale obiectelor b si c.
Acolo unde se poate folosi un singur parametru la declararea obiectului, se poate face
iniializarea asemntor iniializrii variabilelor simple. Folosind oricare dintre cei doi
constructori din exemplul anterior, putem declara un obiect si n modul urmtor:
Compl ex a = 1; / / numar ul 1+i *0
Valoarea declarat este atribuit primului parametru al constructorului.
Pentru situaiile n care avem nevoie att de obiecte iniializate ct si de obiecte
neiniializate, se adaug n descrierea clasei att un constructor care realizeaz iniializarea
obiectului ct si un constructor vid, care simuleaz constructorul implicit, adugat de compilator
atunci cnd nu se deIinesc constructori implicii. Constructorul vid are urmtoarea Iorm:
Compl ex: : Compl ex( )
{
}
n acest context, declaraia Compl ex a; are ca efect crearea obiectului a neiniializat (se
utilizeaz constructorul vid, nu constructorul cu valori implicite pentru parametri).
83
Parametrii unui constructor pot Ii de orice tip, mai puin de tipul clasei respective (n
exemplele anterioare, constructorul clasei Complex nu poate avea un parametru de tipul Complex.
Este posibil ns s avem un parametru de tip pointer ctre clasa respectiv sau reIerin
2
ctre
clasa respectiv. Un constructor care primeste ca parametru o reIerin ctre un obiect din acea
clas se numeste constructor de copiere. Prin utilizarea unui constructor de copiere se poate
iniializa un obiect nou cu atributele unui obiect existent (se realizeaz o copie a acelui obiect).
Constructorii de copiere pot avea si ali parametri, dar acestia trebuie s aib valori implicite.
Compilatorul genereaz automat un constructor de copiere pentru toate clasele care nu au un
constructor de copiere definit explicit.
Exemplu
Clasa Complex conine un constructor de copiere:
class Complex { float p_reala,p_imaginara;
public:
Complex(float a=0,float b=0);
Complex(Complex &x);
};
Complex::Complex(float a,float b)
{ p_reala=a;
p_imaginara=b;
}
Complex::Complex(Complex &x)
{ p_reala=x.p_reala;
p_imaginara=x.p_imaginara;
}
Putem declara urmtoarele obiecte:
Compl ex a( 3, 4) ; / / numar ul 3+i *4
Compl ex b = a; / / numar ul 3+i *4
Compl ex c( b) ; / / numar ul 3+i *4
Obiectul b este o copie a obiectului a si va avea aceeasi stare, imediat dup declarare (aceleasi
valori ale atributelor). De asemenea, obiectul c este o copie a obiectului b. Pentru ambele obiecte
s-a apelat constructorul de copiere.
Constructorul implicit de copiere realizeaz o copie binar a spaiului propriu de memorie
al obiectului surs. Ca urmare, dac obiectele au spaiu extins de memorie, n urma copierii
ambele obiecte reIer acelasi spaiu extins de memorie. Pentru a evita aceast situaie anormal,
atunci cnd clasele descriu obiecte care lucreaz si cu spaiu extins este necesar Iolosirea unui
constructor de copiere explicit, care s realizeze, pe lng copierea atributelor, alocarea de spaiu
extins propriu pentru obiectul nou si copierea spaiului extins al obiectului surs n acest spaiu
nou.
Constructorii nu pot Ii apelai n mod explicit n program. Singura situaie n care poate s
apar un astIel de apel este la declararea unui obiect, n modul urmtor:
2
n C++este implementat transIerul parametrilor prin adres. Pentru a transmite un parametru prin adres,
n lista de parametri se pune naintea numelui su operatorul de reIereniere &
84
Compl ex a = Compl ex( 2, 5) ;
n cazul n care o clas are ca membri obiecte, la declararea unui obiect al clasei se
apeleaz nti constructorii pentru obiectele membru si apoi constructorul noului obiect.
4.4. Destructori
Destructorii snt metode speciale, asemntoare constructorilor, care au rol invers:
ncheierea ciclului de via al obiectelor. Asa cum pentru Iiecare clas se genereaz un
constructor implicit (dac nu a Iost prevzut unul explicit), compilatorul genereaz si un
destructor implicit, dac nu a Iost prevzut unul explicit. Spre deosebire de constructori, o clas
poate avea numai un destructor explicit. Ca si constructorii, destructorii nu ntorc nici un rezultat.
Numele destructorului este numele clasei precedat de caracterul ~(tilda). Destructorii nu au
parametri.
Exemplu
cl ass Compl ex { f l oat p_r eal a, p_i magi nar a;
publ i c
~Compl ex( ) ;
}
Compl ex: : ~Compl ex( )
{ / / descr i er ea cor pul ui dest r uct or ul ui
}
Pentru clasa Complex destructorul nu are nimic de Icut si nu e necesar descrierea unui
destructor explicit. Acest exemplu urmreste doar s arate cum se declar un destructor explicit.
Spre deosebire de constructori, destructorii pot Ii apelai explicit, atunci cnd este
necesar stergerea unui obiect. Apelul se Iace la Iel ca pentru orice alt metod, n contextul
obiectului care trebuie sters:
a. ~Compl ex( ) ;
Utilizarea destructorilor este obligatorie atunci cnd se lucreaz cu date dinamice,
deoarece destructorii implicii nu pot elibera spaiul alocat dinamic.
n cazul n care la crearea unui obiect au Iost apelai mai muli constructori, la stergerea
lui se apeleaz destructorii corespunztori, n ordine invers.
4.5. Funcii prieten
n unele situaii este nevoie ca Iuncii care nu snt membri ai unei clase s poat accesa
atributele protejate ale clasei. n acest scop a fost introdus conceptul de funcie prieten n C++. O
Iuncie prieten nu Iace parte din clas, dar poate accesa atributele protejate.
Pentru a speciIica o Iuncie prieten, n interiorul descrierii clasei se scrie prototipul
Iunciei prieten, preIixat cu cuvntul rezervat friend. ntruct Iuncia prieten nu este membru al
clasei, n interiorul su nu este deIinit pointerul this, ceea ce Iace ca Iuncia prieten s nu poat
accesa direct atributele obiectului. De aceea este necesar ca obiectul s Iie parametru al Iunciei
prieten. Ca urmare, o Iuncie prieten are un parametru n plus Ia de o metod.
Modificatorii de acces nu au nici o inIluen asupra Iunciilor prieten, de aceea ele pot Ii
specificate oriunde n cadrul descrierii clasei.
85
Exemplu
n acest exemplu Iuncia Afiea: va Ii scoas n aIara clasei Complex si va Ii declarat ca Iuncie
prieten.
cl ass Compl ex { f l oat p_r eal a, p_i magi nar a;
publ i c:
f r i end voi d Af i seaza( Compl ex x) ;
Compl ex( f l oat a=0, f l oat b=0) ;
Compl ex( Compl ex &x) ;
};
voi d Af i seaza( Compl ex x)
{ pr i nt f ( " \ n%5. 2f %ci *%5. 2f \ n" , x. p_r eal a, x. p_i magi nar a>=0?' +' : ' - ' ,
x. p_i magi nar a>=0?x. p_i magi nar a: - x. p_i magi nar a) ;
}
voi d mai n( )
{ Compl ex a( 1, 2) ;
Af i seaza( a) ;
}
Exemplu
S se implementeze clasa Stiv dinamic. O list dinamic este Iormat din noduri, deci putem
defini nti clasa Nod, urmnd a folosi tipul Nod pentru a descrie clasa Stiv. Pentru acest
exemplu, datele memorate n nodurile stivei snt de tip float.
#i ncl ude <st di o. h>
t ypedef f l oat TI P_I NFO;
cl ass Nod { TI P_I NFO i nf o;
Nod* next ;
publ i c:
f l oat Get I nf o( ) ;
Nod* Get Next ( ) ;
Nod( f l oat a, Nod* n) ;
};
f l oat Nod: : Get I nf o( )
{ r et ur n i nf o;
}
Nod* Nod: : Get Next ( )
{ r et ur n next ;
}
Nod: : Nod( f l oat a, Nod* n)
{ i nf o=a;
next =n;
}
cl ass St i va { Nod* Cap;
publ i c:
St i va( ) ;
St i va( f l oat a) ;
~St i va( ) ;
voi d Push( f l oat a) ;
f l oat Pop( ) ;
i nt Empt y( ) ;
voi d Af i seaza( ) ;
};
voi d St i va: : Af i seaza( )
{ Nod* x;
86
x=Cap;
whi l e( x)
{ pr i nt f ( " %5. 2f " , x- >Get I nf o( ) ) ;
x=x- >Get Next ( ) ;
}
}
St i va: : ~St i va( )
{ Nod* x;
whi l e( Cap)
{ x=Cap;
Cap=Cap- >Get Next ( ) ;
del et e x;
}
}
f l oat St i va: : Pop( )
{ f l oat x;
Nod* y;
y=Cap;
x=Cap- >Get I nf o( ) ;
Cap=Cap- >Get Next ( ) ;
del et e y;
r et ur n x; }
voi d St i va: : Push( f l oat a)
{ Cap=new Nod( a, Cap) ;
}
i nt St i va: : Empt y( )
{ r et ur n Cap?0: 1;
}
St i va: : St i va( f l oat a)
{ Cap= new Nod( a, NULL) ;
}
St i va: : St i va( )
{ Cap=NULL;
}
voi d mai n( )
{ St i va s;
i nt i ;
f l oat x;
i f ( s. Empt y( ) ) pr i nt f ( " \ nSt i va est e goal a" ) ;
el se pr i nt f ( " \ nSt i va cont i ne dat e" ) ;
f or ( i =0; i <10; i ++)
s. Push( ( f l oat ) i ) ;
s. Af i seaza( ) ;
x=s. Pop( ) ;
s. Af i seaza( ) ;
i f ( s. Empt y( ) ) pr i nt f ( " \ nSt i va est e goal a" ) ;
el se pr i nt f ( " \ nSt i va cont i ne dat e" ) ;
}
Clasa Nod conine atributele info (inIormaia util din nod) si next iar ca metode un constructor
care iniializeaz atributele obiectului si metode accesorii pentru accesarea valorilor atributelor.
Clasa Stiva conine un singur atribut, Cap care are ca valoare adresa primului nod al stivei (vrful
stivei). Constructorii clasei asigur crearea unei stive vide sau a unei stive cu un element.
Metodele asigur adugarea unei inIormaii n stiv, respectiv extragerea unei inIormaii. Metoda
Afiseaza asigur aIisarea pe ecran a inIormaiilor din stiv.
87
4.6. Derivarea claselor
Derivarea claselor este legat de implementarea conceptului de mostenire. n limbajul
C este permis mostenirea multipl. Pentru a deIini o clas Iiu ca Iiind derivat dintr-o clas
printe (sau mai multe clase printe), se procedeaz astfel:
class nume_clasa_fiu : lista_clase_printe
{ descr i er e membr i noi ai cl asei f i u};
n lista claselor printe se speciIic numele claselor printe, separate prin virgul si,
eventual, precedate de modificatori de acces se pot folosi modificatorii public sau private.
Acesti modiIicatori de acces deIinesc nivelul de protecie a membrilor clasei printe n clasa Iiu,
conIorm tabelului urmtor:
Nivel acces n clasa printe
Modificator de acces n
lista claselor printe
Nivel acces n clasa fiu
public inaccesibil
private
private inaccesibil
public protected
protected
private private
public public
public
private private
Pentru Iiecare clas printe se poate speciIica un modiIicator de acces. Dac nu se speciIic nici
un modiIicator de acces atunci, implicit, se consider modiIicatorul public.
Se observ c o clas derivat are acces la membrii clasei printe care au Iost deIinii ca
Iiind publici sau protejai si nu are acces la membrii privai. Prin derivare se construiesc ierarhii
de clase, deci din clasa Iiu se pot deriva alte clase noi. Dac la derivare s-a folosit modificatorul
de acces private, atunci toi membrii clasei printe vor deveni privai n clasa Iiu si o derivare n
continuare nu mai este posibil, ei Iiind inaccesibili pentru orice alt clas derivat din clasa Iiu.
ntruct ierarhiile de clase nu snt deIinitive ci oIer posibilitatea extinderii prin adugarea de noi
clase derivate, se preIer ca la derivare s se Ioloseasc modiIicatorul de acces public. De aceea
aceste este modificatorul explicit.
Exemplu
Fie clasa Punct care implementeaz entitatea punct geometric. Aceasta are atributele x si y, care
reprezint coordonatele punctului n plan. Este inclus o singur metod, care deseneaz punctul
pe ecran (aceast metod nu va implementat n acest exemplu).
cl ass punct { i nt x, y;
publ i c:
voi d deseneaza( ) ;
};
voi d punct : : deseneaza( )
{ / / cor pul nu est e descr i s i n acest exempl u
}
Fie clasa Cerc care implementeaz entitatea geometric cerc. Aceasta este descris prin
coordonatele centrului cercului si raza sa. Ca urmare clasa Cerc poate fi derivat din clasa Punct,
adugnd un nou atribut (raza) si o nou metod, pentru desenarea cercului.
88
cl ass cer c: punct
{ f l oat r aza;
publ i c:
voi d deseneaza( ) ;
};
void cerc::deseneaza()
{ / / cor pul nu est e descr i s i n acest exempl u
}
Clasa cerc o s aib ca membri atributele x, y si raza si metodele desenea: (mostenit de la clasa
Punct, care va fi folosit pentru desenarea centrului cercului) si desenea: (nou definit, care va
Ii Iolosit pentru desenarea cercului).
n lucrul cu ierarhii de clase se pune problema compatibilitii tipurilor de date (clase) n
cadrul atribuirilor si a conversiilor tipurilor de date. Ca principiu, un obiect al unei clase printe
poate primi ca valoare un obiect al unei clase derivate. Acelasi principiu este valabil si n cazul
pointerilor ctre obiecte. Utiliznd exemplul de mai sus si declaraiile
punct a, *pp;
cer c b, *pc;
snt corecte atribuirile
pp=&a;
pc=&b;
a=b;
pp=pc;
pp=&b;
Nu snt corecte urmtoarele atribuiri:
pc=&a;
b=a;
pc=pp;
Pot Ii realizate atribuiri Iolosind conversia explicit a tipurilor de date, astIel:
pc=( cer c *) pp;
pc=( cer c *) &a;
4.6.1.Redefinirea atributelor
Este posibil ca o clas Iiu s redeIineasc atribute mostenite de la clasa printe (atribute
publice sau protejate, ntruct cele private snt oricum inaccesibile n clasa fiu). n acest caz, clasa
Iiu va avea dou atribute cu acelasi nume. Implicit, utilizarea numelui atributului respectiv reIer
atributul redeIinit. Pentru a accesa atributul mostenit, trebuie Iolosit operatorul de rezoluie,
prefixnd numele atributului cu numele clasei printe.
Exemplu
Fie o clas Clasa_parinte care are un atribut a de tip float, atribut protejat, si o clas Clasa_fiu
care redeIineste atributul a, de tip double. x este un obiect de tipul Clasa_fiu.
cl ass Cl asa_par i nt e
{ pr ot ect ed:
89
f l oat a;
/ / descr i er ea r est ul ui cl asei
};
Cl ass Cl asa_f i u: publ i c Cl asa_par i nt e
{ pr ot ect ed:
doubl e a;
/ / descr i er ea r est ul ui cl asei
}
Cl asa_f i u x;
Expresia
x. a
reIer atributul a al clasei derivate, de tip double. Pentru a accesa atributul a mostenit de la clasa
printe, n cadrul unei metode a obiectului x trebuie Iolosit expresia
Cl asa_par i nt e: : a
4.6.2.Redefinirea metodelor
La Iel ca n cazul atributelor, o clas Iiu poate s redeIineasc metodele mostenite de la
clasa printe, n cazul n care metoda mostenit nu corespunde necesitilor. n exemplul anterior,
clasa Cerc redeIineste metoda desenea:. Dac a este un obiect de tipul Cerc, atunci apelul
a.deseneaz(); sau deseneaz(); efectuat din interiorul clasei Cerc va lansa n
execuie metoda redeIinit, cea descris de clasa Cerc, care va desena conturul cercului. Atunci
cnd e nevoie s se apeleze metoda mostenit numele acesteia se preIixeaz cu numele clasei
printe, Iolosind operatorul de rezoluie:
punct : : deseneaza( ) ;
Un astIel de apel poate s apar n interiorul metodei desenea: a clasei Cerc pentru a desena
centrul cercului.
4.6.3.Constructori yi destructori n relaia de moytenire
Constructorii si destructorii nu se mostenesc precum alte metode. La crearea unui obiect
al unei clase Iiu se apeleaz nti constructorul clasei printe si apoi constructorul clasei Iiu. Dac
snt mai multe clase printe (mostenire multipl) se apeleaz constructorii claselor printe, n
ordinea n care acestea apar n lista claselor printe. La stergerea unui obiect al unei clase Iiu se
apeleaz destructorii n ordine invers Ia de constructori: nti destructorul clasei Iiu si apoi
destructorii claselor printe, n ordine invers celei n care acestea apar n lista claselor printe.
Pentru a preciza parametrii reali utilizai pentru Iiecare din constructorii claselor printe,
antetul constructorului clasei derivate are o Iorm special:
cl ass Cl asa_f i u: cl asa_p1, cl asa_p2, cl asa_p3
{ / / at t r i but e
publ i c:
Cl asa_f i u( ) ; / / const r uct or ul cl asei f i u
}
Cl asa_f i u: : cl asa_f i u( ) : cl asa_p1( ) , cl asa_p2( ) , cl asa_p3( )
{ / / descr i er ea cor pul ui const r uct or ul ui
}
Se observ c n descrierea clasei, constructorul se descrie n mod obisnuit, dar ulterior,
n antetul constructorului apar apeluri ale constructorilor claselor printe. Ordinea n care apar
90
aceste apeluri nu are nici o importan, deoarece ordinea de apelare este dat de ordinea n care
snt speciIicate clasele printe.
Dac una din clasele printe nu are constructor, atunci nu o s apar un apel
corespunztor n antetul constructorului clasei fiu, pentru ea apelndu-se automat constructorul
implicit.
Dac nici una dintre clase nu are constructor explicit, atunci se Iolosesc constructorii
implicii pentru toate clasele.
O situaie deosebit este aceea n care clasa Iiu nu are constructor explicit, dar cel puin
una din clasele printe are un constructor explicit. Deoarece n aceast situaie nu se pot descrie
explicit parametrii pentru apelarea constructorilor claselor printe, acesti constructori trebuie s
aib valori implicite pentru toi parametrii.
4.6.4.Clase virtuale
n cazul mostenirii multiple pot s apar situaii n care o clas derivate mosteneste un
atribut (sau mai multe) de mai multe ori, prin intermediul mai multor linii de mostenire. Aceste
situaii produc ambiguiti legate de referirea atributului respectiv.
Limbajul C oIer un mecanism simplu prin care s se revin astIel de situaii, prin
utilizarea claselor virtuale. Fie urmtoare ierarhie, n care clasa cf este derivat din clasele cp1,
cp2 si cp3, toate acestea fiind la rndul lor derivate din clasa cb. Clasa de la baza ierarhiei, cb are
un atribut x. Acest atribut va Ii mostenit n clasele cp1, cp2, cp3. Clasa cf va mosteni 3 exemplare
ale atributului x.
Fig.4.5. Exemplu de mostenire multipl
Pentru a evita aceast situaie, clasa cb poate Ii declarat ca virtual la descrierea claselor
cp1, cp2 si cp3, astfel:
cl ass cp1: vi r t ual publ i c cb
{
};
cl ass cp2: vi r t ual publ i c cb
{
};
cl ass cp3: vi r t ual publ i c cb
{
};
cl ass cf : publ i c cp1, publ i c cp2, publ i c cp3,
{
};
91
Considernd aceste declaraii, clasa cf mosteneste o singur dat atributul x, prin
intermediul clasei cp1. Ca principiu, atributul este mostenit prin intermediul clasei care apare
prima n lista claselor printe.
n cazul n care n lista claselor printe apar si clase virtuale, se apeleaz nti
constructorii claselor virtuale, n ordinea n care au fost specificate, apoi constructorii claselor
nevirtuale, n ordinea n care snt acestea specificate.
4.6.5.Funcii virtuale
Exist situaii n care nu se poate decide n momentul compilrii care este contextul
curent n care se apeleaz o metod, care a Iost redeIinit ntr-o clas Iiu. AstIel de situaii apar
atunci cnd se lucreaz cu pointeri. Fie o clas cp care conine metoda executa, si o clas derivat
din ea, numit cf, care redeIineste metoda executa, cu aceeasi list de parametri. Fie urmtoarele
declaraii:
cp a; / / a est e obi ect de t i pul cp
cf b; / / b est e obi ect de t i pul cf
cp* po; / / po est e poi nt er cat r e cl asa cp
Pointerul po poate lua ca valoare att adresa unui obiect de tipul cp ct si adresa unui obiect de
tipul cf.
Fie apelul
po- >execut a( ) ;
n momentul compilrii nu se poate stabili ce metod s se apeleze, a clasei printe sau a clasei
Iiu. n astIel de situaii compilatorul genereaz un apel ctre metoda clasei printe.
Limbajul C oIer posibilitatea de a ntrzia decizia pn la momentul execuiei. n acest
scop metoda clasei printe se declar ca Iiind virtual prin scrierea cuvntului rezervat virtual
naintea antetului su. Este suIicient ca metoda clasei de baz s Iie declarat ca Iiind virtual, n
mod automat si metodele claselor derivate vor Ii virtuale.
Constructorii, destructorii si Iunciile inline nu pot Ii virtuale.
4.6.6.Clase abstracte
n limbajul C este deIinit conceptul de Iuncie virtual pur. Acest concept este
necesar n cazul ierarhiilor de clase. Exist situaii n care toate clasele ierarhiei trebuie s conin
o anumit metod, implementarea ei Iiind diIerit n Iiecare clas derivat. Clasa de la baza
ierarhiei este prea general pentru a putea implementa metodele. n aceast situaie n clasa de
baz se includ metode virtuale pure. Prezena unei astIel de metode oblig toate clasele derivate
s o conin, Iie c o redeIinesc Iie c nu.
O metod virtual pur se declar asemntor cu o metod virtual, adugnd la sIrsitul
antetului =0:
vi r t ual t i p_r ezul t at nume_met oda( l i st a par amet r i ) =0;
Metodele virtuale pure nu au un corp, nefiind implementate.
O clas care conine o metod virtual pur se numeste clas abstract. O clas abstract
nu poate Ii instaniat, ea coninnd metode care nu snt implementate.
92
Clasele derivate din clase abstracte pot s redeIineasc metodele virtuale pure sau nu.
Dac metoda virtual pur nu este implementat, atunci si clasa respectiv este clas abstract si
nu poate Ii instaniat.
De exemplu, ntr-o ierarhie de clase care descriu Iiguri geometrice, Iiecare clas are
nevoie de metode pentru desenarea figurii respective, calculul ariei sau perimetrului. La baza
ierarhiei se aIl o clas abstract care include metode virtuale pure pentru aceste operaii. Clasele
derivate, vor implementa metodele conIorm speciIicului Iiecrei Iiguri geometrice.
93
Bibliografie
1. [Aho, Hop sa] Aho A., Hopcroft J ., Ullman J ., Data Structures and Algorithms,
Addison-Wesley, 1983
2. [Bras, Brat] Brassard G., Bratley P., Algoritmics: Theory and Practice, Prentice-Hall,
1988
3. [Cor, Lei sa] Cormen T., Leiserson C., Rivest R., Introduction to Algorithms, MIT
Press, sixteenth printing, 1996
4. [Gon] Gonnet G.H., Handbook of Algorithms and Date Structures, Addison-Wesley,
1984
5. [Hor] Horowitz E., Sahni S., Fundamentals of Computer Algorithms, Computer
Science Press, 1978
6. [Knu] Knuth D., Fundamental Algorithms, vol 1 of The Art of Computer
Programming, Addison-Wesley, 1973
7. [Knu] Knuth D., Sorting and Searching, vol 3 of The Art of Computer Programming,
Addison-Wesley, 1973
8. [Man] Manmber U., Introduction to Algorithms: A Creative Approach, Addison-
Wesley, 1989
9. [Pop, Geo sa] Popovici Ct., Georgescu H., State L., Bazele informaticii, vol 1, Tip.
Universitii din Bucuresti, 1990
10. [Tom] Tomescu I.., Probleme de combinatoric i teoria grafurilor, Editura
Didactic si Pedagogic, Bucuresti, 1981
11. [Tud] Tudor S., Tehnici de programare, Ed. Teora, 1994
12. [Wil] Wilf H., Algorithms and Complexity, Prentice-Hall, 1986
13. [Negrescu, 1994] Liviu Negrescu, Limbafele C i C++ pentru nceptori, Editura
Microinfomatica, Cluj-Napoca, 1994
14. [Smeureanu, 1995] Ion Smeureanu, Ion Ivan, Marian Drdal, Limbajul C/C++ prin
exemple, Editura Cison, Bucuresti 1995
15. [Ghilic, 2003] Bogdan Ghilic-Micu, Ion Gh. Rosca, Constantin Apostol, Marian
Stoica, Ctlina Lucia Cocianu, Algoritmi n programare, Editura ASE,
Bucuresti 2003

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