Sunteți pe pagina 1din 334

C

1. Tehnici de programare

I
OG
1.1. Analiza algoritmilor
Prin analiza unui algoritm se identific resursele necesare pentru executarea

AG
algoritmului: timpul de execuie i memoria.
Analiza algoritmilor este necesar atunci cnd exist mai muli algoritmi pentru rezolvarea
aceleiai probleme i trebuie ales algoritmul cel mai eficient.

ED
Eficiena unui algoritm este evaluat prin timpul necesar pentru executarea
algoritmului.
Pentru a compara din punct de vedere al eficienei doi algoritmi care rezolv aceeai
problem, se folosete aceeai dimensiune a datelor de intrare n (acelai numr de

P
valori pentru datele de intrare).
Timpul de execuie al algoritmului se exprim prin numrul de operaii de baz
I
executate n funcie de dimensiunea datelor de intrare: T(n).
Pentru a compara doi algoritmi din punct de vedere al timpului de execuie, trebuie s se stabi-
leasc unitatea de msur care se va folosi, adic operaia de baz executat n cadrul algorit-

milor, dup care, se numr de cte ori se execut operaia de baz n cazul fiecrui algoritm.
IC

Operaia de baz este o operaie elementar sau o succesiune de operaii


elementare, a cror execuie nu depinde de valorile datelor de intrare.
CT

Exist algoritmi la care timpul de execuie depinde de distribuia datelor de intrare. S


considerm doi algoritmi de sortare a unui vector cu n elemente algoritmul de sortare
prin metoda seleciei directe i algoritmul de sortare prin metoda bulelor i ca operaie
de baz comparaia. Dac, n cazul primului algoritm, timpul de execuie nu depinde de
DA

distribuia datelor de intrare (modul n care sunt aranjate elementele vectorului nainte de
n (n 1)
sortarea lui), el fiind T(n) = , n cazul celui de al doilea algoritm timpul de exe-
2
cuie depinde de distribuia datelor de intrare (numrul de execuii ale structurii repetitive
DI

while depinde de modul n care sunt aranjate elementele vectorului nainte de sortare). n
cazul n care numrul de execuii ale operaiilor elementare depinde de distribuia datelor
de intrare, pentru analiza algoritmului se folosesc:
timpul maxim de execuie timpul de execuie pentru cazul cel mai nefavorabil de
RA

distribuie a datelor de intrare; n cazul sortrii prin metoda bulelor, cazul cel mai
nefavorabil este atunci cnd elementele vectorului sunt aranjate n ordine invers
dect aceea cerut de criteriul de sortare;
timpul mediu de execuie media timpilor de execuie pentru fiecare caz de
TU

distribuie a datelor de intrare.


Deoarece, n analiza eficienei unui algoritm, se urmrete comportamentul lui pentru o
dimensiune mare a datelor de intrare, pentru a compara doi algoritmi din punct de vedere
I

al eficienei, este suficient s se ia n considerare numai factorul care determin timpul de


ED

execuie i care este denumit ordinul de complexitate.


4 Tehnici de programare

C
Ordinul de complexitate al unui algoritm l reprezint timpul de execuie estimat
prin ordinul de mrime al numrului de execuii ale operaiei de baz: O((f(n)), unde
f(n) reprezint termenul determinant al timpului de execuie T(n).

I
OG
De exemplu, dac pentru algoritmul de sortare, prin metoda seleciei directe timpul de
n (n 1) n 2 n
execuie este T(n) = , ordinul de complexitate al algoritmului este
2 2 2
2
O(n ), deoarece n calcularea lui se ia n considerare numai factorul determinant din

AG
timpul de execuie.
n funcie de ordinul de complexitate, exist urmtoarele tipuri de algoritmi:
Ordin de Tipul algoritmului

ED
complexitate
O(n) Algoritm liniar.
m Algoritm polinomial. Dac m=2, algoritmul este ptratic, iar dac
O(n )
m=3, algoritmul este cubic.
n n

P
Algoritm exponenial. De exemplu: 2 , 3 etc. Algoritmul de tip O(n!)
O(kn) este tot de tip exponenial, deoarece:
n-1
1234...n > 222...2 = 2 .
I
O(logn) Algoritm logaritmic.
O(nlogn) Algoritm liniar logaritmic.
De exemplu, algoritmul de sortare prin metoda seleciei directe este un algoritm ptratic.

Ordinul de complexitate este determinat de structurile repetitive care se execut cu muli-


IC

mea de valori pentru datele de intrare. n cazul structurilor repetitive imbricate, ordinul de
complexitate este dat de produsul dintre numrul de repetiii ale fiecrei structuri repetitive.
Structura repetitiv Numrul de execuii ale Tipul
CT

corpului structurii algoritmului


for (i=1;i=n;i=i+k) {....} f(n)=n/k O(n)=n Liniar
for (i=1;i=n;i=i*k) {....} f(n)= logkn O(n)= logn Logaritmic
for (i=n;i=n;i=i/k) {....} f(n)= logkn O(n)= logn Logaritmic
DA

for (i=n;i=n;i=i+p) {....} f(n)=(n/p)*(n/q) = n2/(p*q) Polinomial


for (j=n; j=n;j=j+q) {....} O(n)= n2 ptratic
for (i=n;i=n;i=i++) {....} f(n)=1+2+3+ ... +n =(n*(n+1))/2 Polinomial
for (j=i; j=n;j=j++) {....} O(n)= n2 ptratic
DI

Determinai complexitatea urmtorilor algoritmi i precizai tipul algoritmului.


Tem Pentru fiecare algoritm se va considera dimensiunea datelor de intrare n.
a. determinarea valorii minime dintr-un ir de numere;
RA

b. inserarea unui element ntr-un vector, dup un element cu valoare precizat;


c. tergerea dintr-un vector a unui element cu valoare precizat,
d. stabilirea dac un ir de numere conine numai numere distincte;
e. sortarea unui vector folosind metoda bulelor;
TU

f. cutarea unui element cu valoare precizat, ntr-un vector nesortat;


g. cutarea unui element cu valoare precizat, ntr-un vector sortat;
h. determinarea tuturor permutrilor unei mulimi de numere.
I
ED
Informatic 5

C
1.2. Metode de construire a algoritmilor
n funcie de procesul de calcul necesar pentru rezolvarea unei probleme, exist urmtoarele

I
clase de probleme:

OG
Clase de probleme

Probleme de enumerare Probleme de decizie Probleme de optimizare

AG
prin care se gsesc toate prin care se precizeaz dac prin care se identific soluia
soluiile posibile exist sau nu cel puin o optim din mulimea de soluii
soluie posibile

ED
Generarea tuturor permutrilor unei mulimi de numere este o problem de enumerare, cuta-
rea unei valori precizate ntr-un ir de numere este o problem de decizie, iar gsirea modalitii
de plat a unei sume s cu un numr minim de bancnote de valori date este o problem de
optimizare.

P
Pentru rezolvarea aceleiai probleme se pot folosi mai multe metode de construire a
algoritmilor. Ai nvat deja c pentru rezolvarea aceleiai probleme putei folosi un:
algoritm iterativ;
I
algoritm recursiv.
Soluiile recursive sunt mult mai clare, mai scurte i mai uor de urmrit. Alegerea
algoritmului recursiv n locul celui iterativ este mai avantajoas n cazul n care soluiile

problemei sunt definite recursiv sau dac cerinele problemei sunt formulate recursiv.
IC

Timpul de execuie a unui algoritm recursiv este dat de o (1) pentru n=0
formul recursiv. De exemplu, pentru algoritmul de T(n) =
calculare a sumei primelor n numere naturale, funcia (1)+T(n-1) pentru n0
CT

pentru timpul de execuie este prezentat alturat, unde


(1) reprezint timpul de execuie a unei operaii elementare de atribuire a unei valori
sumei. Rezult c T(n)=(n+1)(1), iar ordinul de complexitate a algoritmului este O(n) la
fel ca i cel al algoritmului iterativ. n cazul implementrii recursive, fiecare apel al unui
DA

subprogram recurent nseamn nc o zon de memorie rezervat pentru execuia sub-


programului (variabilele locale i instruciunile). Din aceast cauz, n alegerea ntre un
algoritm iterativ i un algoritm recursiv trebuie inut cont nu numai de ordinul de complexi-
tate, dar i de faptul c, pentru o adncime mare a recursivitii, algoritmii recursivi nu
DI

mai sunt eficieni, deoarece timpul de execuie crete, din cauza timpilor necesari pentru
mecanismul de apel i pentru administrarea stivei de sistem.
Vei nva noi metode de construire a algoritmilor care v ofer avantajul c prezint
RA

fiecare o metod general de rezolvare care se poate aplica unei clase de probleme:
metoda backtracking;
metoda divide et impera;
metoda greedy;
TU

metoda programrii dinamice.


Fiecare dintre aceste metode de construire a algoritmilor se poate folosi pentru anumite clase
de probleme, iar n cazul n care pentru aceeai clas de probleme se pot folosi mai multe
metode de construire a algoritmilor, criteriul de alegere va fi eficiena algoritmului.
I
ED
6 Tehnici de programare

C
1.3. Metoda backtracking
1.3.1. Descrierea metodei backtracking

I
OG
Metoda backtracking se poate folosi pentru problemele n care trebuie s se genereze toate
soluiile, o soluie a problemei putnd fi dat de un vector:
S = {x1, x2, , xn}
ale crui elemente aparin, fiecare, unor mulimi finite Ai (xiAi), iar asupra elementelor

AG
unei soluii exist anumite restricii specifice problemei care trebuie rezolvat, numite
condiii interne. Mulimile Ai sunt mulimi ale cror elemente sunt n relaii bine stabilite.
Mulimile Ai pot s coincid sau nu. Pentru a gsi toate soluiile unei astfel de probleme
folosind o metod clasic de rezolvare, se execut urmtorul algoritm:

ED
PAS1. Se genereaz toate elementele produsului cartezian A1 A2 A3 An.
PAS2. Se verific fiecare element al produsului cartezian, dac ndeplinete condiiile
interne impuse ca s fie soluie a problemei.

P
Scop: identificarea problemelor pentru care trebuie enumerate toate soluiile, fiecare
I
soluie fiind format din n elemente xi, care aparin fiecare unor mulimi finite Ai i care
trebuie s respecte anumite condiii interne.
Enunul problemei 1: S se genereze toate permutrile mulimii {1, 2, 3}.

Cerina este de a enumera toate posibilitile de generare a 3 numere naturale din


mulimea {1, 2, 3}, astfel nct numerele generate s fie distincte (condiia intern a solu-
IC

iei). O soluie a acestei probleme va fi un vector cu 3 elemente: S = {x1,x2,x3}, n care


elementul xi reprezint numrul care se va gsi, n permutare, pe poziia i, iar mulimea Ai
reprezint mulimea numerelor din care se va alege un numr pentru poziia i. n acest
CT

exemplu, mulimile Ai coincid. Ele au aceleai 3 elemente, fiecare element reprezentnd un


numr. Ai = {1, 2, 3} = A
Dac s-ar rezolva clasic aceast problem, ar nsemna s se genereze toate elementele
produsului cartezian A1 A2 A3 = A A A = A3, adic mulimea:
DA

{(1,1,1), (1,1,2), (1,1,3), (1,2,1), , (3,3,2), (3,3,3)}


dup care se va verifica fiecare element al mulimii dac este o soluie a problemei, adic
dac cele trei numere dintr-o soluie sunt distincte. Soluiile obinute sunt:
DI

{(1,2,3), (1,3,2), (2,1,3), (2,3,1), (3,1,2), (3,2,1)}


Enunul problemei 2: S se genereze toate aranjamentele de 2 elemente ale mulimii {1, 2, 3}.
Cerina este de a enumera toate posibilitile de generare a 2 numere naturale din
mulimea {1, 2, 3}, astfel nct numerele generate s fie distincte (condiia intern a solu-
RA

iei). O soluie a acestei probleme va fi un vector cu 2 elemente: S = {x1,x2}, n care


elementul xi reprezint numrul care se va gsi n aranjament pe poziia i, iar mulimea Ai
reprezint mulimea numerelor din care se va alege un numr pentru poziia i. i n acest
exemplu, mulimile Ai coincid. Ele au aceleai 3 elemente, fiecare element reprezentnd un
TU

numr. Ai = {1, 2, 3} = A
Dac s-ar rezolva clasic aceast problem, ar nsemna s se genereze toate elementele
produsului cartezian A1 A2 = A A = A2, adic mulimea:
I

{(1,1), (1, 2), (1,3), (2,1), , (3,2), (3,3)}


ED
Informatic 7

C
dup care se va verifica fiecare element al mulimii, dac este o soluie a problemei,
adic dac cele dou numere dintr-o soluie sunt distincte. Soluiile obinute sunt:
{(1,2), (1,3), (2,1), (2,3), (3,1), (3,2)}

I
Enunul problemei 3: S se genereze toate combinrile de 2 elemente ale mulimii {1, 2, 3}.

OG
Cerina este de a enumera toate posibilitile de generare a 2 numere naturale din muli-
mea {1,2,3}, astfel nct numerele generate s fie distincte (condiia intern a soluiei),
iar soluiile obinute s fie distincte. Dou soluii sunt considerate distincte dac nu conin
aceleai numere. O soluie a acestei probleme va fi un vector cu 2 elemente: S = {x1,x2},

AG
n care elementul xi reprezint numrul care se va gsi n combinare pe poziia i, iar muli-
mea Ai reprezint mulimea numerelor din care se va alege un numr pentru poziia i. i n
acest exemplu, mulimile Ai coincid. Ele au aceleai 3 elemente, fiecare element repre-
zentnd un numr. Ai = {1, 2, 3} = A

ED
Dac s-ar rezolva clasic aceast problem, ar nsemna s se genereze toate elementele
produsului cartezian A1 A2 = A A = A2, adic mulimea:
{(1,1), (1, 2), (1,3), (2,1), , (3,2), (3,3)}

P
dup care se va verifica fiecare element al mulimii dac este o soluie a problemei, adic
dac cele dou numere dintr-o soluie sunt distincte i dac soluia obinut este distinct
de soluiile obinute anterior. Soluiile obinute sunt: {(1,2), (1,3), (2,3)}
I
Enunul problemei 4: S se genereze toate permutrile mulimii {1,2,3,4} care ndeplinesc
condiia c 1 nu este vecin cu 3, i 2 nu este vecin cu 4.
Cerina este de a enumera toate posibilitile de generare a 4 numere naturale din mulimea

{1, 2, 3, 4}, astfel nct numerele generate s fie distincte, iar 1 s nu se nvecineze cu 3, i 2
s nu se nvecineze cu 4 (condiia intern a soluiei). O soluie a acestei probleme va fi un
IC

vector cu 4 elemente: S = {x1,x2,x3,x4}, n care elementul xi reprezint numrul care se va


gsi n permutare pe poziia i, iar mulimea Ai reprezint mulimea numerelor din care se va
alege un numr pentru poziia i. n acest exemplu, mulimile Ai coincid. Ele au aceleai 4
CT

elemente, fiecare element reprezentnd un numr. Ai = {1, 2, 3, 4} = A


Dac s-ar rezolva clasic aceast problem, ar nsemna s se genereze toate elementele
produsului cartezian A1 A2 A3 A4 = A A A A = A4, adic mulimea:
DA

{(1,1,1,1), (1,1,1,2), (1,1,1,3), (1,1,1,4), ,(4,4,4,3), (4,4,4,4)}


dup care se va verifica fiecare element al mulimii dac este o soluie a problemei, adic
dac cele patru numere dintr-o soluie sunt distincte i dac 1 nu se nvecineaz cu 3, iar
2 cu 4. Soluiile obinute sunt:
DI

{(1,2,3,4), (1,4,3,2), (2,1,4,3), (2,3,4,1), (3,2,1,4), (3,4,1,2), (4,1,2,3), (4,3,2,1)}


Enunul problemei 5: S se aranjeze pe tabla de ah opt dame care nu se atac ntre
ele (problema celor 8 dame).
RA

Cerina este de a enumera toate posibilitile de aranjare a 8 dame pe o tabl de ah cu


dimensiunea 8x8 (8 linii i 8 coloane), astfel nct toate cele 8 dame s nu se atace ntre ele
(condiia intern a soluiei). Deoarece nu se pot aranja dou dame pe aceeai coloan (s-ar
ataca ntre ele), nseamn c pe fiecare coloan a tablei de ah se va pune o dam. O soluie
TU

a acestei probleme va fi un vector cu 8 elemente, S = {x1,x2,x3,x4,x5,x6,x7,x8}, n care


elementul xi reprezint numrul liniei pe care se va pune dama n coloana i, iar mulimea Ai
reprezint mulimea liniilor pe care se poate aranja dama din coloana i. i n acest caz
mulimile Ai coincid. Ele au aceleai opt elemente, fiecare element reprezentnd un numr de
I

linie: Ai = {1, 2, 3, 4, 5, 6, 7, 8} = A
ED
8 Tehnici de programare

C
Dac s-ar rezolva clasic aceast problem, ar nsemna s se genereze toate elementele
produsului cartezian A1 A2 A3 ... A8 = A A A A = A8, adic mulimea:
{(1,1,1,1,1,1,1,1), (1,1,1,1,1,1,1,2), (1,1,1,1,1,1,1,3), , (8,8,8,8,8,8,8,7), (8,8,8,8,8,8,8,8)}

I
dup care se va verifica fiecare element al mulimii, dac este o soluie a problemei, adic

OG
dac cele opt numere dintr-o soluie pot reprezenta coloanele pe care pot fi aranjate
damele pe fiecare linie, astfel nct s nu se atace ntre ele. Soluiile obinute sunt:
{(1,5,8,6,3,7,2,4), (1,6,8,3,7,4,2,5), (1,7,4,6,8,2,5,3), , (8,3,1,6,2,5,7,4),
(8,4,1,3,6,2,7,5)}

AG
Observaie. Metoda clasic de rezolvare a acestui tip de probleme necesit foarte multe
operaii din partea calculatorului, pentru a verifica fiecare element al produsului cartezian.
Presupunnd (pentru simplificare) c fiecare mulime Ai are m elemente, atunci algoritmul de
generare a elementelor produsului cartezian are complexitatea O(card(A1) card(A2)
n

ED
card(An)) = Q(m m m m) = O(m ). Considernd c algoritmul prin care se verific
dac un element al produsului cartezian este o soluie a problemei (respect condiia intern
a soluiei) are complexitatea O(p), atunci complexitatea algoritmului de rezolvare a
n
problemei va fi O(pm ). De exemplu, n algoritmul de generare a permutrilor, complexitatea

P
algoritmului de verificare a condiiei interne este dat de complexitatea algoritmului prin care se
verific dac numerele dintr-un ir sunt distincte. n acest algoritm, se parcurge irul de m
numere i pentru fiecare numr din ir se parcurge din nou irul pentru a verifica
I
dac acel numr mai exist n ir. Complexitatea algoritmului este dat de cele dou
2 2
structuri for imbricate: O(m ) p = m .
Metoda recomandat pentru acest gen de probleme este metoda backtracking sau meto-

da cutrii cu revenire prin care se reduce volumul operaiilor de gsire a tuturor soluiilor.
IC

Metoda backtracking construiete progresiv vectorul soluiei, pornind de la


primul element i adugnd la vector urmtoarele elemente, cu revenire la
elementul anterior din vector, n caz de insucces. Elementul care trebuie adugat se
CT

caut n mulime, printre elementele care respect condiiile interne.


Prin metoda backtracking se obin toate soluiile problemei, dac ele exist. Pentru
exemplificarea modului n care sunt construite soluiile, considerm problema generrii
DA

permutrilor mulimii {1, 2, 3, , n} (A1=A2= =An=A={1, 2, 3, , n}).


PAS1. Se alege primul element al soluiei ca fiind primul element din mulimea A. n
exemplu, x1=1, adic primul numr din permutare este 1.
PAS2. Se caut al doilea element al soluiei (x2). Pentru a-l gsi, se parcurg pe rnd ele-
DI

mentele mulimii A i, pentru fiecare element i al mulimii, se verific dac respect


condiiile interne. Cutarea continu pn cnd se gsete primul element din
mulimea A care ndeplinete condiia intern, dup care se oprete. n exemplu, se
caut numrul de pe a doua poziie a permutrii, verificndu-se dac al doilea numr
RA

din permutare este diferit de primul numr. Se parcurg primele dou elemente ale
mulimii A i se gsete elementul x2=2, dup care procesul de cutare se oprete.
PAS3. Se caut al treilea element al soluiei (x3). Cutarea va folosi acelai algoritm de
la Pasul 2. n exemplu, se caut numrul din poziia a treia din permutare. Se
TU

gsete elementul x3=3.


PAS4. Presupunnd c s-au gsit primele k elemente ale soluiei, x1, x2, x3, , xk, se
trece la cutarea celui de al k+1-lea element al soluiei, xk+1. Cutarea se va face
astfel: se atribuie pe rnd lui xk+1 elementele mulimii A, pn se gsete primul
I
ED

element i care ndeplinete condiia intern. n exemplu, condiia intern este ca


Informatic 9

C
numrul din poziia k+1 a permutrii s nu fie egal cu nici unul dintre numerele
din poziiile anterioare lui k+1. Pot s apar dou situaii:
a. Exist un element i n mulimea A, astfel nct xk+1 = i s fie element al soluiei

I
problemei. n acest caz, se atribuie elementului xk+1 al soluiei valoarea i, dup

OG
care se verific dac s-a gsit soluia problemei. n exemplu, presupunem c pe
nivelul k+1 s-a gsit numrul 4. Se verific dac s-au generat toate cele n
elemente ale mulimii S, adic dac s-au gsit numere pentru toate cele n poziii
din permutare (k=n). Dac s-a gsit soluia problemei, atunci se afieaz soluia;

AG
altfel, se caut urmtorul element al soluiei, relundu-se operaiile de la Pasul 4.
b. S-au parcurs toate elementele mulimii A i nu s-a gsit nici un element i care s fie
elementul xk+1 al soluiei problemei. nseamn c trebuie s revenim la elementul k
al soluiei xk. Aadar, se consider generate primele k-1 elemente ale soluiei: x1,
x2, , xk-1 i, pentru elementul xk al soluiei, se reia cutarea, cu urmtorul

ED
element din mulimea A, adic se reiau operaiile de la Pasul 4 pentru elementul
xk al soluiei, ns nu cu primul element din mulimea A, ci cu elementul din muli-
mea A care se gsete imediat dup cel care a fost atribuit anterior pentru elemen-

P
tul xk al soluiei. n exemplu, lund n considerare modul n care au fost generate
primele k numere ale permutrii, n poziia k+1, orice numr s-ar alege, el mai
exist pe una dintre cele k poziii anterioare, i se revine la elementul k, care presu-
I
punem c are valoarea 3. Se genereaz n aceast poziie urmtorul numr din
mulimea A (4) i se verific dac el nu mai exist pe primele k-1 poziii ale permu-
trii, iar dac exist, se genereaz urmtorul element din mulimea A (5) .a.m.d.
PAS5. Algoritmul se ncheie dup ce au fost parcurse toate elementele mulimii A pentru

elementul x1 al soluiei. n exemplu, algoritmul se ncheie dup ce s-au atribuit pe


rnd valorile 1, 2, , n, elementului de pe prima poziie a permutrii.
IC

Generarea tuturor permutrilor mulimii {1, 2, 3}


1 2 3 3 12 2 3
CT

12 2 2 2 3 3 3 3 1
1 1 1 1 1 1 1 1 2 2

1 2 3 3 1 1 23
DA

1 1 1 23 3 3 3 1
2 2 2 2 2 2 2 3 3

1 23
DI

12 2 3 1 Au fost parcurse
1 1 1 2 2 2 2 3 toate elementele
3 3 3 3 3 3 3 mulimii A pen-
tru elementul x1 al soluiei.
RA

Observaie. n metoda backtracking, dac s-a gsit elementul xk al soluiei, elementului


xk+1 al soluiei i se atribuie o valoare numai dac mai exist o valoare care s ndeplineas-
c condiia de continuare a construirii soluiei adic dac, prin atribuirea acelei valori, se
poate ajunge la o soluie final pentru care condiiile interne sunt ndeplinite.
TU

Desenai diagramele pentru generarea prin metoda backtracking a:


Tem a. tuturor aranjamentelor de 2 elemente ale mulimii {1, 2, 3};
b. tuturor combinrilor de 2 elemente ale mulimii {1, 2, 3};
c. tuturor permutrilor mulimii {1, 2, 3, 4} care ndeplinesc condiia c 1 nu este vecin cu 3, i
I
ED

2 nu este vecin cu 4.
10 Tehnici de programare

C
Algoritmul metodei backtracking poate fi generalizat pentru orice problem care ndepli-
nete urmtoarele condiii:
1. Soluia problemei poate fi pus sub forma unui vector S = {x1, x2, , xn} ale crui

I
elemente xi aparin fiecare unei mulimi Ai, astfel: x1A1, x2A2, , xnAn.

OG
2. Mulimile Ai sunt finite, iar elementele lor sunt numere ntregi i se gsesc ntr-o
ordine bine stabilit.
Algoritmul backtracking este urmtorul:
PAS1. Se alege primul element al soluiei S: x1Ai.

AG
PAS2. Ct timp nu au fost parcurse toate elementele mulimii A1 (nu au fost gsite toate
soluiile) execut:
PAS3. Pentru fiecare element al soluiei execut:
PAS4. Se presupune c s-au gsit primele k elemente ale soluiei (x1, x2, , xk)

ED
aparinnd mulimilor A1, A2, A3, , Ak i se trece la cutarea celui de al
k+1-lea element al soluiei, xk+1, printre elementele mulimii Ak+1. Cutarea
se va face astfel: se atribuie, pe rnd, lui xk+1, elementele mulimii Ak+1,
pn se gsete primul element care ndeplinete condiia de continuare.

P
PAS5. Dac exist un element ai n mulimea Ak+1, astfel nct xk+1 = ai s
aparin soluiei problemei, atunci se atribuie elementului xk+1 valoa-
rea ai i se trece la Pasul 7; altfel, se trece la Pasul 6.
I
PAS6. Deoarece s-au parcurs toate elementele mulimii Ak+1 i nu s-a gsit
nici un element ai care s ndeplineasc condiia de continuare, se
revine la elementul xk i se consider generate primele k-1 elemente

ale soluiei: x1, x2, , xk-1, i pentru elementul xk se reia cutarea cu


urmtorul element din mulimea Ak, adic se reiau operaiile de la
IC

Pasul 4 pentru elementul xk al soluiei, ns nu cu primul element din


mulimea Ak ci cu elementul din mulimea Ak care se gsete imediat
dup cel care a fost atribuit anterior elementului xk.
CT

PAS7. Se verific dac s-a gsit soluia problemei, adic dac s-au gsit
toate elementele mulimii S. Dac s-a gsit soluia problemei, atunci
se afieaz soluia; altfel, se trece la cutarea urmtorului element al
soluiei, relundu-se operaiile de la Pasul 4.
DA

1.3.2. Implementarea metodei backtracking


Pentru implementarea metodei se folosesc urmtoarele structuri de date i subprograme.
DI

Date i structuri de date


Pentru a memora elementele xk ale soluiei se folosete o structur de date de tip stiv, care
RA

este implementat static printr-un vector st. Pentru vrful stivei se folosete variabila k.
Cnd s-a gsit elementul xk al soluiei, se urc n stiv, prin incrementarea vrfului cu 1
(k++), pentru a cuta elementul xk+1 al soluiei, iar pentru a reveni la elementul xk-1 al soluiei
se coboar n stiv prin decrementarea vrfului cu 1 (k--). Iniial, stiva are dimensiunea 1
(kmin=1), corespunztoare poziiei de pornire, i conine valoarea primului element al soluiei.
TU

Pentru elementul din vrful stivei (care corespunde elementului xk al soluiei) se va atribui o
valoare din mulimea Ak care poate fi un element al soluiei: st[k]=a[i]. Dup parcurgerea
complet a mulimilor Ak, stiva va avea dimensiunea n (kmax=n) corespunztoare numrului
I
ED
Informatic 11

C
de elemente ale soluiei. Vrful stivei va fi iniial 1, la gsirea unei soluii va avea valoarea n,
iar la terminarea algoritmului vrful stivei va avea valoarea 0.
Se mai folosesc urmtoarele variabile de memorie:

I
as pentru a ti dac pentru elementul xk al soluiei mai exist un succesor, adic dac

OG
mai exist un element n mulimea Ak care ar putea fi elementul xk al soluiei (este o varia-
bil logic ce are valoarea 1 true, dac exist succesor; altfel, are valoarea 0 false),
ev pentru a ti dac succesorul gsit respect condiia de continuare i poate fi
elementul xk al soluiei (este o variabil logic ce are valoarea 1 true, dac

AG
succesorul este element al soluiei; altfel, are valoarea 0 false) i
n pentru dimensiunea soluiei (numrul de elemente ale soluiei, n cazul
problemelor n care toate soluiile au acelai numr de elemente).
typedef int stiva[100];

ED
stiva st; //st=stiva
int n,k,ev,as; //k=vrful stivei
n cazul problemelor prezentate n studiul de caz, un element xk al soluiei este format
dintr-o singur valoare: numrul din poziia k (n cazul permutrilor, al aranjamentelor i

P
al combinrilor), respectiv numrul liniei pe care va fi pus dama din coloana k. n proble-
mele n care trebuie gsit un traseu, un element xk al soluiei este format din dou valori
I
care reprezint coordonatele poziiei n care se face urmtoarea deplasare. n acest caz,
pentru memorarea elementelor xk ale soluiei se va folosi o stiv dubl:
typedef int stiva[100][3];
stiva st;

sau o nregistrare n care cele dou cmpuri reprezint coordonatele deplasrii:


IC

struct element{int x,y;};


typedef element stiva[100];
stiva st;
CT

Elementele mulimii Ak vor fi perechi de valori (i,j) i vor reprezenta coordonatele unei
poziii, iar pentru elementul din vrful stivei se va atribui o valoare, din mulimea Ak, care
poate fi un element al soluiei, astfel: st[k][1]=i i st[k][2]=j, respectiv
st[k].x=i i st[k].y=j.
DA

Pentru simplificarea implementrii, toate aceste date i structuri de date sunt declarate
globale, deoarece valoarea pentru vrful stivei se va transmite mai uor, ntre subpro-
grame ca variabil global.
DI

Subprograme
Algoritmul va fi implementat prin:
un subprogram care va fi acelai pentru toi algoritmii de rezolvare prin metoda
RA

backtracking (parte fix) i care descrie strategia general backtracking i


subprogramele care au aceeai semnificaie pentru toi algoritmii, dar al cror coni-
nut difer de la o problem la alta, depinznd de condiiile interne ale soluiei.
Semnificaia subprogramelor folosite este (se va considera ca exemplu generarea
TU

permutrilor mulimii {1, 2, 3, , n}):


Subprogramul init (funcie procedural). Se iniializeaz elementul din vrful stivei
(elementul k). n acest element se va nregistra urmtorul element al soluiei. Acest
element se iniializeaz cu o valoare care nu face parte din mulimea Ak considerat,
I
ED

urmnd ca n urmtorii pai ai algoritmului s se atribuie acestui element prima


12 Tehnici de programare

C
valoare din mulimea Ak. n exemplu, nivelul k al stivei se va iniializa cu valoarea 0
(st[k]=0), urmnd ca la pasul urmtor s i se atribuie ca valoare 1, adic primul
numr din mulimea {1, 2, 3, ..., n}.

I
void init()

OG
{st[k]=0;}
Subprogramul succesor (funcie operand). Verific dac mai exist n mulimea Ak
un element pentru nivelul k al soluiei (un succesor). Dac mai exist un succesor, se
trece la urmtorul element din mulimea Ak, iar funcia va returna valoarea 1 (true).

AG
Dac nu mai exist un succesor, funcia va returna valoarea 0 (false). Valoarea
returnat de funcie se va atribui variabilei as. Iniial, valoarea variabilei de memorie
as este 1 (true) se presupune c mai exist un succesor. n exemplu, subprogramul
succesor va verifica dac pentru poziia k din permutare mai exist un numr. Dac

ED
numrul i de pe nivelul k este mai mic dect n, poziiei k i se va atribui numrul
urmtor, i+1, i funcia va returna valoarea 1 (true), iar dac numrul de pe nivelul k
este n, nseamn c pe aceast poziie din permutare nu mai poate fi pus nici un
numr i funcia va returna valoarea 0 (false).

P
int succesor()
{if (st[k]<n) {st[k]++; return 1;}
else return 0;}
I
Subprogramul valid (funcie operand). Verific dac valoarea atribuit elementului
xk al soluiei ndeplinete condiia de continuare, adic poate fi considerat c face
parte din soluia problemei (dac succesorul gsit este element al soluiei). Dac este

ndeplinit condiia (se evalueaz expresia prin care este descris condiia), funcia va
returna valoarea 1 (true); altfel, va returna valoarea 0 (false). Valoarea returnat de
IC

funcie se va atribui variabilei ev. Iniial, valoarea variabilei ev este 0 (false) se


presupune c succesorul gsit nu este elementul k al soluiei. n exemplu, subpro-
gramul valid va verifica dac numrul din poziia k nu mai exist n cele k-1 poziii
CT

anterioare. Dac numrul nu ndeplinete aceast condiie, funcia va returna valoarea


0 (false).
int valid()
DA

{for (int i=1;i<k;i++)


if (st[i]==st[k]) return 0;
return 1;}
Subprogramul solutie (funcie operand). Verific dac s-au obinut toate elementele
DI

soluiei. n exemplu, subprogramul solutie va verifica dac au fost gsite toate cele
n elemente ale soluiei, adic dac s-au gsit soluii de aranjare n permutare pentru
toate cele n numere. Dac s-a gsit soluia, subprogramul ntoarce valoarea 1 (true);
altfel, ntoarce valoarea 0 (false).
RA

int solutie()
{return k==n;}
Subprogramul tipar (funcie procedural). Afieaz elementele soluiei. De obicei,
afiarea soluiei const n afiarea valorilor din stiv.
TU

void tipar()
{for (int i=1;i<=n;i++) cout<<st[i]<<" ";
cout<<endl;}
I
ED
Informatic 13

C
Numrul de ordine al Elementele soluiei
elementelor soluiei
n an1 an2 anj anm xn

I
OG
.. Parcurgerea elementelor se face cu .
.. subprogramul succesor .
i ai1 ai2 aij aim xi

AG
.. k=k+1 . k=k-1
2 a21 a22 a2j a2m x2
1 a11 a12 a1j a1m x1

ED
1 2 j . m
Numrul de ordine al elementelor din mulimea Ak Stiva st[k]

P
Subprogramul valid verific dac este element al soluiei
Subprogramul fix poate fi implementat iterativ sau recursiv.
Implementarea iterativ
I
void bt() //partea fix a algoritmului
{k=1; //se iniializeaz vrful stivei
init(); //se iniializeaz stiva pentru primul element al soluiei

while (k>0) //ct timp stiva nu s-a golit


{as=1; ev=0;
IC

while(as && !ev) // ct timp are succesor i nu s-a gsit


// elementul k al soluiei
{as=succesor(); // se caut succesor
CT

if(as) // dac are succesor, atunci


ev=valid();} // se verific dac este element al soluiei
// se iese din structura repetitiv while dac nu mai exist
DA

// succesor sau dac s-a gsit elementul soluiei


if(as) // dac are succesor, atunci
if (solutie()) //dac s-au obinut toate elementele soluiei,
tipar(); // atunci se afieaz elementele soluiei; _
DI

else {k++; // altfel, se urc n stiv pentru a nregistra


// urmtorul element al soluiei
init();} // i se iniializeaz stiva pentru
// urmtorul element al soluiei;
RA

else k--;} // altfel, se coboar n stiv pentru a reveni


} // la elementul anterior al soluiei
void main() { ... bt(); ... }
Implementarea recursiv Prelucrrile care se fac pentru elementul k al soluiei se fac
TU

i pentru elementul k+1 al soluiei i aceste prelucrri pot fi apelate pentru elementul k+1
al soluiei, iar trecerea de la elementul k al soluiei la elementul k+1 al soluiei se face prin
apelul recursiv al acestor prelucrri. n algoritmul backtracking implementat iterativ, reve-
nirea la nivelul k-1 trebuie s se fac atunci cnd pe nivelul k nu se gsete o valoare
I
ED

care s ndeplineasc condiiile interne. n cazul implementrii recursive, condiia de


14 Tehnici de programare

C
baz este ca pe nivelul k s nu se gseasc o valoare care s ndeplineasc condiiile
interne. Cnd se ajunge la condiia de baz, nceteaz apelul recursiv i se revine la
subprogramul apelant, adic la subprogramul n care se prelucreaz elementul k-1 al

I
soluiei, iar n stiv se vor regsi valorile prelucrate anterior n acest subprogram.

OG
Deoarece apelul recursiv se face n funcie de valoarea vrfului stivei (k), aceast valoare
se va transmite, ntre subprograme, prin intermediul parametrilor de comunicaie.
void bt(int k) //partea fix a algoritmului
{init(k); //se iniializeaz stiva pentru elementul k al soluiei

AG
while(succesor(k))
//ct timp se gsete succesor pentru elementul k al soluiei
if(valid(k)) dac succesorul este element al soluiei
if(solutie(k)) //dac s-au obinut toate elementele soluiei,

ED
tipar(k); // atunci se afieaz elementele soluiei;_
else bt(k+1); //altfel, se apeleaz subprogramul pentru a gsi
} //elementul k+1 al soluiei
void main() { ... bt(1); ... }

P
Complexitatea algoritmului metodei backtracking
Dac fiecare soluie are n elemente i fiecare mulime Ai din care se alege un element al
I
soluiei are m elemente, atunci complexitatea algoritmului metodei backtracking este
n
O(card(A1) card(A2) card(An)) = Q(m m m m) = O(m ). Dac numrul de
elemente ale mulimilor Ai este diferit i notm cu:

mmin= min(card(A1), card(A2), , card(An))


mmax= max(card(A1), card(A2), , card(An))
IC

n
atunci complexitatea algoritmului va fi cuprins ntre o complexitate minim O(mmin ) i o
n
complexitate maxim O(mmax ). Rezult c algoritmul metodei backtracking este un
algoritm exponenial. Avnd o complexitate exponenial, metoda backtracking se reco-
CT

mand numai dac nu se cunoate un algoritm mai eficient.

1.3.3. Probleme rezolvabile prin metoda backtracking


DA

Metoda backtracking este recomandat n cazul problemelor care au urmtoarele


caracteristici:
se cere gsirea tuturor soluiilor posibile;
nu se cunoate un algoritm mai eficient.
DI

Alte exemple de probleme clasice care se pot rezolva folosind metoda backtracking:
generarea tuturor elementelor unui produs cartezian;
generarea tuturor partiiilor unui numr natural;
RA

generarea tuturor partiiilor unei mulimi;


generarea tuturor funciilor surjective;
generarea tuturor funciilor injective;
generarea tuturor posibilitilor de plat a unei sume cu bancnote de valori date;
TU

generarea tuturor posibilitilor de acoperire a tablei de ah prin sritura calului (parcur-


gerea tablei de ah prin sritura calului, fr a se trece de dou ori prin aceeai poziie).
generarea tuturor posibilitilor de ieire dintr-un labirint;
I
ED
Informatic 15

C
1.3.3.1. Generarea permutrilor
Prin asamblarea subprogramelor definite anterior, programul pentru generarea tuturor

I
permutrilor muimii {1, 2, 3, , n} va fi:

OG
Implementarea iterativ Implementarea recursiv
#include<iostream.h> #include<iostream.h>
typedef int stiva[100]; typedef int stiva[100];
int n,k,ev,as; int n;

AG
stiva st; stiva st;
void init() void init(int k)
{st[k]=0;} {st[k]=0;}
int succesor() int succesor(int k)

ED
{if (st[k]<n) {if (st[k]<n)
{st[k]=st[k]+1; return 1;} {st[k]=st[k]+1; return 1;}
else return 0;} else return 0;}
int valid() int valid(int k)

P
{for(int i=1;i<k;i++) {for(int i=1;i<k;i++)
if (st[k]==st[i]) return 0; if (st[k]==st[i]) return 0;
return 1;} return 1;}
I
int solutie() int solutie(int k)
{return k==n;} {return k==n;}
void tipar() void tipar()
{for(int i=1;i<=n;i++) {for(int i=1;i<=n;i++)

cout<<st[i]<<" "; cout<<st[i]<<" ";


cout<<endl;} cout<<endl;}
IC

void bt() void bt(int k)


{k=1; {init(k);
CT

init(); while(succesor(k))
while (k>0) if(valid(k))
{as=1; ev=0; if(solutie(k)) tipar();
while(as && !ev) else bt(k+1);}
DA

{as=succesor(); void main()


if(as) ev=valid();} {cout<<"n= "; cin>>n;
if(as) bt(1);}
if (solutie()) tipar();
DI

else {k++; init();}


else k--;}}
void main()
{cout<<"n= "; cin>>n;
RA

bt();}
Algoritmul de generare a permutrilor poate fi folosit i n alte probleme. De exemplu, s se
genereze toate permutrile mulimii {1, 2, 3, , n} n care nu apar numere consecutive.
TU

Aceast problem face parte din categoria de probleme de generare a permutrilor cu


condiie soluia conine o condiie intern suplimentar fa de cea impus de permutare.
n acest exemplu, condiia suplimentar de continuare a construirii soluiei este ca numrul ales
pentru nivelul k al soluiei s nu difere printr-o unitate de numrul care se gsete pe nivelul k-1
I

al soluiei. Modificarea apare n subprogramul valid():


ED
16 Tehnici de programare

C
int valid()
{if (k>1 && abs(st[k]-st[k-1])==1) return 0;
for (int i=1;i<k;i++)if (st[i]==st[k]) return 0;

I
return 1;}

OG
Scriei urmtoarele programe, n care s folosii metoda backtracking pentru
Tem generarea tuturor permutrilor.
1. S se genereze toate permutrile unei mulimi de numere oarecare.
Numerele se memoreaz ntr-un vector. (Indicaie. Se permut indicii elementelor din

AG
vectorul v, i n subprogramul tipar() se afieaz elementele v[st[i]]).
2. S se afieze toate anagramele unui cuvnd citit de la tastatur.
3. S se genereze toate matricele binare ptrate, de dimensiune n, care au un singur
element de 1 pe linie i un singur element de 1 pe coloan. O matrice binar este o

ED
matrice ale crei elemente au valoarea 0 sau 1. Indicaie. Soluia are n elemente.
Elementul soluiei xk reprezint numrul coloanei de pe linia k pe care se gsete
elementul cu valoarea 1.
4. S se genereze toate funciile bijective f : AB, unde card(A)=card(B)=n.

P
5. S se genereze toate posibilitile de aranjare pe o tabl de ah, cu dimensiunea nn, a
n ture care s nu se atace ntre ele. Deoarece tura se poate deplasa numai pe linia sau
pe coloana pe care a fost plasat, turele se pot ataca ntre ele pe linie i pe coloan.
I
Indicaie. Se observ c fiecare tur trebuie s fie plasat singur pe o coloan, ca
s nu se atace ntre ele. Soluia problemei este dat de mulimea cu n elemente {x1,
x2, , xn} care se memoreaz n stiv. Elementul soluiei xk reprezint numrul liniei

n care se aaz tura din coloana k i se memoreaz pe nivelul k al stivei st.


Deoarece dou ture nu pot fi aezate pe aceeai linie, stiva trebuie s conin ele-
IC

mente distincte. Problema se reduce la generarea permutrilor mulimii {1, 2, 3, , n}.


Interpretarea soluiei este: fiecare tur se plaseaz n coloana k, pe linia st[k].
6. S se genereze toate permutrile mulimii {1, 2, 3, , n} n care dou numere vecine nu
CT

trebuie s fie ambele pare sau ambele impare. Indicaie. n subprogramul valid() se
mai verific i condiia suplimentar de vecintate.
int valid()
DA

{if (k>1 && (st[k-1]%2==0 && st[k]%2==0)||


(st[k-1]%2==1 && st[k]%2==1)) return 0;
for (int i=1;i<k;i++) if (st[i]==st[k]) return 0;
return 1;}
7. S se genereze toate permutrile mulimii {1, 3, 5, , 2n+1}. Indicaie. Soluia are n
DI

elemente. n subprogramul init() elementul din vrful stivei se iniializeaz cu valoa-


rea -1, iar n subprogramul succesor() se modific modul de determinare a succe-
sorului.
RA

int succesor()
{if (st[k]<2*n+1) {st[k]= st[k]+2; return 1;}
else return 0;}
8. S se genereze toate permutrile unei mulimi de numere oarecare, astfel nct cea mai
TU

mic i cea mai mare valoare s-i pstreze poziiile iniiale.


9. ntr-un ir sunt aranjate n persoane. S se genereze toate posibilitile de rearanjare n
ir a acestor persoane, astfel nct fiecare persoan din ir:
a. s nu aib n faa sa aceeai persoan pe care a avut-o n irul iniial;
I

b. s nu aib aceiai vecini ca n irul iniial;


ED
Informatic 17

C
c. s nu aib n faa sa persoanele pe care le-a avut n irul iniial;
d. s fie desprit de vecinii pe care i-a avut n irul iniial de una sau cel mult p
persoane; valoarea pentru p se citete de la tastatur.

I
OG
1.3.3.2. Generarea produsului cartezian
Se genereaz toate elementele produsului cartezian A1 A2 A3 An, unde Ai={1,
2, , ni}.
O soluie a problemei va fi un element al produsului cartezian i va fi format din n ele-

AG
mente. Un element xk al soluiei poate fi orice element din mulimea Ak (nu exist
condiii interne). Numrul de elemente ale fiecrei mulimi Ai va fi memorat ntr-un
vector m cu lungimea logic n, unde m[i]=ni. Fa de algoritmul pentru generarea per-
mutrilor, apar urmtoarele diferene:

ED
Deoarece fiecare mulime Ak are un numr diferit de elemente, elementul de pe nive-
lul k are succesor dac numrul i de pe acest nivel este mai mic dect m[k].
Deoarece nu exist condiii interne, nu exist restricii nici pentru condiia de conti-
nuare, i subprogramul valid() va furniza valoarea 1.

P
Implementarea iterativ Implementarea recursiv
#include<iostream.h> #include<iostream.h>
I
typedef int stiva[10]; typedef int stiva[10];
int n,k,ev,as,m[10]; int n;
stiva st; stiva st;
void init() void init(int k)

{st[k]=0;} {st[k]=0;}
int succesor() int succesor(int k)
IC

{if (st[k]<m[k]) {if (st[k]<m[k])


{st[k]=st[k]+1; return 1;} {st[k]=st[k]+1; return 1;}
CT

else return 0;} else return 0;}


int valid() int valid(int k)
{return 1;} {return 1;}
int solutie() int solutie(int k)
DA

{return k==n;} {return k==n;}


void tipar() void tipar()
{for(int i=1;i<=n;i++) {for(int i=1;i<=n;i++)
cout<<st[i]<<" "; cout<<st[i]<<" ";
DI

cout<<endl;} cout<<endl;}
void bt() void bt(int k)
{//partea fix a algoritmului} {//partea fix a algoritmului}
void main() void main()
RA

{cout<<"n= "; cin>>n; {cout<<"n= "; cin>>n;


for(int i=1;i<=n;i++) for(int i=1;i<=n;i++)
{cout<<"Nr. de elemente multimea " {cout<<"Nr. de elemente multimea "
<<i<<" "; <<i<<" ";
TU

cin>>m[i];} cin>>m[i];}
bt();} bt(1);}
Algoritmul de generare a produsului cartezian poate fi folosit i n alte probleme. De exemplu,
I

pentru generarea tuturor submulimilor unei mulimi.


ED
18 Tehnici de programare

C
O submulime este format din elemente ale mulimii A. Pentru simplificarea algoritmului,
vom considera mulimea A={1,2,3,,n}. Considerm mulimea B={0,1}. Pentru construirea
submulimilor, pentru fiecare submulime se definete funcia Submulimile Stiva

I
f:AB, astfel: dac elementul i din mulimea A aparine sub- 000

OG
{}=
mulimii, atunci f(i)=1; altfel, f(i)=0. Problema se reduce la {3} 001
n
generarea produsului cartezian B . Soluia va fi memorat n {2} 010
stiv i va avea n elemente, fiecare element k al soluiei avnd {2, 3} 011
valoarea 0 sau 1, cu semnificaia c elementul k din mulimea {1} 100

AG
A aparine, respectiv nu aparine submulimii. Alturat, sunt {1,3} 101
prezentate toate submulimile mulimii {1,2,3} i coninutul {1,2} 110
stivei pentru fiecare dintre ele. {1,2,3} 111
Fa de programul anterior, apar urmtoarele modificri:

ED
Deoarece mulimile produsului cartezian sunt identice (B={0,1}), s-au modificat: sub-
programul init() iniializarea nivelului k al stivei se face cu valoarea -1 , cu 1 mai
mic dect 0 i subprogramul succesor() elementul are succesor numai dac
este mai mic dect ultimul element din mulime, 1.

P
n subprogramul de afiare a soluiei, va fi afiat numrul nivelului i pentru care, n
stiv, se memoreaz valoarea 1.
I
Implementarea iterativ Implementarea recursiv
#include<iostream.h> #include<iostream.h>
typedef int stiva[100]; typedef int stiva[100];
int n,k,ev,as; int n;

stiva st; stiva st;


void init() void init (int k)
IC

{st[k]=-1;} {st[k]=0;}
int succesor() int succesor(int k)
{if (st[k]<1) {if (st[k]<st[k-1]+1)
CT

{st[k]=st[k]+1; return 1;} {st[k]=st[k]+1;return 1;}


else return 0;} else return 0;}
int valid() int valid() {return 1;}
DA

{return 1;} int solutie(int k)


int solutie() {return k==n;}
{return k==n;} void tipar()
void tipar () {int i,x=0; cout<<"{";
DI

{int i,x=0; cout<<"{"; for (i=1;i<=n;i++)


for (i=1;i<=n;i++) if (st[i]==1)
if (st[i]==1) {cout<<i<<","; x=1;}
{cout<<i<<","; x=1;} if (x) cout<<'\b';
RA

if (x) cout<<'\b'; cout<<"}"<<endl;}


cout<<"}"<<endl;} cout<<endl;}
void bt() void bt(int k)
{//partea fix a algoritmului} {//partea fix a algoritmului}
TU

void main() void main()


{cout<<"n= "; cin>>n; {cout<<"n= "; cin>>n; bt(1);}
bt();}
Observaie. Caracterul escape
'\b' este caracterul Backspace
I

(terge ultimul caracter din ir)


ED
Informatic 19

C
Scriei urmtoarele programe, n care s folosii metoda backtracking pentru
Tem generarea produsului cartezian.
1. Se consider n mulimi de cuvinte Ai, fiecare mulime avnd ni

I
cuvinte. S se genereze toate textele de n cuvinte care se pot forma cu cuvintele din aceste

OG
mulimi, cuvntul i din text aparinnd mulimii Ai.
2. ntr-un restaurant, un meniu este format din trei feluri de mncare. Exist patru
preparate culinare pentru felul unu, cinci preparate culinare pentru felul doi i trei prepa-
rate culinare pentru felul 3. S se genereze toate meniurile care se pot forma cu aceste

AG
preparate culinare.
3. ntr-un restaurant, un meniu este format din trei feluri de mncare. Exist patru preparate
culinare pentru felul unu, cinci preparate culinare pentru felul doi i trei preparate culinare
pentru felul 3. Fiecare preparat culinar are un pre i un numr de calorii. S se genereze
toate meniurile pe care le poate comanda o persoan, care s nu depeasc suma s i

ED
numrul de calorii c. Datele se citesc dintr-un fiier text, astfel: de pe primul rnd suma s i
numrul de calorii, de pe rndul urmtor, n ordine, preul fiecrui preparat culinar, i de pe
ultimul rnd, n aceeai ordine, caloriile fiecrui preparat culinar.

P
4. Pentru o mulime oarecare A, cu n elemente, s se genereze toate submulimile care au
suma elementelor egal cu s. Numrul de elemente ale mulimii, elementele mulimii A
i valoarea pentru suma s se citesc de la tastatur.
I
5. S se afieze toate numerele cu n cifre (1n10) care au proprietatea c sunt formate
numai din cifre pare, n ordine descresctoare.
6. S se afieze toate numerele formate din cifre distincte cu proprietatea c suma
cifrelor este S. Valoarea variabilei S se citete de la tastatur.

7. S se afieze toate secvenele de n litere (n numr natural par, citit de la tastatur)


din mulimea {A,B,C,D}, secvene care se construiesc astfel: nu se aaz dou litere
IC

identice una lng alta i trebuie s se foloseasc exact n/2 litere A.


8. Se citesc de la tastatur un numr natural n (0<n10) i apoi n numere naturale a1,
CT

a2, a3, ..., an. S se afieze pe ecran toate posibilitile de a intercala ntre toate cele n
numere operatorii + i - astfel nct, evalund expresia obinut, de la stnga la
dreapta, la fiecare pas, rezultatul obinut s fie strict pozitiv.
9. S se rezolve n mulimea numerelor naturale ecuaia 4x+3y+2xy=48. Indicaie.
DA

Soluia are 2 elemente: x i y. Ele pot lua valori n intervalul [0,16]. Limita inferioar a
intervalului este 0, pentru c numerele sunt naturale. Limita superioar s-a determinat
considernd, pe rnd, situaiile limit x=0 i y=0. Considerm mulimea A={0,2,3,,16}.
Problema se reduce la generarea produsului cartezian cu condiie AA soluia conine
DI

o condiie intern suplimentar: elementele ei trebuie s verifice ecuaia.


10. Se citesc n cifre distincte i un numr natural x. S se genereze toate numerele care se
pot forma cu aceste cifre i sunt mai mici dect numrul x. De exemplu, pentru cifrele 0,
1 i 3 i numrul x=157, se genereaz 1, 3, 10, 11, 13, 30, 31, 33, 100, 101, 103, 110,
RA

111, 113, 130, 131, 133. Indicaie. Se calculeaz numrul de cifre m ale numrului x.
p
Pentru mulimea A format din cele n cifre, se genereaz produsele carteziene A , cu
1pm. Elementele produsului cartezian sunt cifrele numrului care se formeaz.
Pentru ca un element al produsului cartezian s fie soluie, trebuie ca primul element s
TU

fie diferit de 0 (cifra cea mai semnificativ din numr nu trebuie s fie 0), iar numrul
format cu m cifre s fie mai mic dect numrul x.
11. S se genereze toate numerele naturale, cu cel mult n cifre (n10), care sunt formate
numai din cifre pare, n ordine strict cresctoare.
I
ED
20 Tehnici de programare

C
12. S se genereze toate numerele naturale, cu n cifre, care conin p cifre k. Valorile pentru
n, p i k se citesc de la tastatur.
13. Se citete un numr natural n. S se genereze toate numerele naturale care, reprezen-

I
tate n baza 2, au acelai numr de cifre de 0 i acelai numr de cifre de 1 ca i

OG
reprezentarea n baza 2 a numrului n.
14. Pe un bilet exist 12 poziii care pot fi perforate, aranjate pe 4 linii i 3 coloane. S se
genereze toate posibilitile de perforare a celor 12 poziii, astfel nct s nu existe dou
poziii alturate neperforate. Indicaie. Considerm mulimea A, format din 12 elemente,

AG
fiecare element reprezentnd o poziie care poate fi perforat, i mulimea B={0,1}. Se
definete funcia f:AB astfel: dac poziia i este perforat, atunci f(i)=1; altfel, f(i)=0.
12
Problema se reduce la generarea produsului cartezian B soluia conine o condiie
intern suplimentar: poziia k care se adaug, nu trebuie s fie neperforat (nu trebuie

ED
s aib valoarea 0) dac poziia k-1 sau poziia k-3 este neperforat (are valoarea 0).
1.3.3.3. Generarea aranjamentelor
Se genereaz toate aranjamentele de m elemente ale mulimii {1, 2, 3, , n}.

P
O soluie a problemei va fi un aranjament i va avea m elemente. Fa de algoritmul
pentru generarea permutrilor, se modific doar condiia prin care se verific dac s-au
obinut toate elementele soluiei.
I
Implementarea iterativ Implementarea recursiv
#include<iostream.h> #include<iostream.h>
typedef int stiva[100]; typedef int stiva[100];

int n,m,k,ev,as; int n,m;


stiva st; stiva st;
IC

void init() void init(int k)


{st[k]=0;} {st[k]=0;}
int succesor() int succesor(int k)
CT

{if (st[k]<n) {if (st[k]<n)


{st[k]=st[k]+1; return 1;} {st[k]=st[k]+1; return 1;}
else return 0;} else return 0;}
DA

int valid() int valid(int k)


{for(int i=1;i<k;i++) {for(int i=1;i<k;i++)
if (st[k]==st[i]) return 0; if (st[k]==st[i]) return 0;
return 1;} return 1;}
DI

int solutie() int solutie(int k)


{return k==m;} {return k==m;}
void tipar() void tipar()
{for(int i=1;i<=m;i++) {for(int i=1;i<=m;i++)
RA

cout<<st[i]<<" "; cout<<st[i]<<" ";


cout<<endl;} cout<<endl;}
void bt() void bt(int k)
{//partea fix a algoritmului} {//partea fix a algoritmului}
TU

void main() void main()


{cout<<"n= "; cin>>n; {cout<<"n= "; cin>>n;
cout<<"m= "; cin>>m; bt();} cout<<"m= "; cin>>m; bt(1);}
I
ED
Informatic 21

C
Algoritmul de generare a aranjamentelor poate fi folosit i n alte
probleme. De exemplu, pentru generarea tuturor funciilor injective. Soluia Afiarea
12 x 12
Se genereaz toate funciile injective f:AB, unde card(A)=m i

I
f(x) 1 2

OG
card(B)=n. Pentru simplificarea algoritmului vom considera muli-
mile A={1,2,3,,m} i B={1,2,3,,n}. O soluie este format din m 13 x 12
elemente. Elementul k al soluiei reprezint valoarea funciei f(k). f(x) 1 3
Deoarece valoarea funciei f(k) aparine mulimii B, n stiv se vor
21 x 12
genera numere din mulimea {1,2,3,,n}. Din definiia funciei

AG
f(x) 2 1
injective, f(i)f(j), pentru orice ij. Rezult c, pentru ca funcia s
fie injectiv, trebuie ca mn. Problema se reduce la generarea n 23 x 12
stiv a tuturor aranjamentelor de n elemente luate cte m. Soluiile f(x) 2 3
vor fi afiate sub forma tabelului de variaie al funciei. De 31 x 12

ED
exemplu, dac A={1,2} i B={1,2,3}, soluiile i modul n care vor fi f(x) 3 1
afiate sunt prezentate alturat.
Fa de programul anterior, nu se va modifica dect subprogramul 32 x 12
de afiare a soluiilor tipar(). f(x) 32

P
void tipar()
{int i; cout<<" x | ";
I
for (i=1;i<=m;i++) cout<<i<<" "; cout<<endl;
for (i=1;i<=m;i++) cout<<"-----"; cout<<endl<<"f(x)| ";
for (i=1;i<=m;i++) cout<<st[i]<<" "; cout<<endl<<endl;}
...

void main()
{cout<<"numarul de elemente ale multimii A= "; cin>>m;
IC

cout<<"numarul de elemente ale multimii B= "; cin>>n; bt();}


Scriei urmtoarele programe, n care s folosii metoda backtracking pentru
Tem generarea tuturor aranjamentelor.
CT

1. S se genereze toate posibilitile de aranjare pe m scaune a n per-


soane (mn). Valorile pentru n i m i numele persoanelor se citesc dintr-un fiier text.
2. Se citesc de la tastatur n cifre distincte. S se genereze toate numerele de m cifre
(mn) care se pot forma cu aceste cifre i care conin toate cele n cifre.
DA

3. S se genereze toate anagramele unui cuvnt, din care se elimin p litere oarecare.
Valoarea minim a numrului p este 1, iar valoarea maxim este cu 1 mai mic dect
lungimea cuvntului. Se citesc de la tastatur cuvntul i valoarea numrului p.
4. Se citesc de la tastatur n caractere distincte. S se genereze toate cuvintele de m carac-
DI

tere (mn) care se pot forma cu aceste caractere i care conin toate cele n caractere.
5. Se citete un numr n care are m cifre. S se genereze toate numerele, cu cel mult m
cifre, care se pot forma cu cifrele numrului iniial.
RA

6. Dintr-o mulime de n persoane, aranjate ntr-un ir, se elimin p persoane. S se genereze


toate posibilitile de aranjare ntr-un ir a persoanelor rmase, astfel nct fiecare persoan
s nu aib aceiai vecini ca n irul iniial. Valorile pentru n i p se citesc de la tastatur.
7. S se genereze toate aranjamentele, de m numere, ale unei mulimi de n numere oarecare
TU

astfel nct suma elementelor generate s fie egal cu s. Numrul de elemente ale mulimii,
n, elementele mulimii, valoarile pentru m i pentru suma s, se citesc de la tastatur.
8. S se genereze toate drapelele cu trei culori care se pot forma cu ase culori: alb, gal-
ben, rou, verde, albastru i negru, care au n mijloc culoarea alb, verde sau rou.
I

Indicaie. Soluia are 3 elemente, un element al soluiei fiind indicele din vector al unei
ED
22 Tehnici de programare

C
culori. Se genereaz aranjamente cu condiie de 6 obiecte luate cte 3 soluia conine o
condiie intern suplimentar fa de cea impus de aranjamente: elementul 2 al soluiei
trebuie s fie indicele culorii alb, verde sau rou.

I
9. Se consider n cuburi. Fiecare cub i are latura Li i culoarea ci. S se construiasc toate

OG
turnurile stabile, formate cu m cuburi, astfel nct dou cuburi vecine n turn s nu aib
aceeai culoare. Valorile pentru n i m i atributele celor n cuburi se citesc de la tastatur.
Indicaie. Informaiile despre cuburi se memoreaz ntr-un vector de nregistrri cu n ele-
mente. Soluia are m elemente. Un element al soluiei este indicele din vector al unui cub.

AG
Se genereaz aranjamente cu condiie de n obiecte luate cte m soluia conine o
condiie intern suplimentar fa de cea impus de aranjamente: cubul k care se adaug
la turn trebuie s aib latura mai mic dect a cubului k-1 i culoarea diferit de acesta.

ED
1.3.3.4. Generarea combinrilor
Se genereaz toate combinrile de m elemente ale mulimii {1, 2, 3, , n}.
O soluie a problemei va fi o combinare i va avea m elemente. Fa de algoritmul pentru

P
generarea aranjamentelor, apare o condiie suplimentar: aceea ca soluiile obinute s fie
distincte, adic dou soluii s nu conin aceleai numere. Pentru aceasta, se va aduga o
condiie de continuare suplimentar: valoarea de pe nivelul k trebuie s fie strict mai
I
mare dect oricare dintre valorile de pe nivelele inferioare. Altfel spus, elementele soluiei
trebuie s fie ordonate: st[1]<st[2]< ... <st[k-1]<st[k]. Condiia de continuare este ndeplini-
t dac elementul de pe nivelul k va avea o valoare strict mai mare dect valoarea elemen-
tului de pe nivelul k-1 (se iniializeaz cu o valoare egal cu cea a elementului de pe nivelul

k-1) i o valoare mai mic dect n-m+k (se caut succesorul pn la valoarea n-m+k).
IC

Implementarea iterativ Implementarea recursiv


#include<iostream.h> #include<iostream.h>
typedef int stiva[100]; typedef int stiva[100];
CT

int n,m,k,ev,as; int n,m;


stiva st; stiva st;
void init() void init(int k)
{if (k==1) st[k]=0; { if (k==1) st[k]=0;
DA

else st[k]=st[k-1];} else st[k]=st[k-1];}


int succesor() int succesor(int k)
{if (st[k]<n-m+k) {if (st[k]<n-m+k)
{st[k]=st[k]+1; return 1;} {st[k]=st[k]+1; return 1;}
DI

else return 0;} else return 0;}


int valid() {return 1;} int valid() {return 1;}
int solutie() int solutie(int k)
{return k==m;} {return k==m;}
RA

void tipar() void tipar()


{for(int i=1;i<=m;i++) {for(int i=1;i<=m;i++)
cout<<st[i]<<" "; cout<<st[i]<<" ";
cout<<endl;} cout<<endl;}
TU

void bt() void bt(int k)


{//partea fix a algoritmului} {//partea fix a algoritmului}
void main() void main()
{cout<<"n= "; cin>>n; {cout<<"n= "; cin>>n;
I
ED

cout<<"m= "; cin>>m; bt();} cout<<"m= "; cin>>m; bt(1);}


Informatic 23

C
Algoritmul de generare a combinrilor poate fi folosit n problemele de generare a
tuturor posibilitilor de a forma din n obiecte grupuri de m obiecte care s aib
anumite proprieti. De exemplu, din n obiecte trebuie s se distribuie unei persoane m

I
obiecte, care s conin obligatoriu obiectul p i s nu conin obiectul q. S se genereze

OG
toate posibilitile de a forma grupuri de m astfel de obiecte. Pentru simplificare vom
considera mulimea obiectelor ca fiind {1, 2, 3, , n}. Valorile pentru numrul de obiecte
n, numrul de obiecte din grup, m, i indicii obiectelor p i q se citesc de la tastatur.
Deoarece obiectul p face parte obligatoriu din grupul de obiecte, el va fi memorat ca prim

AG
element al soluiei (st[1]=p), iar subprogramul bt() va genera numai urmtoarele m-1
elemente ale soluiei. Se modific i condiia de continuare a construirii soluiei (subpro-
gramul valid()), deoarece obiectele p i q nu pot fi elemente ale soluiei.
#include<iostream.h>

ED
typedef int stiva[100];
int n,m,p,q,k,ev,as;
stiva st;
void init() {if (k==2) st[k]=0; else st[k]=st[k-1];}

P
int succesor() {//la fel ca n exemplul anterior}
int valid()
I
{return st[k]!=p && st[k]!=q;}
int solutie() {//la fel ca n exemplul anterior}
void tipar() {//la fel ca n exemplul anterior}
void bt()

{k=2;init();
while (k>1)
IC

//la fel ca n exemplul anterior}


void main()
{cout<<"n= "; cin>>n; cout<<"m= "; cin>>m;
CT

cout<<"p= "; cin>>p; cout<<"q= "; cin>>q;


st[1]=p; bt();}
Scriei urmtoarele programe, n care s folosii metoda backtracking pentru
DA

Tem generarea tuturor combinrilor.


1. S se genereze toate grupurile de p persoane care se pot forma din n
persoane. Informaiile se citesc dintr-un fiier text unde, pe primul rnd, sunt scrise
valorile pentru p i n, desprite printr-un spaiu, iar pe urmtoarele rnduri numele
DI

persoanelor, cte un nume pe un rnd.


2. Dou persoane i mpart n obiecte astfel: prima persoan ia m obiecte, iar cealalt
persoan restul obiectelor. S se genereze toate posibilitile de distribuire a celor n
obiecte ntre cele dou persoane.
RA

3. Dou persoane i mpart n obiecte. Fiecare obiect are o valoare vi. S se genereze
toate posibilitile de distribuire a celor n obiecte, ntre cele dou persoane, astfel nct
fiecare persoan s primeasc obiecte, care s aib aceeai valoare total.
4. Dou persoane i mpart n obiecte astfel: prima persoan ia m obiecte, iar cealalt
TU

persoan, restul obiectelor. Fiecare obiect are o valoare vi. S se genereze toate
posibilitile de distribuire a celor n obiecte, ntre cele dou persoane, astfel nct fiecare
persoan s primeasc obiecte care s aib aceeai valoare total.
I
ED
24 Tehnici de programare

C
5. S se genereze toate numerele binare de n cifre care au m cifre de 0. Indicaie. O
soluie este format din m elemente, un element fiind poziia din numr n care se poate
gsi cifra 0 exceptnd prima poziie.

I
6. Din n obiecte date, s se genereze toate grupurile de m obiecte care ndeplinesc

OG
urmtoarele condiii:
a. conin exact p obiecte precizate;
b. nu conin nici unul din p obiecte precizate;
c. conin numai un obiect din p obiecte precizate;

AG
d. conin cel puin un obiect din p obiecte precizate;
e. conin exact q obiecte din p obiecte precizate;
f. conin exact q obiecte din p obiecte precizate i nu conin r obiecte precizate;
g. conin exact q obiecte din p obiecte precizate i nu conin s obiecte din r obiecte

ED
precizate.

1.3.3.5. Generarea tuturor partiiilor unui numr natural


O partiie a unui numr natural nenul n este o descompunere a nu-

P
4=1+1+1+1 (m=4)
mrului n n sum de m numere naturale nenule. Soluiile care nu 4=1+1+2 (m=3)
difer dect prin ordinea termenilor nu sunt considerate distincte. 4=1+3 (m=2)
I
Alturat sunt prezentate toate partiiile numrului 4. 4=2+2 (m=2)
O soluie a problemei va fi format din m elemente a cror sum este 4=4 (m=1)
egal cu numrul n. Elementele soluiei reprezint termenii unei descompuneri. Numrul de

elemente ale unei soluii (m) este egal cu valoarea vrfului stivei k atunci cnd s-a obinut
soluia. Soluia se obine atunci cnd suma elementelor din stiv este egal cu n. Altfel
IC

spus, soluia se obine atunci cnd suma s=st[1]+st[2]+ ... +st[k-1]+st[k] are valoarea n.
Pentru a evita repetarea aceleiai descompuneri, valoarea de pe nivelul k trebuie s fie mai
mare sau egal cu oricare dintre valorile de pe nivelele inferioare. Altfel spus, elementele
soluiei trebuie s fie ordonate: st[1]st[2] ... st[k-1]st[k]. Aceast condiie este
CT

ndeplinit dac elementul de pe nivelul k va avea o valoare mai mare sau egal cu
valoarea elementului de pe nivelul k-1 (se iniializeaz cu o valoare mai mic cu 1 dect
cea a elementului de pe nivelul k-1) i o valoare mai mic dect diferena dintre numrul n
DA

i suma termenilor descompunerii gsii pn la nivelul k, s=st[1]+st[2]+ ... +st[k-1].


Condiia de continuare este ca suma termenilor generai, s, s fie mai mic sau egal
cu n (sn), o soluie complet obinndu-se atunci cnd s=n. Iniial, suma s are valoarea
0 i ea trebuie actualizat n permanen. Exist dou cazuri de actualizare:
DI

Atunci cnd se adaug n stiv un nou termen, acesta se adaug i la sum. Altfel
spus, dac succesorul gsit poate fi element al soluiei (prin adugarea lui la sum
aceasta nu va depi valoarea numrului n), atunci el se adaug la sum. Actuali-
RA

zarea sumei se va face n subprogramul valid() (termenul se adaug la sum


numai dac face parte din descompunere): s+=st[k].
Atunci cnd se coboar n stiv, trebuie sczute din sum dou valori: valoarea
elementului din vrful stivei (k) i valoarea elementului de pe nivelul precedent (k-1).
TU

Deoarece n stiv se coboar ntotdeauna dup ce s-a obinut o soluie complet i nu


se mai poate gsi un element pentru nivelul k cu care s se continue dezvoltarea
soluiei, scderea din sum a termenului curent se va face dup ce se afieaz o
soluie complet n subprogramul tipar(): s-=st[k], iar scderea din sum a
I
ED
Informatic 25

C
termenului precedent se face n subprogramul succesor(), atunci cnd nu se
gsete succesor pentru elementul din vrful stivei: s-=st[k-1].
Implementarea iterativ Implementarea recursiv

I
OG
#include<iostream.h> #include<iostream.h>
typedef int stiva[100]; typedef int stiva[100];
int n,s=0,k,ev,as; int n,s=0;
stiva st; stiva st;
void init () void init (int k)

AG
{if (k==1) st[k]=0; {if (k==1) st[k]=0;
else st[k]=st[k-1]-1;} else st[k]=st[k-1]-1;}
int succesor() int succesor(int k)
{if (st[k]<n-s) {if (st[k]<n-s)

ED
{st[k]=st[k]+1; return 1;} {st[k]=st[k]+1; return 1;}
else {s-=st[k-1]; return 0;}} else {s-=st[k-1]; return 0;}}
int valid() int valid(int k)
{if (s+st[k]<=n) {if (s+st[k]<=n)

P
{s+=st[k]; return 1;} {s+=st[k]; return 1;}
else return 0;} else return 0;}
int solutie() int solutie(int k)
I
{return s==n;} {return s==n;}
void tipar() void tipar(int k)
{for(int i=1;<k;i++) {for(int i=1;<k;i++)

cout<<st[i]<<"+ "; cout<<st[i]<<"+ ";


cout<<st[k]<<endl; cout<<st[k]<<endl;
IC

s-=st[k];} s-=st[k];}
void bt() void bt(int k)
{//partea fix a algoritmului} {//partea fix a algoritmului}
CT

void main() void main()


{cout<<"n= "; cin>>n; bt();} {cout<<"n= "; cin>>n; bt(1);}
Algoritmul de generare a tuturor partiiilor unui numr natural poate fi folosit i n alte
DA

probleme. De exemplu, generarea tuturor posibilitilor de plat a unei sume cu


bancnote de valori date.
Problema se reduce la generarea tuturor partiiilor unui nu- 25 = 5+5+5+5+5 (m=5)
mr natural nenul suma, o partiie fiind o descompunere a 25 = 5+5+5+10 (m=4)
DI

numrului suma n sum de m numere naturale, nenule, cu 25 = 5+10+10 (m=3)


valori aparinnd mulimii A={a1,a2, , an}. Alturat, sunt
prezentate toate partiiile sumei 25 pentru bancnote cu valori aparinnd mulimii A={5,10}.
RA

Fa de problema anterioar, apar urmtoarele modificri:


Deoarece suma suma se descompune n valori precizate, aparinnd mulimii A,
aceste valori se memoreaz n vectorul a, care are lungimea logic n (numrul de
valori ale bancnotelor).
Un element al soluiei este indicele valorii bancnotei din vectorul a, adic un element
TU

din mulimea {1,2, , n}.


O soluie a problemei va fi format din m elemente, alese astfel nct suma valorilor
bancnotelor corespunztoare lor s fie egal cu numrul suma. Altfel spus, soluia se
I

obine atunci cnd suma s=a[st[1]]+a[st[2]]+ ... + a[st[k-1]]+ a[st[k]] are valoarea suma.
ED
26 Tehnici de programare

C
Condiia de continuare este ca suma valorilor termenilor generai, s, s fie mai mic
sau egal cu suma (ssuma), o soluie complet obinndu-se atunci cnd s=suma.
Atunci cnd se urc n stiv, se adun la sum valoarea bancnotei cu indicele k:

I
s+=a[st[k]], iar cnd se coboar n stiv, se scade din sum valoarea bancnotei

OG
cu indicele k: s-=a[st[k]] i valoarea bancnotei cu indicele k-1: s+=a[st[k-1]].
Deoarece este posibil ca pentru anumite valori ale sumei suma i ale valorilor
bancnotelor s nu existe nici o soluie, se folosete variabila de tip logic este, care
are valoarea 1 (true), dac exist cel puin o soluie, i 0 (false), n caz contrar.

AG
#include<iostream.h>
typedef int stiva[100];
int n,k,ev,as,s=0,suma,este=0,a[10];
stiva st;

ED
void init ()
{if (k==1) st[k]=0;
else st[k]=st[k-1]-1;}
int succesor()

P
{if (st[k]<n) {st[k]=st[k]+1; return 1;}
else {s-=a[st[k-1]]; return 0;}}
int valid()
I
{if (s+a[st[k]]<=suma) {s+=a[st[k]]; return 1;}
else return 0;}
int solutie()

{return s==suma;}
void tipar()
IC

{int i,j,p,este=1;
for (i=1;i<=n;i++)
{for(j=1,p=0;j<=k;j++) if (i==st[j]) p++;
CT

if (p!=0) cout<<p<<"*"<<a[i]<<" + ";}


cout<<'\b'<<'\b'<<" "<<endl; s-=a[st[k]];}
void bt() {//partea fix a algoritmului }
void main()
DA

{cout<<"n= "; cin>>n;


for (int i=1;i<=n;i++)
{cout<<"Valoare bancnota "<<i<<": "; cin>>a[i];}
cout<<"suma= "; cin>>suma; bt();
DI

if (!este) cout<<"Imposibil"; }
Scriei urmtoarele programe, n care s folosii metoda backtracking pentru
Tem generarea tuturor partiiior unui numr natural.
RA

1. S se genereze toate descompunerile unui numr natural n n


numere naturale distincte.
2. S se genereze toate descompunerile unui numr natural n n numere prime.
3. S se genereze toate descompunerile unui numr natural n n sum de 3 i 5.
TU

4. O bar are lungimea L. Se consider n repere de lungimi diferite. S se genereze toate


posibilitile de a tia bara dup reperele existente, fr s rmn rest la tiere, un
reper putnd fi folosit de mai multe ori. Se poate ca unele repere s nu fie folosite Se
citesc dintr-un fiier text, de pe primul rnd, lungimea barei L i numrul de repere n,
I

iar de pe urmtorul rnd, reperele. Numerele de pe un rnd sunt separate prin spaiu.
ED
Informatic 27

C
5. Pentru realizarea unui chestionar exist n ntrebri, fiecare ntrebare avnd un punctaj.
Numrul de ntrebri i punctajul fiecrei ntrebri se citesc dintr-un fiier text. S se
genereze toate chestionarele care au ntre a i b ntrebri distincte i un punctaj total

I
ntre p i q puncte. Valorile pentru a, b, p i q se citesc de la tastatur.

OG
6. S se gseasc modalitatea de plat a unei sume cu un numr minim de bancnote cu valori
date.

1.3.3.6. Generarea tuturor partiiilor unei mulimi

AG
O partiie a unei mulimi A este format din mulimile nevide disjuncte Ai a cror reuniune
m
este mulimea A: A i A i A i A j pentru orice i,j = 1m.
i 1

ED
Pentru simplificarea algoritmului vom considera mulimea A={1,2,3, ,n}. O partiie va fi
format din m mulimi, cu 1mn. Soluia va fi memorat n stiv i va avea n elemente,
fiecare element k al soluiei reprezentnd mulimea i (1in) creia i aparine elementul k din
mulimea care se partiioneaz: st[k]=i nseamn c elementul k din mulimea A face parte

P
din mulimea i a partiiei. n cadrul unei partiii nu intereseaz ordinea n care apar elementele
mulimii A. Cel mai mare numr care va fi generat n stiv reprezint numrul de mulimi m n
I
care a fost descompus mulimea A. n plus, numerele generate n stiv trebuie s aparin
unei mulimi de numere consecutive care ncepe cu 1, deoarece
partiia nu conine mulimi vide. Alturat, sunt prezentate toate Partiiile Stiva
partiiile mulimii {1,2,3} i coninutul stivei pentru fiecare dintre ele. n {1, 2, 3} 111

exemplu, nu exist soluia 1 3 3 deoarece aceste valori nu aparin {1, 2} {3} 112
unei mulimi de numere consecutive (nu se poate ca un element din {1, 3} {2 } 121
IC

{1} {2, 3 } 122


mulimea A s aparin mulimii A1, i alte dou elemente mulimii {1} {2} {3 } 123
A3, deoarece ar nsemna c mulimea A2 este vid).
CT

Condiia de continuare este asigurat prin modul n care este ales succesorul st[k]k,
ceea ce nseamn c elementul k din mulimea A nu poate aparine dect unei partiii al crei
numr este mai mic sau cel mult egal cu numrul de ordine al elementului. Altfel spus, dac
pn la nivelul k numrul maxim atribuit pentru o partiie este i, acest numr reprezentnd
DA

numrul de mulimi ale partiiei care exist n soluia parial, pe nivelul k+1 elementul poate
avea una dintre urmtoarele valori:
Orice valoare de la 1 la i, ceea ce nseamn c elementul k+1 din mulimea A se
adaug la una dintre mulimile care exist deja.
DI

Valoarea i+1, ceea ce nseamn c elementul k+1 din mulimea A va genera o nou
mulime n partiie.
Implementarea iterativ Implementarea recursiv
RA

#include<iostream.h> #include<iostream.h>
typedef int stiva[100]; typedef int stiva[100];
int n,k,ev,as; int n;
stiva st; stiva st;
TU

void init() {st[k]=0;} void init (int k) {st[k]=0;}


int succesor() int succesor(int k)
{if (st[k]<st[k-1]+1) {if (st[k]<st[k-1]+1)
{st[k]=st[k]+1; return 1;} {st[k]=st[k]+1;return 1;}
I

else return 0;} else return 0;}


ED
28 Tehnici de programare

C
int valid() {return 1;} int valid() {return 1;}
int solutie() int solutie(int k)
{return k==n;} {return k==n;}

I
void tipar() void tipar()

OG
{int i,j,max=st[1]; {int i,j,max=st[1];
for(i=2;i<=n;i++) for(i=2;i<=n;i++)
if (st[i]>max) max=st[i]; if (st[i]>max) max=st[i];
for (i=1;i<=max;i++) for (i=1;i<=max;i++)

AG
{cout<<"{"; {cout<<"{";
for (j=1;j<=n;j++) for (j=1;j<=n;j++)
if (st[j]==i) cout<<j<<","; if (st[j]==i) cout<<j<<",";
cout<<'\b'<<"} ";} cout<<'\b'<<"} ";}

ED
cout<<endl;} cout<<endl;}
void bt() void bt(int k)
{//partea fix a algoritmului} {//partea fix a algoritmului}
void main() void main()

P
{cout<<"n= "; cin>>n; bt();} {cout<<"n= "; cin>>n; bt(1);}
Scriei urmtoarele programe, n care s folosii metoda backtracking pentru
Tem generarea tuturor partiiilor unei mulimi. Se consider mulimea A, cu n
I
numere ntregi. Valorile pentru n i m i pentru elementele mulimii A se
citesc de la tastatur.
1. S se genereze toate partiiile mulimii A formate din dou submulimi care au suma

elementelor egale.
2. S se genereze toate partiiile mulimii A formate din m submulimi.
IC

3. S se genereze toate partiiile mulimii A formate din submulimi care au acelai numr
de elemente.
CT

1.3.3.7. Generarea tuturor funciilor surjective


Se genereaz toate funciile surjective f:AB unde card(A)=m i
Soluia Afiarea
card(B)=n. Pentru simplificarea algoritmului vom considera muli-
112 x 123
DA

mile A={1,2,3,,m} i B={1,2,3,,n}. O soluie este format din m


f(x) 1 1 2
elemente. Elementul k al soluiei reprezint valoarea funciei: f(k).
Deoarece valoarea funciei f(k) aparine mulimii B, n stiv se vor 121 x 123
genera numere din mulimea {1,2,3,,n}. Din definiia funciei f(x) 1 2 1
DI

surjective, trebuie ca, pentru orice jB, s existe iA, astfel nct
122 x 123
f(i)=j. Rezult c pentru ca funcia s fie surjectiv trebuie ca
f(x) 1 2 2
nm. Problema se reduce la generarea n stiv a tuturor elemen-
m 211 x 123
telor produsului cartezian B din care vor fi considerate soluii
RA

numai cele care conin toate elementele din mulimea B. Soluiile f(x) 2 1 1
vor fi afiate sub forma tabelului de variaie a funciei. De 221 x 123
exemplu, dac A={1,2,3} i B={1,2}, soluiile i modul n care vor fi f(x) 2 2 1
afiate sunt prezentate alturat.
TU

212 x 123
Condiia de continuare este asigurat prin modul n care este ales f(x) 2 1 2
succesorul ca element din mulimea B, singurul caz special fiind al
elementului care se adaug pe ultimul nivel din stiv (m). Prin adu- 221 x 123
I

garea acestui element, trebuie ca n stiv s existe toate elementele f(x) 2 2 1


ED
Informatic 29

C
mulimii B. Aceast condiie este verificat prin funcia surjectiva() care furnizeaz un
rezultat logic: 1 (true), dac n stiv exist toate cele n elemente ale mulimii B, i 0 (false), n
caz contrar.

I
Implementarea iterativ Implementarea recursiv

OG
#include<iostream.h> #include<iostream.h>
typedef int stiva[100]; typedef int stiva[100];
int n,m,k,ev,as; int n,m;
stiva st; stiva st;

AG
int surjectiva() int surjectiva()
{int i,j,x; {int i,j,x;
for (j=1;j<=n;j++) for (j=1;j<=n;j++)
{for (i=1,x=0;i<=m && !x;i++) {for (i=1,x=0;i<=m && !x;i++)

ED
if (st[i]==j) x=1; if (st[i]==j) x=1;
if (!x) return 0;} if (!x) return 0;}
return 1;} return 1;}
void init() {st[k]=0;} void init (int k) {st[k]=0;}

P
int succesor() int succesor(int k)
{if (st[k]<st[k-1]+1) {if (st[k]<st[k-1]+1)
{st[k]=st[k]+1; return 1;} {st[k]=st[k]+1;return 1;}
I
else return 0;} else return 0;}
int valid() int valid(int k)
{if (k==m) {if (k==m)
if (!surjectiva()) return 0; if (!surjectiva()) return 0;

return 1;} return 1;}


IC

int solutie() int solutie(int k)


{return k==m;} {return k==n;}
void tipar() void tipar()
CT

{int i; cout<<" x | "; {int i; cout<<" x | ";


for (i=1;i<=m;i++) cout<<i<<" "; for (i=1;i<=m;i++) cout<<i<<" ";
cout<<endl; cout<<endl;
for (i=1;i<=m;i++) cout<<"-----"; for (i=1;i<=m;i++) cout<<"-----";
DA

cout<<endl<<"f(x)| "; cout<<endl<<"f(x)| ";


for (i=1;i<=m;i++) cout<<st[i]<<" "; for (i=1;i<=m;i++) cout<<st[i]<<" ";
cout<<endl<<endl;} cout<<endl<<endl;}
void bt() void bt(int k)
DI

{//partea fix a algoritmului} {//partea fix a algoritmului}


void main() void main()
{cout<<"elemente multimea A= "; {cout<<"elemente multimea A= ";
cin>>m; cin>>m;
RA

cout<<"elemente multimea B= "; cout<<"elemente multimea B= ";


cin>>n; bt();} cin>>n; bt(1);}
Scriei urmtoarele programe, n care s folosii metoda backtracking pentru
TU

Tem generarea tuturor funciilor surjective.


1. Se citesc de la tastatur n cifre distincte. S se genereze toate nu-
merele de m cifre (nm) care se pot forma cu aceste cifre i care conin toate cele n cifre.
2. Se citesc de la tastatur n caractere distincte. S se genereze toate cuvintele de m carac-
I

tere (nm) care se pot forma cu aceste caractere i care conin toate cele n caractere.
ED
30 Tehnici de programare

C
3. Profesorul de informatic a pregtit m teme, pentru proiecte pe care trebuie s le repar-
tizeze celor n elevi din clas (mn), astfel nct nici o tem de proiect s nu rmn
nerepartizat. S se genereze toate soluiile de repartizare a temelor pentru proiect.

I
4. O bar are lungimea L. Se consider n repere de lungimi diferite. S se genereze toate

OG
posibilitile de a tia bara dup reperele existente, fr s rmn rest la tiere, fiecare
reper fiind folosit cel puin o dat. Se citesc dintr-un fiier text, de pe primul rnd,
lungimea barei L i numrul de repere n, iar de pe urmtorul rnd, reperele.
Numerele de pe un rnd sunt separate prin spaiu.

AG
5. S se genereze toate construciile corecte de paranteze ( i ); n este numr par i se
citete de la tastatur. De exemplu, pentru n=6, construciile (())() i ()(()) sunt corecte,
iar construcia ())(() nu este corect. Indicaie. Se genereaz funciile surjective f:AB
unde A = {1,2,3,,n} = mulimea poziiilor ocupate de paranteze, i B = {0,1} = mulimea
parantezelor (=0 i )=1 care ndeplinesc urmtoarele condiii:

ED
f(1)=0 i f(n)=1 (expresia ncepe cu parantez deschis i se termin cu o parantez
nchis).
Numrul de valori 0 ale funciei i numrul de valori 1 ale funciei sunt egale cu n/2

P
(numrul de paranteze deschise este egal cu numrul de paranteze nchise).
n timpul construirii soluiei, nu trebuie ca numrul de valori 1 ale funciei s fie mai mare
dect numrul de valori 0 generate pn la acel moment (numrul de paranteze nchise
I
este ntotdeauna cel mult egal cu numrul de paranteze deschise).

1.3.3.8. Problema celor n dame


Se genereaz toate posibilitile de aranjare, pe o tabl de ah, cu dimensiunea nn, a n


dame care s nu se atace ntre ele. Damele se pot ataca ntre ele pe linie, pe coloan i
IC

pe diagonal.
8
Se observ c fiecare dam trebuie s fie plasat singur
7
pe o coloan, ca s nu se atace ntre ele. Soluia proble-
CT

6
mei este dat de mulimea cu n elemente {x1, x2, , xn}
care se memoreaz n stiv. Elementul soluiei xk 5
reprezint numrul liniei n care se aaz dama din 4
coloana k, i se memoreaz pe nivelul k al stivei st. De 3
DA

exemplu, pentru n=8, o soluie este S={4,8,1,5,7,2,6,3} i 2


damele sunt aranjate pe tabla de ah ca n figura 1
alturat. 1 2 3 4 5 6 7 8
DI

Date fiind coordonatele i,j, de pe tabla de


ah ale poziiei unei dame care a fost
C
aezat anterior (linia i este memorat pe
i+p, k
nivelul j n stiv i=st[j]), ca ea s nu atace
RA

dama care urmeaz s fie pus n coloana k


trebuie s fie ndeplinite urmtoarele
A B
condiii interne:
i,j i,k
Dama din coloana k nu trebuie s se
TU

gseasc pe linia i.
Dama din coloana k nu trebuie s se g-
seasc pe diagonala cu dama din coloa- i-p, k
I

na j, adic triunghiul ABC nu trebuie s


ED

fie isoscel. Pentru ca triunghiul ABC s


Informatic 31

C
nu fie isoscel, condiia pe care trebuie s o ndeplineasc dama din coloana k se
poate exprima astfel: oricare ar fi j<k, xj xk i |xk xj| kj.

I
Aceste condiii interne ale soluiei trebuie s se regseasc n condiia de continuare a

OG
soluiei care se verific n subprogramul valid(): st[j]st[k] i abs(st[k]st[j])kj,
pentru orice jk.
#include<iostream.h>
#include<math.h>
typedef int stiva[100];

AG
int n,k,ev,as;
stiva st;
void init() {st[k]=0;}
int succesor()

ED
{if (st[k]<n) {st[k]=st[k]+1; return 1;}
else return 0;}
int valid()
{for(int i=1;i<k;i++)

P
if (st[k]==st[i] || abs(st[k]-st[i])==k-i) return 0;
return 1;}
int solutie() {return k==n;}
I
void tipar()
{for(int i=1;i<=n;i++) cout<<st[i]<<" "; cout<<endl;}
void bt() {//partea fixa a algoritmului }

void main() {cout<<"n= "; cin>>n; bt();}


S se genereze toate posibilitile de aranjare, pe o tabl de ah, cu
IC

Tem dimensiunea nn, a n nebuni, care s nu se atace ntre ei. Nebunul se


poate deplasa numai pe diagonal.
CT

1.3.3.9. Parcurgerea tablei de ah cu un cal


Se caut toate posibilitile de parcurgere a tablei de ah prin sritura calului, fr a trece
de dou ori prin aceeai poziie. Tabla de ah are dimensiunea nn, iar poziia iniial a
DA

calului este dat de i numrul liniei i j numrul coloanei. Se citesc de la tastatur


valorile pentru n, i i j.
Soluia problemei este dat de mulimea cu nn elemente {x1, x2, , xnn} care se
DI

memoreaz n stiv. Elementul soluiei xk reprezint coordonatele i i j ale ptratului n


care se deplaseaz calul la mutarea k i se memoreaz pe nivelul k al stivei st. Pentru
a nregistra traseul strbtut de cal, elementele stivei vor fi de tip nregistrare cu dou
cmpuri, x i y, corespunztoare celor dou coordonate ale ptratului.
RA

struct element{int x,y;};


typedef element stiva[100];
stiva st;
TU

Stiva va avea dimensiunea nn, corespunztoare parcurgerii ntregii table de ah


(kmax=nn), i va conine, n ordine, coordonatele tuturor ptratelor de pe traseul de
parcurgere: st[1].x i st[1].y corespund primei poziii de pe tabl, st[2].x i
st[2].y corespund celei de a doua poziii de pe tabl, , st[n*n].x i st[n*n].y
I

corespund ultimei poziii de pe tabl.


ED
32 Tehnici de programare

C
De exemplu, pentru n=5 i ca poziie de pornire ptratul de pe linia 1 i coloana 1 o
soluie va avea 25 de elemente. Prima dintre soluiile obinute este prezentat mai jos:

I
Ordinea de ocupare a tablei de ah

OG
Soluia 1 1 16 21 10 25
1,1 3,2 5,1 4,3 5,5 2 20 11 24 15 22
3,4 4,2 5,4 3,5 1,4
2,2 4,1 5,3 4,5 2,4 3 17 2 19 6 9

AG
1,2 3,1 5,2 3,3 2,1
4 12 7 4 23 14
1,3 2,5 4,4 2,3 1,5
5 3 18 13 8 5
1 2 3 4 5

ED
Dat fiind o poziie curent i,j a
traseului, variantele posibile 4 3
pentru urmtoarea poziie a i+2, j-1 i+2, j+1

P
calului pe tabla de ah sunt 5 2
prezentate alturat. i+1, j-2 i+1, j+2
I
Se observ c exist 8 variante i,j
posibile pentru continuarea dru-
mului. Coordonatele urmtoru- 6 1
lui ptrat de pe tabla de ah n i-1, j-2 i-1, j+2

care poate sri calul, pentru 7 8


fiecare dintre cele 8 variante, i-2, j-1 i-2, j+1
IC

sunt prezentate n tabel.


Variant Coordonate Variant Coordonate n vectorul p, de dimensiune nn
se pstreaz varianta care s-a ales
CT

1 i-1, j+2 5 i+1, j-2


2 i+1, j+2 6 i-1, j-2 pentru continuarea drumului. Ele-
3 i+2, j+1 7 i-2, j-1 mentele sale sunt de tip ntreg.
4 i+2, j-1 8 i-2, j+1 Elementul k din vector arat care
DA

dintre cele 8 variante s-a ales


pentru a ajunge de la poziia k-1 la poziia k Orice element k al vectorului trebuie s
ndeplineasc urmtoarea condiie: 1 p [k] 8.
Fiecare dintre cele 8 variante de deplasare din ptratul k-1 n ptratul k nseamn
DI

adugarea unei constante de deplasare la coordonata x, respectiv y, a ptratului k-1.


Aceste constante sunt memorate n vectorul d (pentru varianta 0, care nu exist, depla-
sarea este 0):
RA

element d[9]={{0,0},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1},{-2,1}};
Variabila logic este se folosete pentru a ti dac s-a gsit cel puin o soluie (de
exemplu, pentru n=4 problema nu are soluii). Este iniializat cu valoarea 0 (nu s-a gsit
nc nici o soluie). Va lua valoarea 1 (s-a gsit o soluie) n subprogramul tipar() care
TU

se execut numai dac s-a gsit o soluie a problemei.


Subprogramele
Subprogramul init(). Se iniializeaz varianta cu care se trece din ptratul k-1 n
I

ptratul k, adic elementul k din vectorul p: p[k]=0.


ED
Informatic 33

C
Subprogramul succesor(). Se consider c mai exist o posibilitate de continuare a
construirii soluiei pe nivelul k dac mai exist o variant de mutare din ptratul k-1 n
ptratul k, adic dac p[k]<8. Dac mai exist o variant de mutare, pe nivelul k din

I
stiv, se trece la aceast variant (p[k]=p[k]+1) i se nregistreaz coordonatele

OG
ptratului k, care se vor obine prin adugarea, la coordonatele ptratului k-1, a
deplasrilor corespunztoare acestei variante (st[k].x=st[k-1].x+d[p[k]].x i
st[k].y=st[k-1].y+d[p[k]].y).
Subprogramul valid(). Se consider c ptratul k n care s-a ajuns poate fi conside-

AG
rat c este bun pentru a continua construirea soluiei, dac coordonatele sale nu sunt
n afara tablei de ah (coordonatele st[k].x i st[k].y iau valori n intervalul [1,n])
i prin ptratul k nu s-a mai trecut (se verific dac n stiv, pe nivelurile anterioare, nu
mai exist un ptrat cu coordonatele ptratului k).
Subprogramul soluie(). Se verific dac a fost parcurs toat tabla de ah, adic

ED
dac vrful stivei k are valoarea n*n.
Subprogramul bt(). Deoarece coordonatele primului ptrat nu trebuie modificate,
primului element al soluiei (k=1) i se atribuie coordonatele n subprogramul main(),

P
iar n subprogram se va ncepe cu iniializarea nivelului 2 din stiv (k=2); cutarea
tuturor soluiilor se va face pn cnd vrful stivei coboar pn la primul element al
soluiei: while (k>1).
I
#include<iostream.h>
struct element{int x,y;};
element d[9]={{0,0},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1},{-2,1}};

int n,k,ev,as,p[100],este=0;
typedef element stiva[100];
IC

stiva st;
void init() {p[k]=0;}
int succesor()
CT

{if (p[k]<8)
{p[k]=p[k]+1; st[k].x=st[k-1].x+d[p[k]].x;
st[k].y=st[k-1].y+d[p[k]].y; return 1;}
else return 0;}
DA

int valid()
{if (st[k].x<1 || st[k].y<1 || st[k].x>n || st[k].y>n) return 0;
for (int i=1;i<k;i++)
if (st[k].x==st[i].x && st[k].y==st[i].y) return 0;
DI

return 1;}
int solutie() {return k==n*n;}
void tipar()
{int i; este=1;
RA

for (i=1;i<=n*n;i++) cout<<st[i].x<<","<<st[i].y<<" ";


cout<<endl;}
void bt()
{k=2; init();
TU

while (k>1)
{as=1; ev=0;
while(as && !ev)
I

{as=succesor();
ED

if(as) ev=valid();}
34 Tehnici de programare

C
if(as)
if(solutie()) tipar();
else {k++; init();}

I
else k--;}}

OG
void main()
{int i,j; cout<<"n= "; cin>>n;
cout<<"linia de pornire "; cin>>i; st[1].x=i;
cout<<"coloana de pornire "; cin>>j; st[1].y=j; bt();

AG
if (!este) cout<<"Nu exista solutii";}
Observaie. Dac se dorete numai afiarea primei soluii, cutarea soluiei se face
pn cnd variabila este trece de la valoarea 0 (nu s-a gsit soluie) la valoarea 1 (s-a
gsit soluie), modificndu-se n subprogramul bt() condiia de terminare a cutrii tuturor

ED
soluiilor (n loc de while (k>1) se va scrie while (k>1 && !este)) .

S se genereze toate posibilitile de aranjare pe o tabl de ah, cu


Tem dimensiunea nn, a n cai care s nu se atace ntre ei.

P
1.3.3.10. Generarea tuturor soluiilor de ieire din labirint
I
Se caut toate posibilitile unui traseu printr-un labirint, ntre dou poziii, iniial i final,
fr a se trece de dou ori prin aceeai poziie. Labirintul are dimeniunea nm. Poziia
iniial este dat de x1 numrul liniei i y1 numrul Plecare

coloanei care se comunic de la tastatur. Poziia final


corespunztoare ieirii din labirint este dat de x2 numrul
liniei i y2 numrul coloanei care vor fi determinate n
IC

urma gsirii traseului. Deplasarea n labirint se poate face


numai ortogonal (pe vertical i orizontal), nu i pe diagonal.
CT

Soluia problemei este dat de mulimea cu t elemente {x1, x2,


, xt} care se memoreaz n stiv. Numrul de elemente ale
soluiei depinde de soluia gsit. Elementul soluiei xk repre-
zint coordonatele i i j ale ptratului n care se deplaseaz o
DA

persoan n labirint i se memoreaz pe nivelul k al stivei st. Sosire


Pentru a nregistra traseul strbtut, elementele stivei vor fi de
tip nregistrare cu dou cmpuri, x i y, corespunztoare celor dou coordonate ale
ptratului. Stiva va avea dimensiunea t
DI

corespunztoare parcurgerii ntregului traseu,


de la ptratul de plecare pn la ptratul de 1 Nord
sosire, i va conine, n ordine, coordonatele i-1, j
RA

tuturor ptratelor de pe traseul de parcurgere:


st[1].x i st[1].y corespund ptratului de Vest Est
plecare, st[2].x i st[2].y corespund celui 4 i,j 2
de al doilea ptrat n care se trece, , i, j-1 i, j+1
TU

st[t].x i st[t].y corespund ptratului de


sosire, prin care se iese din labirint. 3
Dat fiind o poziie curent i,j a traseului, i+1, j Sud
variantele posibile pentru urmtoarea poziie
I

sunt prezentate alturat.


ED
Informatic 35

C
Se observ c exist 4 variante posibile pentru continuarea drumului. Coordonatele
urmtorului ptrat de pe traseu n care poate s treac persoana, pentru fiecare dintre
cele 8 variante, sunt prezentate n tabel.

I
n vectorul p, de dimensiune nm, se pstreaz varianta

OG
Variant Coordonate
care s-a ales pentru continuarea drumului. Elementele sale
1 i+1, j sunt de tip ntreg. Elementul k din vector arat care dintre
2 i, j+1
cele 4 variante s-a ales pentru a ajunge de la poziia k-1 la
3 i+1, j
poziia k Orice element k al vectorului trebuie s nde-
4 i, j-1

AG
plineasc urmtoarea condiie: 1 p [k] 4.
Fiecare dintre cele 4 variante de deplasare din ptratul k-1 n ptratul k nseamn
adugarea unei constante de deplasare la coordonata x, repsectiv y, a ptratului k-1.
Aceste constante sunt memorate n vectorul d (pentru varianta 0, care nu exist,

ED
deplasarea este 0):
element d[5]={{0,0},{-1,0},{0,1},{1,0},{0,-1}};
Deoarece din ptratul k-1 se poate trece n ptratul k, gsit pe una dintre cele patru

P
direcii de deplasare numai dac cele dou ptrate comunic (exist un culoar ntre ele)
trebuie gsit o metod de descriere a labirintului printr-o matrice L cu dimensiunea nm.
Vor fi prezentate dou metode de reprezentare a labirintului.
I
Varianta 1 Nord: cale blocat;
Fiecare element al matricei L corespunde a patra cifr: 0
unui ptrat din labirint i memoreaz infor-

maii despre micrile care pot fi executate


n ptrat. Fiecrui ptrat i se atribuie un ir Vest: Est:
IC

de patru cifre binare, care va fi construit cale liber; cale liber;


dup urmtoarele reguli: prima cifr: 1 a treia cifr: 1
prima cifr: are valoarea 1, dac se
CT

poate executa un pas spre Vest;


a doua cifr: are valoarea 1, dac se
poate executa un pas spre Sud; Sud: cale blocat;
a treia cifr: are valoarea 1, dac se a doua cifr: 0
DA

poate executa un pas spre Est;


a patra cifr: are valoarea 1, dac se poate executa un pas spre Nord.
Pentru ptratul din exemplu este Elementul matricei corespunztor ptratului
DI

prezentat alturat valoarea ele- 1 0 1 0


mentului care i se asociaz n ma-
tricea L. irul de patru cifre binare prima cifr a patra cifr
formeaz un numr binar, care va fi a doua cifr a treia cifr
RA

transformat ntr-un numr zecimal.

0011 1110 1010 1010 1010 1010 1100 0100 3 14 10 10 10 10 12 4


0100 0101 0010 1010 1010 1100 0111 1001 4 5 2 10 10 12 7 9
TU

0101 0111 1010 1010 1100 0101 0011 1100 5 7 10 10 12 5 3 12


0111 1001 0010 1100 0101 0011 1110 1001 7 9 2 12 5 3 14 9
0111 1110 1000 0101 0111 1100 0011 1000 7 14 8 5 7 10 3 8
0111 1001 0010 1101 0111 1011 1010 1000 7 9 2 13 7 11 10 8
I

0011 1000 0010 1011 1011 1010 1010 1100 3 8 2 11 11 10 10 12


ED
36 Tehnici de programare

C
Pentru a simplifica verificarea condiiei de ieire din labirint, matricea L este bordat cu o
valoare pe care nu o poate lua nici unul dintre elementele ei (de exemplu, valoarea 16).
Matricea L are 7 linii i 8 coloane.
1 1 2

I
Soluia obinut va afia coordonatele ptratelor

OG
2 3
prin care se trece:
3 4 5 6 7
Soluia 4 8
1,1 1,2 2,2 3,2 3,3
5 9
3,4 3,5 4,5 5,5 6,5

AG
7,5 7,6 7,7 7,8 6 10
7 11 12 13 14
Subprogramele
Subprogramul init(). Se iniializeaz varianta 1 2 3 4 5 6 7 8

ED
cu care se trece din ptratul k-1 n ptratul k, adic elementul k din vectorul p: p[k]=0.
Subprogramul succesor(). Se consider c mai exist o posibilitate de continuare a
construirii soluiei pe nivelul k dac mai exist o variant de deplasare din ptratul k-1
n ptratul k, adic dac p[k]<4. Dac mai exist o variant de deplasare, pe nivelul

P
k din stiv, se trece la aceast variant (p[k]=p[k]+1) i se nregistreaz coordo-
natele ptratului k, care se vor obine prin adugarea, la coordonatele ptratului k-1, a
deplasrilor corespunztoare acestei variante (st[k].x=st[k-1].x+d[p[k]].x i
I
st[k].y=st[k-1].y+d[p[k]].y).
Subprogramul valid(). Se consider c ptratul k, n care s-a ajuns, poate fi
considerat c este bun, pentru a continua construirea soluiei, numai dac exist culoar
de trecere ntre ptratul k-1 i ptratul k pe direcia de deplasare aleas (dac n

matricea L, n elementul asociat ptratului k-1, bitul corespunztor direciei de deplasare


IC

are valoarea 1) i dac prin ptratul k nu s-a mai trecut (se verific dac n stiv, pe
nivelurile anterioare, nu mai exist un ptrat cu coordonatele ptratului k).
Subprogramul soluie(). Se verific dac ptratul n care s-a ajuns se afl n afara
CT

matricei (elementul asociat lui n matricea L are valoarea cu care a fost bordat
matricea: L[st[k].x][st[k].y]==16). Pentru a evita soluia prin care se iese din
labirint prin ptratul prin care s-a intrat, n stiv trebuie s existe cel puin dou elemente
(k>2). Deoarece ultimul ptrat din stiv nu face parte din soluia problemei (este ca un
DA

terminator al soluiei), coordonatele lui nu vor fi afiate n subprogramul tipar().


Subprogramul bt(). Deoarece coordonatele primului ptrat nu trebuie modificate, primu-
lui element al soluiei (k=1) i se atribuie coordonatele n subprogramul main(), iar n sub-
program se va ncepe cu iniializarea nivelului 2 din stiv (k=2); cutarea tuturor soluiilor se
DI

va face pn cnd vrful stivei coboar pn la primul element al soluiei: while (k>1).
#include<fstream.h>
struct element{int x,y;};
RA

element d[5]={{0,0},{-1,0},{0,1},{1,0},{0,-1}};
int n,m,k,ev,as,p[100],este=0,L[10][10];
typedef element stiva[100];
stiva st;
TU

fstream f("labirint1.txt",ios::in);
void init() {p[k]=0;}
int succesor()
{if (p[k]<4) {p[k]=p[k]+1;st[k].x=st[k-1].x+d[p[k]].x;
I

st[k].y=st[k-1].y+d[p[k]].y; return 1;}


ED
Informatic 37

C
else return 0;}
int valid()
{int x=st[k-1].x,y=st[k-1].y;

I
for (int i=1;i<k;i++)

OG
if (st[k].x==st[i].x && st[k].y==st[i].y) return 0;
switch (p[k])
{case 1: if (L[x][y] & 1) return 1; break; //spre N
case 2: if (L[x][y] & 2) return 1; break; //spre E

AG
case 3: if (L[x][y] & 4) return 1; break; //spre S
case 4: if (L[x][y] & 8) return 1;} //spre V
return 0;}
int solutie() {return k>2 && L[st[k].x][st[k].y]==16;}

ED
void tipar()
{int i; este=1;
for (i=1;i<k;i++) cout<<st[i].x<<","<<st[i].y<<" ";
cout<<endl;}

P
void bt(){//partea fix a algoritmului ca in exemplul anterior}
void main()
{int i,j; f>>n>>m;
I
for (i=1;i<=n;i++)
for (j=1;j<=m;j++) f>>L[i][j];
cout<<"Intrarea in labirint: "<<endl;
cout<<"x= "; cin>>i; st[1].x=i; cout<<"y= "; cin>>j; st[1].y=j;

for (i=1;i<=n;i++) {L[i][0]=16; L[i][m+1]=16;}


IC

for (i=1;i<=m;i++) {L[0][i]=16; L[n+1][i]=16;}


bt(); if (!este) cout<<"Nu exista solutii";}
Varianta 2
CT

Fiecare element al matricei L corespunde unei poziii din labirint:


1, dac se poate trece prin poziia (i, j) este culoar
L(i , j)
0, dac nu se poate trece prin poziia (i, j) este zid)
DA

Matricea L are 15 linii i 17 coloane. Punctul de intrare n labirint se gsete pe linia 1 i


n coloana 2.
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 0
DI

0 0 0 1 0 0 0 0 0 0 0 0 0 1 1 1 0
0 1 0 1 0 1 1 1 1 1 1 1 0 1 0 0 0
0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0
0 1 0 1 1 1 1 1 1 1 0 1 0 1 1 1 0
RA

0 1 1 1 0 0 0 0 0 1 0 1 0 0 0 1 0
0 1 1 1 0 1 1 1 0 1 0 1 1 1 1 1 0
0 1 0 0 0 0 0 1 0 1 0 0 1 0 0 0 0
0 1 1 1 1 1 0 1 0 1 1 0 1 1 1 1 0
TU

0 1 1 0 0 0 0 1 0 1 1 0 0 0 0 0 0
0 1 1 0 1 1 1 1 0 1 1 1 1 1 1 1 0
0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0
0 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
I
ED
38 Tehnici de programare

C
Soluia obinut va afia coordonatele punctelor prin care se trece:
Soluia 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1,2 2,2 2,3 2,4 3,4 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 0

I
0 0 0 1 0 0 0 0 0 0 0 0 0 1 1 1 0

OG
4,4 5,4 6,4 6,5 6,6
0 1 0 1 0 1 1 1 1 1 1 1 0 1 0 0 0
6,7 6,8 6,9 6,10 7,10
0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0
8,10 9,10 10,10 10,11 11,11 0 1 0 1 1 1 1 1 1 1 0 1 0 1 1 1 0
12,11 12,10 13,10 14,10 14,11 0 1 1 1 0 0 0 0 0 1 0 1 0 0 0 1 0
14,12 14,13 14,14 14,15 14,16 0 1 1 1 0 1 1 1 0 1 0 1 1 1 1 1 0

AG
15,16 0 1 0 0 0 0 0 1 0 1 0 0 1 0 0 0 0
0 1 1 1 1 1 0 1 0 1 1 0 1 1 1 1 0
Subprogramele (sunt prezentate numai 0 1 1 0 0 0 0 1 0 1 1 0 0 0 0 0 0
modificrile fa de varianta anterioar): 0 1 1 0 1 1 1 1 0 1 1 1 1 1 1 1 0
Subprogramul valid(). Se consider c 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0

ED
poziia k, n care s-a ajuns, poate fi consi- 0 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
derat c este bun, pentru a continua
construirea soluiei, numai dac ea este culoar de trecere (L[st[k].x][st[k].y]==1)
i dac prin poziia k nu s-a mai trecut (se verific dac n stiv, pe nivelurile anterioare,

P
nu mai exist o poziie cu coordonatele poziiei k).
Subprogramul soluie(). Se verific dac poziia n care s-a ajuns nu se afl la iei-
I
rea din labirint, adic se gsete pe marginea matricei (st[k].x==1 sau
st[k].x==n sau st[k].y==1 sau st[k].y==m).
#include<fstream.h>

struct element{int x,y;};


element d[5]={{0,0},{-1,0},{0,1},{1,0},{0,-1}};
IC

int n,m,k,ev,as,p[100],este=0,L[10][10];
typedef element stiva[100];
stiva st;
CT

fstream f("labirint1.txt",ios::in);
void init() {p[k]=0;}
int succesor()
{if (p[k]<4) {p[k]=p[k]+1;st[k].x=st[k-1].x+d[p[k]].x;
DA

st[k].y=st[k-1].y+d[p[k]].y; return 1;}


else return 0;}
int valid ()
{if (L[st[k].x][st[k].y]==0) return 0;
DI

for (int i=1;i<k;i++)


if (st[k].x==st[i].x && st[k].y==st[i].y) return 0;
return 1;}
int solutie()
RA

{return st[k].x==1 || st[k].x==n || st[k].y==1 || st[k].y==m;}


void tipar()
{for (int i=1,este=1;i<=k;i++) cout<<st[i].x<<","<<st[i].y<<" ";
cout<<endl;}
TU

void bt(){//partea fix a algoritmului ca in exemplul anterior}


void main()
{int i,j; f>>n>>m;
I

for (i=1;i<=n;i++)
ED

for (j=1;j<=m;j++) f>>L[i][j];


Informatic 39

C
cout<<"Intrarea in labirint: "<<endl;
cout<<"x= "; cin>>i; st[1].x=i; cout<<"y= "; cin>>j; st[1].y=j;
bt(); if (!este) cout<<"Nu exista solutii";}

I
OG
Observaie. Algoritmul folosit pentru generarea tuturor traseelor de ieire dintr-un labirint poate
fi folosit n orice problem de gsire a unui traseu pe o suprafa mprit n ptrate i pentru
care exist restricii de deplasare de la un ptrat la altul.
1. Problema bilei. Un teren este mprit n mai multe zone, fiecare

AG
Tem zon avnd o nlime h. Pentru simplificare, vom considera fiecare
zon ca fiind un ptrat cu aceeai dimensiune. Terenul poate fi
reprezentat sub forma unei matrice cu n linii i m coloane, fiecare element al matricei
reprezentnd nlimea unei zone de teren. O bil se gsete ntr-o zon cu coordo-
natele x (numrul liniei) i y (numrul coloanei). Ea se poate rostogoli numai ctre o

ED
zon care are nlimea mai mic dect cea a zonei n care se gsete. S se genereze
toate posibilitile de rostogolire a bilei pn la marginea terenului. Indicaie. Construi-
rea soluiei traseului are urmtoarele caracteristici:
O soluie este format din coordonatele zonelor prin care se rostogolete bila.

P
Fiecare soluie are un numr variabil de elemente. Primul element al soluiei conine
coordonatele zonei de plecare a bilei, iar ultimul element al soluiei conine coordo-
I
natele unei zone de la marginea terenului.
Bila se poate rostogoli n 8 direcii (corespunztoare celor 8 ptrate adiacente ptra-
tului n care se gsete), fiecare direcie de deplasare corespunznd unei constante
de deplasare care se adaug la coordonata x, respectiv y, a ptratului n care se

gsete bila.
Condiia de continuare a construirii soluiei este ca ptratul n care a ajuns bila s
IC

aib nlimea mai mic dect a ptratului anterior.


2. Problema capcanelor. Un teren este mprit n mai multe zone. Pentru simplificare
CT

vom considera fiecare zon ca fiind un ptrat cu aceeai dimensiune. Terenul poate fi
reprezentat sub forma unei matrice cu n linii i m coloane, fiecare element al matricei
reprezentnd un ptrat de teren. Anumite ptrate conin diverse capcane ascunse. O
persoan se gsete n ptratul cu coordonatele x1 (numrul liniei) i y1 (numrul
DA

coloanei) i trebuie s ajung n ptratul cu coordonatele x2 i y2 deplasndu-se orto-


gonal i fr s calce n ptratele cu capcane. Datele se citesc dintr-un fiier text, astfel:
de pe primul rnd, n, m i coordonatele ptratului de pornire i ale ptratului destinaie,
iar de pe urmtoarele rnduri perechile de coordonate ale ptratelor cu capcane. S
DI

se gseasc traseele pe care trebuie s le urmeze persoana respectiv. Indicaie.


Construirea soluiei traseului are urmtoarele caracteristici:
O soluie este format din coordonatele zonelor prin care trece persoana.
Fiecare soluie are un numr variabil de elemente. Primul element al soluiei conine
RA

coordonatele ptratului din care pleac persoana, iar ultimul element al soluiei
conine coordonatele ptratului n care trebuie s ajung.
Persoana se poate deplasa n 4 direcii (corespunztoare celor 4 ptrate aflate pe
diagonala ptratului n care se gsete), fiecare direcie de deplasare corespunznd
TU

unei constante de deplasare care se adaug la coordonata x, respectiv y, a


ptratului n care se gsete persoana.
Condiia de continuare a construirii soluiei este ca ptratul n care a ajuns per-
soana s nu conin capcane.
I
ED
40 Tehnici de programare

C
1.4. Metoda Divide et Impera
1.4.1. Descrierea metodei Divide et Impera

I
OG
Metoda divide et impera se poate folosi pentru problemele care pot fi descompuse n
subprobleme similare cu problema iniial (care se rezolv prin aceeai metod) i care
prelucreaz mulimi de date de dimensiuni mai mici, independente unele de altele (care
folosesc mulimi de date de intrare disjuncte).

AG
Scop: identificarea problemelor care pot fi descompuse n subprobleme similare care
folosesc mulimi de date de intrare disjuncte.

ED
Enunul problemei 1: S se calculeze suma elementelor dintr-un vector v care conine
numere ntregi.
Mulimea datelor de intrare o reprezint cele n elemente ale vectorului v. Ele pot fi divizate

P
n cte dou submulimi disjuncte, prin divizarea mulimii indicilor n dou submulimi.
Mulimea iniial a indicilor este determinat de primul indice (s) i de ultimul indice (d), iar
intervalul indicilor care se divizeaz este [s,d]. El se divizeaz n dou submulimi disjuncte,
I
[s,m] i [m+1,d], unde m este indicele din mijlocul intervalului: m=(s+d)/2. Astfel, problema
iniial este descompus n dou subprobleme, fiecare dintre ele constnd n calcularea
sumei numerelor dintr-o submulime de elemente (care corespunde unui subinterval al

indicilor). Descompunerea continu pn cnd fiecare submulime conine un singur


element i se poate calcula suma, obinndu-se soluia subproblemei.
IC

Enunul problemei 2: S se calculeze suma 12+23+ ... +n(n+1).


Mulimea datelor de intrare o reprezint primele n numere naturale. Mulimea iniial este
determinat de primul numr (s=1) i de ultimul numr (d=n), iar intervalul care se divi-
CT

zeaz este [s,d]. El se divizeaz n dou submulimi disjuncte, [s,m] i [m+1,d], unde m
este numrul din mijlocul intervalului: m=(s+d)/2. Astfel, problema iniial este descompus
n dou subprobleme, fiecare dintre ele constnd n calcularea sumei produselor dintre
DA

dou numere consecutive dintr-o submulime de elemente (care corespunde unui subinter-
val al numerelor). Descompunerea continu pn cnd fiecare submulime conine un
singur element i se poate calcula produsul, care se va aduga la sum, pentru a obine
soluia subproblemei.
DI

Enunul problemei 3: S se genereze termenul n al irului lui Fibonacci.


irul lui Fibonacci este definit recursiv: f1=1, f2=1 i fn= fn-2+ fn-1, pentru n3. Problema
determinrii termenului n al irului lui Fibonacci se poate descompune n dou subpro-
bleme: determinarea termenului n-1 i determinarea termenului n-2. Descompu-
RA

nerea continu pn cnd trebuie determinai termenii f1 i f2, a cror valoare este
cunoscut.

Metoda Divide et impera se bazeaz pe descompunerea unei probleme n


TU

subprobleme similare, prin intermediul unui proces recursiv. Procesul recursiv de


descompunere a unei subprobleme n alte subprobleme continu pn se obine
o subproblem cu rezolvarea imediat (cazul de baz), dup care se compun
soluiile subproblemelor pn se obine soluia problemei iniiale.
I
ED
Informatic 41

C
Paii algoritmului sunt:
PAS1. Se descompune problema n subprobleme similare problemei iniiale, de dimen-
siuni mai mici, independente unele de altele (care folosesc mulimi de date de

I
intrare disjuncte di).

OG
PAS2. Dac subproblema permite rezolvarea imediat (corespunde cazului de baz),
atunci se rezolv obinndu-se soluia s; altfel, se revine la Pas1.
PAS3. Se combin soluiile subproblemelor n care a fost descompus (si) o subproble-
m, pn cnd se obine soluia problemei iniiale.

AG
1.4.2. Implementarea metodei Divide et Impera
Deoarece subproblemele n care se descompune problema sunt similare cu problema inii-
al, algoritmul divide et impera poate fi implementat recursiv. Subprogramul recursiv

ED
divide_et_impera(d,s), unde d reprezint dimensiunea subproblemei (corespunde mulimii
datelor de intrare), iar s soluia subproblemei, poate fi descris n pseudocod astfel:
divide_et_impera(d,s)
nceput

P
dac dimensiunea d corespunde unui caz de baz
atunci se determin soluia s a problemei;
I
altfel
pentru i=1,n execut
se determin dimensiunea d i a subproblemei P i;
se determin soluia s i a subproblemei P i prin

apelul divide_et_impera(d_i,s_i);
sfrit_pentru;
IC

se combin soluiile s 1, s 2, s 3, ..., s n;


sfrit_dac;
sfrit;
CT

Implementarea acestui algoritm n limbajul C++ se face astfel:


/*declaraii globale pentru datele de intrare ce vor fi divizate n sub-
mulimi disjuncte pentru subproblemele n care se descompune problema*/
DA

void divizeaza(<parametri: submulimile>)


{//se divizeaz mulimea de date de intrare n submulimi disjuncte d i}
void combina(<parametri: soluiile s i care se combin>)
{//se combin soluiile obinute s i}
DI

void dei(<parametri: mulimea de date d i soluia s>)


{//declaraii de variabile locale
if (<este caz de baz>) {//se obine soluia corespunztoare subproblemei}
else
RA

{divizeaza(<parametri: k submulimi>);
for (i=1;i=k;i++)
dei(<parametri: mulimea de date d i i soluia s i>);
combina(<parametri: soluiile s i>);}}
TU

void main()
{//declaraii de variabile locale
//se citesc datele de intrare ale problemei mulimea d
dei(<parametri: mulimea de date d i soluia s>);
I

//se afieaz soluia problemei s}


ED
42 Tehnici de programare

C
Exemplul 1. S se calculeze suma elementelor pare dintr-un vector v care conine nume-
re ntregi. Numrul de elemente ale vectorului (n) i elementele lui se citesc de la tastatur.
s=1 1 2 3 4 5 d=5

I
OG
5 10 15 20 25
m=(1+5)/2=3
z=z12345= z123+ z45=10+20=30

1 2 3 4 5

AG
s=1 5 10 15 d=3 s=4 20 25 d=5
m=(1+3)/2=2 m=(4+5)/2=4
z123= z12+ z45= z4+ z5=20+0=20
z3=10+0=10

ED
1 2 3 4 5
s=1 5 10 d=2 15 20 25
m=(1+2)/2=1 s=d=3 s=d=4 s=d=5
z12= z1+ z2=0+10=10 z3=0 z4=20 z5=0

1 2
P
I
s=d=1 5 10 s=d=2
z1=0 z2=10
Implementarea metodei divide et impera n acest exemplu se face astfel:

Subprogramul divizeaza() Numrul de subprobleme n care se descompune problema


este 2 (k=2). Mulimea datelor de intrare este divizat n dou submulimi disjuncte, prin
IC

divizarea mulimii indicilor n dou submulimi disjuncte de indici, adic mulimea indicilor
[s,d] (unde s este primul indice, iar d ultimul indice) este divizat n dou submulimi disjunc-
te [s,m] i [m+1,d], unde m este indicele din mijlocul intervalului: m=(s+d)/2. n subpro-
CT

gram, procesul de divizare const n determinarea mijlocului intervalului m.


Subprogramul combina() Combinarea soluiei nseamn adunarea celor dou sume
obinute prin rezolvarea celor dou subprobleme. n subprogram sunt combinate cele
dou valori obinute din prelucrarea celor dou intervale, adic se adun cele dou
DA

valori x i y, obinndu-se soluia z.


Subprogramul dei() O subproblem corespunde cazului de baz atunci cnd sub-
mulimea conine un singur element (se poate calcula suma, obinndu-se soluia subpro-
blemei). Dac s-a terminat procesul recursiv (prin procesul de divizare, cele dou capete
DI

ale intervalului au ajuns s fie identice), atunci se prelucreaz cazul de baz (se calcu-
leaz suma n variabila z, corespunztoare soluiei, astfel: dac numrul v[s] este par,
atunci suma va fi chiar numrul; altfel, are valoarea 0); altfel, se apeleaz subproramul
pentru divizarea intervalului, se apeleaz subprogramul dei() pentru primul interval, se
RA

apeleaz subprogramul dei() pentru al doilea interval i se combin cele dou rezultate.
#include<iostream.h>
int v[100],n;
TU

void divizeaza(int s,int d,int &m) {m=(s+d)/2;}


void combina(int x,int y,int &z) {z=x+y;}
void dei(int s,int d,int &z)
{int m,x1,x2;
I

if (d==s)
ED
Informatic 43

C
if (v[s]%2==0) z=v[s]; else z=0;
else
{divizeaza(s,d,m); dei(s,m,x1); dei(m+1,d,x2); combina(x1,x2,z);}}

I
void main()

OG
{int i,z; cout<<"n= ";cin>>n;
for(i=1;i<=n;i++) {cout<<"v["<<i<<"]="; cin>>v[i];}
dei(1,n,z); cout<<"suma= "<<z;}
Exemplul 2: S se calculeze suma 12+23+ ... +n(n+1).

AG
s=1 1 2 3 4 5 d=5
m=(1+5)/2=3
z=z12345= z123+ z45=20+50=70

ED
s=1 1 2 3 d=3 s=4 4 5 d=5
m=(1+3)/2=2 m=(4+5)/2=4
z123= z12+ z3=8+12=20 z45= z4+ z5=20+30=50

s=1 1 2
m=(1+2)/2=1
d=2 3
s=d=3
P 4
s=d=4
5
s=d=5
I
z12= z1+ z2=2+6=8 z3=34=12 z4=45=20 z5=56=30

s=d=1 1 2 s=d=2

z1=12=2 z2=23=6
Implementarea metodei divide et impera n acest exemplu se face astfel:
IC

Subprogramul divizeaza() Numrul de subprobleme n care se descompune pro-


blema este 2 (k=2). Mulimea datelor de intrare este divizat n dou submulimi disjunc-
CT

te, prin divizarea mulimii primelor n numere naturale n dou submulimi disjuncte, adi-
c mulimea [s,d] (unde s este primul numr din mulime, iar d ultimul numr din
mulime) este divizat n dou submulimi disjuncte, [s,m] i [m+1,d], unde m este nu-
mrul din mijlocul intervalului: m=(s+d)/2. n subprogram, procesul de divizare const
DA

n determinarea mijlocului intervalului, m.


Subprogramul combina() Combinarea soluiei nseamn adunarea celor dou sume
obinute prin rezolvarea celor dou subprobleme. n subprogram sunt combinate cele
dou valori obinute din cele dou intervale (se adun cele dou valori, x i y) obinn-
DI

du-se soluia z.
Subprogramul dei() O subproblem corespunde cazului de baz atunci cnd sub-
mulimea conine un singur element (se poate calcula termenul sumei produsul celor
dou numere consecutive obinndu-se soluia subproblemei). Dac s-a terminat
RA

procesul recursiv (prin procesul de divizare, cele dou capete ale intervalului au ajuns
s fie identice), atunci se prelucreaz cazul de baz (se calculeaz produsul n variabila
z, corespunztoare soluiei); altfel, se apeleaz subprogramul pentru divizarea inter-
valului, se apeleaz subprogramul dei() pentru primul interval, se apeleaz subpro-
TU

gramul dei() pentru al doilea interval i se combin cele dou rezultate.


#include<iostream.h>
int n;
void divizeaza(int s,int d,int &m) {m=(s+d)/2;}
I
ED

void combina(int x,int y,int &z) {z=x+y;}


44 Tehnici de programare

C
void dei(int s,int d,int &z)
{int m,x1,x2;
if (d==s) z=s*(s+1);

I
else {divizeaza(s,d,m); dei(s,m,x1); dei(m+1,d,x2); combina(x1,x2,z);}}

OG
void main()
{int z; cout<<"n= ";cin>>n; dei(1,n,z); cout<<"suma ="<<z; }
Exemplul 3: S se calculeze termenul n al irului lui Fibonacci.
f(2) =1

AG
f(3)
f(4) z=1+1=2 f(1) =1
f(5) z=2+1=3 f(2) =1
z=3+2=5

ED
f(2) =1
f(3)
z=1+1=2 f(1) =1

P
f(6) f(2) =1
z=5+3=8 f(3)
z=1+1=2
I
f(4) f(1) =1
z=2+1=3 f(2) =1

Implementarea metodei divide et impera n acest exemplu se face astfel:


Subprogramul divizeaza() Numrul de subprobleme n care se descompune


problema este 2 (k=2): determinarea termenului n-1 i determinarea termenului n-2.
IC

Descompunerea se face implicit, prin parametrul cu care se apeleaz subprogramul


dei(), i subprogramul de divizare nu mai este necesar.
Subprogramul combina() Combinarea soluiei nseamn adunarea celor doi termeni
CT

ai irului (x1 i x2), obinndu-se soluia z.


Subprogramul dei() O subproblem corespunde cazului de baz atunci cnd s-a ajuns
la un termen direct calculabil. Dac s-a terminat procesul recursiv (prin procesul de divizare
s-a ajuns la termenul f1 sau f2), atunci se prelucreaz cazul de baz; altfel, se apeleaz
DA

subprogramul dei() pentru primul termen al descompunerii, se apeleaz subprogramul


dei()pentru al doilea termen al descompunerii i se combin cele dou rezultate.
#include<iostream.h>
int n;
DI

void combina(int x1,int x2,int &z) {z=x1+x2;}


void dei(int n,int &z)
{int x1,x2;
RA

if (n==1 || n==2) z=1;


else {dei(n-1,x1); dei(n-2,x2); combina(x1,x2,z);}}
void main()
{int z; cout<<"n= "; cin>>n; dei(n,z); cout<<z;}
TU

n acest exemplu, problema a fost descompus n probleme care nu


Atenie sunt independente unele de altele i, n apelurile recursive,
aceeai subproblem este rezolvat de mai multe ori: f(4), f(3), f(2),
f(1). Pentru acest tip de problem nu se recomand metoda divide et impera deoarece
I

nu este eficient.
ED
Informatic 45

C
Exemplul 4: S se determine simultan valoarea minim i valoarea maxim dintr-un
vector v care conine numere ntregi. Numrul de elemente ale vectorului (n) i elementele
lui se citesc de la tastatur.

I
Implementarea metodei divide et impera n acest exemplu se face astfel:

OG
Subprogramul divizeaza() Numrul de subprobleme n care se descompune pro-
blema este 2 (k=2). Divizarea mulimii datelor de intrare se face la fel ca la exemplul
pentru calcularea sumei elementelor unui vector i subprogramele sunt identice.
Subprogramul combina() Combinarea soluiei nseamn determinarea minimului (z1)

AG
i a maximului (z2) dintre cele dou valori minime (x1 i y1), respectiv maxime (x2 i y2),
obinute prin rezolvarea celor dou subprobleme. n subprogram sunt combinate cele
dou perechi de valori obinute din cele dou intervale. Dac x1>y1, atunci minimul (z1)
este y1; altfel, este x1. Dac x2>y2, atunci maximul (z2) este x2; altfel, este y2.

ED
Subprogramul dei() O subproblem corespunde cazului de baz atunci cnd
submulimea conine un singur element (se pot calcula minimul i maximul; att minimul
ct i maximul vor avea valoarea elementului). Dac s-a terminat procesul recursiv (prin
procesul de divizare cele dou capete ale intervalului au ajuns s fie identice), atunci se

P
prelucreaz cazul de baz (se calculeaz minimul i maximul n variabilele z1 i z2
corespunztoare soluiei); altfel, se apeleaz subprogramul pentru divizarea interva-
lului, se apeleaz subprogramul dei() pentru primul interval, se apeleaz subpro-
I
gramul dei() pentru al doilea interval i se combin cele dou rezultate.
#include<iostream.h>
int v[100],n;

void divizeaza(int s,int d,int &m){m=(s+d)/2;}


void combina(int x1,int y1,int &z1,int x2,int y2,int &z2)
IC

{if (x1>y1) z1=y1; else z1=x1;


if (x2>y2) z2=x2; else z2=y2;}
void dei(int s,int d,int &z1, int &z2) //z1 minim, z2 maxim
CT

{int m,x1,x2,y1,y2;
if (d==s) z1=z2=v[s];
else {divizeaza(s,d,m);
dei(s,m,x1,x2); //x1 minim, x2 maxim
DA

dei(m+1,d,y1,y2); //y1 minim, y2 maxim


combina(x1,y1,z1,x2,y2,z2);}}
void main()
{int i,z1,z2; cout<<"n= ";cin>>n;
DI

for(i=1;i<=n;i++) {cout<<"v["<<i<<"]="; cin>>v[i];}


dei(1,n,z1,z2);
cout<<"minimul ="<<z1<<endl<<"maximul ="<<z2<<endl;}
RA

Exemplul 5: S se calculeze suma a dou polinoame. Gradele celor dou polinoame, n


i m, i coeficienii celor dou polinoame se citesc de la tastatur. Coeficienii celor dou
polinoame se memoreaz n vectorii p i q, iar coeficienii polinomului sum se memoreaz
n vectorul r.
TU

Implementarea metodei divide et impera n acest exemplu se face astfel:


Subprogramul divizeaza() Numrul de subprobleme n care se descompune pro-
blema este 2 (k=2). Deoarece exist dou mulimi de date de intrare (vectorii p i q care
memoreaz coeficienii celor dou polinoame), se va lua ca reper mulimea cu cele mai
I

multe elemente. Mulimea datelor de intrare este divizat n dou submulimi disjuncte,
ED
46 Tehnici de programare

C
prin divizarea mulimii indicilor n dou submulimi disjuncte de indici, adic mulimea
indicilor [s,d] (unde s este primul indice, iar d este ultimul indice d=maxim(n,m)+1)
este divizat n dou submulimi disjuncte [s,mijl] i [mijl+1,d], unde mijl este indicele

I
din mijlocul intervalului: mijl=(s+d)/2. Procesul de divizare este identic cu cel de la

OG
exemplele anterioare.
Subprogramul combina() Deoarece n cazul de baz se determin unul dintre coe-
ficienii polinomului sum care se scrie direct n vectorul r, acest subprogram nu mai
este necesar.

AG
Subprogramul dei() O subproblem corespunde cazului de baz atunci cnd submul-
imea conine un singur element (se poate calcula coeficientul polinomului sum). Dac
s-a terminat procesul recursiv (prin procesul de divizare, cele dou capete ale intervalului
au ajuns s fie identice), atunci se prelucreaz cazul de baz, prin care se calculeaz
coeficientul polinomului sum pentru acel indice (dac termenul care se calculeaz are

ED
indicele mai mic dect gradul minim al polinoamelor, atunci el este egal cu suma coefi-
cienilor celor dou polinoame; altfel, dac polinomul p are gradul mai mic dect al polino-
mului q, atunci el este egal cu coeficientul polinomului q; altfel, el este egal cu coeficientul
polinomului p); altfel, se apeleaz subprogramul pentru divizarea intervalului, se apelea-

P
z subprogramul dei() pentru primul interval i apoi pentru al doilea interval.
#include<iostream.h>
I
int p[10],q[10],r[10],n,m;
int maxim(int x,int y) {if (x>y) return x; else return y;}
int minim(int x,int y) {if (x>y) return y; else return x;}
void divizeaza(int s,int d,int &mijl) {mijl=(s+d)/2;}

void dei(int s,int d)


IC

{int mijl;
if (d==s)
if (d<=minim(n,m)) r[d]=p[d]+q[d];
CT

else if(n<m) r[d]=q[d];


else r[d]=p[d];
else {divizeaza(s,d,mijl); dei(s,mijl); dei(mijl+1,d);}}
void main()
DA

{int i; cout<<"n= ";cin>>n; cout<<"m= ";cin>>m;


for(i=1;i<=n+1;i++) {cout<<"p("<<i-1<<")= "; cin>>p[i];}
for(i=1;i<=m+1;i++) {cout<<"q("<<i-1<<")= "; cin>>q[i];}
dei(1,maxim(n,m)+1);
DI

for(i=maxim(n,m)+1;i>=1;i--)
if (r[i]!=0)
{if (r[i]!=1) {cout<<r[i]; if (i!=1) cout<<"*";}
if (i>2) cout<<"x^"<<i-1; else if (i==2) cout<<"x";
RA

if (i!=1) cout<<" + ";}}


1. Programul urmtor afieaz, n ordine invers, elementele unui
Tem vector. Explicai cum a fost folosit metoda divide et impera pentru a
rezolva problema.
TU

#include<iostream.h>
int v[100],n;
void divizeaza(int s,int d,int &m)
I

{m=(s+d)/2;}
ED
Informatic 47

C
void dei(int s,int d)
{int m;
if (d==s) cout<<v[s]<<" ";

I
else {divizeaza(s,d,m); dei(m+1,d); dei(s,m);}}

OG
void main()
{int i; cout<<"n= ";cin>>n;
for(i=1;i<=n;i++) {cout<<"a("<<i<<")= "; cin>>v[i];}
dei(1,n);}

AG
2. Determinai ce calculeaz programul urmtor. Explicai cum a fost folosit metoda
divide et impera pentru a rezolva problema.
#include<iostream.h>
int n;

ED
void divizeaza(int s,int d,int &m) {m=(s+d)/2;}
void combina(int x,int y,int &z) {z=x+y;}
void dei(int s,int d,int &z)
{int m,x1,x2;

P
if (d==s) {if(s%2==0) z=-s*5;else z=s*5;}
else
{divizeaza(s,d,m); dei(s,m,x1); dei(m+1,d,x2); combina(x1,x2,z);}}
I
void main()
{int z; dei(1,20,z); cout<<"suma = "<<z;}
Scriei urmtoarele programe, n care folosii metoda divide et impera.

Tem Valorile pentru datele de intrare se citesc de la tastatur.


1. S se calculeze n!.
IC

2. S se calculeze simultan produsul i suma a n numere memorate ntr-un vector.


3. S se calculeze suma 1+12+123+...+123...n.
4. S se numere elementele pare dintr-un vector.
CT

5. S se verifice dac un vector conine numai numere pozitive sau numai numere negative.
6. S se calculeze c.m.m.d.c. a n numere memorate ntr-un vector.
7. S se determine numrul de apariii ale unei valori x ntr-un vector.
8. S se calculeze valoarea unui polinom P(x) ntr-un punct x precizat.
DA

9. ntr-o matrice cu n linii i m coloane, s se interschimbe coloana p cu coloana q.


10. ntr-o matrice ptrat cu dimensiunea n s se interschimbe linia p cu coloana q.
11. ntr-o matrice ptrat cu dimensiunea n s se interschimbe diagonala principal cu
diagonala secundar.
DI

12. S se determine simultan valoarea minim i valoarea maxim, dintr-o matrice cu n linii
i m coloane.
Complexitatea algoritmului divide et impera
RA

Metoda divide et impera se bazeaz pe rezolvarea recursiv a subproblemelor n care


este divizat problema iniial.
Atunci cnd un algoritm conine un apel recursiv, timpul su de execuie este dat de o formul
TU

recursiv care calculeaz timpul de execuie al algoritmului pentru o dimensiune n a datelor


de intrare, cu ajutorul timpilor de execuie pentru dimensiuni mai mici. Timpul de execuie al
unui algoritm care folosete metoda divide et impera se bazeaz pe calculul timpilor de exe-
cuie ai celor trei etape de rezolvare a problemei. Dac:
I
ED
48 Tehnici de programare

C
problema iniial se divizeaz n a subprobleme, pentru care dimensiunea datelor de
intrare reprezint 1/b din dimensiunea problemei iniiale;
timpul de execuie a problemei iniiale este T(n);

I
timpul necesar pentru a divide problema n subprobleme este D(n);

OG
timpul necesar pentru combinarea soluiilor subproblemelor, pentru a obine soluia
problemei, este C(n);
timpul necesar pentru rezolvarea cazului (1) pentru cazul de baz
de baz este (1); T(n) =
aT(n/b)+D(n)+C(n) n caz contrar

AG
atunci se obine funcia pentru timpul de exe-
cuie care este prezentat alturat.
De exemplu, pentru a calcula suma elementelor unui vector cu n elemente, problema se
descompune n dou subprobleme (a=2) i dimensiunea datelor de intrare pentru o subpro-

ED
blem reprezint jumtate din dimensiunea datelor iniiale (b=2). Pentru divizarea problemei
n subprobleme, se calculeaz mijlocul intervalului de indici i O(D(n))=(1)). Pentru combi-
narea celor dou soluii ale fiecrei subprobleme, se adun cele dou valori, i O(C(n))=(1).
k
Considerm c n=2 . Rezult c:

P
k k-1 k-1 2
T(n)=T(2 )+2(1) = 2(T(2 )+2(1))+2(1 )= 2(T(2 )+2 (1) =
k-2 2 2 k-2 3
2(2T(2 )+2(1))+2 (1)=2 T(2 )+2 (1) = ... =
k 0 k+1 k k+1 k
2 T(2 )+2 (1) = 2 (1)+2 (1) = 2 3 = n3.
I
Ordinul de complexitate al algoritmului este O(n). Algoritmul iterativ pentru rezolvarea
acestei probleme are ordinul de complexitate O(n).
Observaie. Pentru acest gen de probleme, metoda iterativ este mai eficient. Rezolvarea

acestui tip de probleme cu ajutorul metodei divide et impera a avut numai un rol scolastic,
pentru nelegerea metodei i a implementrii ei.
IC

Metoda divide et impera se recomand n urmtoarele cazuri:


algoritmul obinut este mai eficient dect algoritmul clasic (iterativ) de exemplu, algo-
CT

ritmul de cutare ntr-un vector sortat i algoritmii pentru sortarea unui vector;
rezolvarea problemei prin divizarea ei n subprobleme este mai simpl dect rezol-
varea clasic (iterativ) de exemplu, problema turnurilor din Hanoi i generarea unor
modele fractale.
DA

1.4.3. Cutarea binar


S se caute, ntr-un ir de numere ntregi ordonate strict cresctor (sau varianta strict des-
cresctor), poziia n care se gsete n ir o valoare x citit de la tastatur. Dac valoarea
DI

nu se gsete n ir, s se afieze un mesaj de informare.


Algoritmul de cutare secvenial ntr-un vector are ordinul de complexitate O(n). Pornind
de la faptul c vectorul este un vector particular (este ordonat strict cresctor sau strict
RA

descresctor), se poate folosi metoda divide et impera. Pentru un vector ordonat strict
cresctor, paii algoritmului sunt:
PAS1. Se divizeaz vectorul v n doi subvectori, prin divizarea mulimii indicilor [s,d] (unde
s este indicele primului element, iar d indicele ultimului element) n dou submulimi
TU

disjuncte, [s,m] i [m+1,d], unde m este indicele din mijlocul intervalului: m=(s+d)/2.
PAS2. Dac elementul situat pe poziia din mijloc (v[m]) are valoarea x, atunci proble-
ma este rezolvat i poziia este m; altfel, dac elementul din mijlocul vectorului
este mai mic dect valoarea x, atunci cutarea se face printre elementele cu
I

indicii n mulimea [s,m]; altfel, cutarea se face printre elementele cu indicii din
ED
Informatic 49

C
mulimea [m+1,d]. Pasul 2 se execut pn cnd se gsete elementul sau pn
cnd vectorul nu mai poate fi mprit n subvectori.
#include<iostream.h>

I
OG
int v[100],n,x;
void divizeaza(int s,int d,int &m) {m=(s+d)/2;}
void cauta(int s,int d,int &z)
{int m;
if (d>s){divizeaza(s,d,m);

AG
if (v[m]==x) z=m;
else if (x>v[m]) cauta(m+1,d,z);
else cauta(s,m,z);}}
void main()

ED
{int i,z=0; cout<<"n= ";cin>>n; cout<<"x= ";cin>>x;
for(i=1;i<=n;i++) {cout<<"v["<<i<<"]="; cin>>v[i];}
cauta(1,n,z);
if(z==0) cout<<"nu exista elementul "<<x<<" in vector";

P
else cout<<"exista pe pozitia "<<z;}
Complexitatea algoritmului de cutare binar. Pentru divizarea problemei n subpro-
bleme, se calculeaz mijlocul intervalului de indici i O(D(n))=(1). Deoarece cutarea se
I
face numai ntr-unul dintre cei doi subvectori (problema iniial se rezolv prin rezolvarea
uneia dintre cele dou subprobleme) i a=1, formula recurent a timpului de execuie
k
este T(n)= T(n/2)+(1). Considerm c n=2 (k=log2n). Rezult c:

k k-1 k-1
T(n)=T(2 )+(1) = (T(2 ) +(1)) +(1)= T(2 )+2(1)) = ... =
0
T(2 )+(k+1)(1) = (1)+ (k+1)(1) = (k+2)(1)= log2n (1).
IC

Ordinul de complexitate al algoritmului este O(log2n).


Aplicarea algoritmului de cutare binar
CT

Exemplu. S se determine, cu o precizie de 4 zecimale, rdcina real, din intervalul [0,1], a


3
ecuaiei x +x-1=0.
S-a identificat pentru aceast ecuaie o rdcin n intervalul [0,1] i ne propunem s locali-
DA

zm aceast rdcin, n limitele unei precizii de 4 zecimale, printr-o valoare x. Pentru cuta-
rea valorii x se va folosi metoda biseciei care const n reducerea intervalului de cutare
prin njumtirea repetat i selectarea subintervalului n care se gsete rdcina. Intervalul
[s,d] este mprit n dou subintervale, [s,m] i [m,d], unde m=(s+d)/2. Cutarea rdcinii
3
DI

se va face n subintervalul n care funcia f(x)=x +x-1 i schimb semnul, astfel: dac
f(s)*f(m)<0, atunci cutarea continu n intervalul [s,m]; altfel, cutarea continu n subinter-
valul [m,d]. Procesul recursiv este ntrerupt cnd se ajunge la intervalul [s,d] pentru care
d-s<r, unde r este eroarea acceptat pentru o precizie de 4 zecimale i are valoarea 0,0001.
RA

#include<iostream.h>
#include<iosmanip.h>
const float r=0.0001;
float f(float x) {return x*x*x+x-1;}
TU

void divizeaza(float s,float d,float &m) {m=(s+d)/2;}


void radacina(float s,float d,float &z)
{float m;
I

if (d-s<r) z=(s+d)/2;
ED

else
50 Tehnici de programare

C
{divizeaza(s,d,m);
if (f(s)*f(m)<0) radacina(s,m,z);
else radacina(m,d,z);}}

I
void main()

OG
{float z=0; radacina(0,1,z); cout<<"radacina= "<<z<<endl;
cout<<"f(x)= "<<setiosflags(ios::fixed)<<f(z); }
1. S se caute, ntr-un ir de numere ntregi, n care mai nti se gsesc
Tem numerele pare i apoi numerele impare, poziia n care se gsete, n

AG
ir, o valoare x citit de la tastatur.
2. S se calculeze radicalul de ordinul 2 din numrul a, cu o aproximaie de 4 zecimale,
fr a folosi funcia matematic de sistem sqrt(). S se compare rezultatul obinut cu
rezultatul furnizat de funcia matematic de sistem. Indicaie. Pornind de la ecuaia

ED
2
x -a=0, se va identifica intervalul n care se gsete soluia i apoi se va localiza, cu o
precizie de 4 zecimale, rdcina real din acest interval.
3. S se calculeze partea ntreag a radicalului de ordinul 3 din numrul a fr a folosi
funcia matematic de sistem.

P
4. S se calculeze radicalul de ordinul 3 din numrul a, cu o aproximaie de 4 zecimale.

1.4.4. Sortarea rapid (QuickSort)


I
Prin aceast metod de sortare se execut urmtoarele operaii prin care sunt rearanjate
elementele din cadrul vectorului:

X1 X2 X3 Xi-1 Xi Xi+1 Xn-1 Xn


IC

Pivotul Vectorul iniial


CT

Primul element din vector, numit pivot, este mutat n cadrul vectorului pe poziia pe
care trebuie s se gseasc n vectorul sortat.
Toate elementele mai mici dect el vor fi mutate n vector n faa sa.
DA

Toate elementele mai mari dect el vor fi mutate n vector dup el.

Xs Xs+1 Xs+2 Xm-1 Xm Xm+1 Xd-1 Xd


DI

Subvectorul din stnga pivotului Subvectorul din dreapta pivotului


(elemente mai mici dect pivotul) Pivotul (elemente mai mari dect pivotul)
RA

De exemplu, dac vectorul conine elementele {3, 4, 1, 5, 2}, dup executarea operaiilor
precizate vectorul va fi {2, 1, 3, 5, 4}.
Folosind metoda divide et impera problema iniial va fi descompus n subprobleme, astfel:
PAS1. Se rearanjeaz vectorul, determinndu-se poziia n care va fi mutat pivotul (m).
TU

PAS2. Problema iniial (sortarea vectorului iniial) se descompune n dou subprobleme,


prin descompunerea vectorului n doi subvectori: vectorul din stnga pivotului i
vectorul din dreapta pivotului, care vor fi sortai prin aceeai metod. Aceti sub-
I

vectori, la rndul lor, vor fi i ei rearanjai i mprii de pivot n doi subvectori etc.
ED
Informatic 51

C
PAS3. Procesul de descompunere n subprobleme va continua pn cnd, prin descom-
punerea vectorului n subvectori, se vor obine vectori care conin un singur element.
Subprogramele specifice algoritmului divide et impera vor avea urmtoarea semnificaie:

I
n subprogramul divizeaza() se va rearanja vectorul i se va determina poziia pivotului

OG
xm, care va fi folosit pentru divizarea vectorului n doi subvectori: [xs, xm-1] i [xm+1, xd].
Subprogramul combina() nu mai este necesar, deoarece combinarea soluiilor se
face prin rearanjarea elementelor n vector.
n subprogramul divizeaza() vectorul se parcurge de la ambele capete ctre poziia n

AG
care trebuie mutat pivotul. Se vor folosi doi indici: i pentru parcurgerea vectorului de la
nceputul lui ctre poziia pivotului (i se va incrementa) i j pentru parcurgerea vectorului
de la sfritul lui ctre poziia pivotului (j se va decrementa). Cei doi indici vor fi iniializai
cu capetele vectorului (i=s, respectiv j=d) i se vor deplasa pn cnd se ntlnesc, adic

ED
att timp ct i<j. n momentul n care cei doi indici s-au ntlnit nseamn c operaiile de
rearanjare a vectorului s-au terminat i pivotul a fost adus n poziia corespunztoare lui n
vectorul sortat. Aceast poziie este i (sau j) i va fi poziia m de divizare a vectorului.
n exemplele urmtoare sunt prezentate dou versiuni pentru subprogramul divizeaza():

P
Versiunea 1. Se folosesc variabilele logice: pi, pentru parcurgerea cu indicele i, i pj,
pentru parcurgerea cu indicele j. Ele au valoarea: 1 se parcurge vectorul cu acel indice,
I
i 0 nu se parcurge vectorul cu acel indice; cele dou valori sunt complementare.
#include<iostream.h>
int x[100],n;

void schimb(int &a, int &b){int aux=a; a=b; b=aux;}


void divizeaza(int s,int d,int &m)
IC

{int i=s,j=d,pi=0,pj=1;
// pivotul fiind pe pozitia s, parcurgerea incepe cu indicele j
while (i<j)
CT

{if (x[i]>x[j]) {schimb(x[i],x[j]); schimb(pi,pj);}


i=i+pi; j=j-pj;}
m=i;}
void QuickSort(int s,int d)
DA

{int m;
if (s<d) {divizeaza(s,d,m);
QuickSort(s,m-1);
QuickSort(m+1,d);}}
DI

void main()
{int i; cout<<"n= ";cin>>n;
for(i=1;i<=n;i++) {cout<<"x["<<i<<"]= ";cin>>x[i];}
RA

QuickSort(1,n);
cout<<"vectorul sortat"<<endl; for(i=1;i<=n;i++) cout<<x[i]<<" ";}
Cei doi indici i i j sunt iniializai cu extremitile vectorului i j
(i=1; j=5) i parcurgerea ncepe cu indicele j (pi=0; pj=1) 1 2 3 4 5
TU

3 4 1 5 2
Se compar pivotul (3) cu ultimul element (2). Deoarece i j
pivotul este mai mic, cele dou valori se interschimb, i 1 2 3 4 5
se schimb i modul de parcurgere (pi=1; pj=0 2 4 1 5 3
I

avanseaz indicele i).


ED
52 Tehnici de programare

C
Se compar elementul din poziia i (4) cu elementul din i j
poziia j (3). Deoarece 4 este mai mare dect 3, cele 1 2 3 4 5
dou valori se interschimb, i se schimb i modul de 2 3 1 5 4

I
parcurgere (pi=0; pj=1 avanseaz indicele j).

OG
Se compar elementul din poziia i (3) cu elementul din i j
poziia j (5). Deoarece 3 este mai mic dect 5, cele dou 1 2 3 4 5
valori nu se interschimb, i se pstreaz modul de 2 3 1 5 4
parcurgere (pi=0; pj=1 avanseaz indicele j).

AG
Se compar elementul din poziia i (3) cu elementul din po- ij
ziia j (1). 3 fiind mai mare dect 1, cele dou valori se in- 1 2 3 4 5
terschimb i se schimb i modul de parcurgere (avansea- 2 1 3 5 4
z indicele i). Cei doi indici fiind egali, algoritmul se termin.

ED
Versiunea 2.
void divizeaza(int s,int d,int &m)
{int pivot=x[s],i=s,j=d;
while (i<j) {while(x[i]<pivot) i++;

P
while(x[j]>pivot) j--;
if (i<j) schimb(x[i],x[j]);}
m=i;}
I
Iniial, cei doi indici i i j sunt iniializai cu extremitile i j
vectorului (i=1; j=5) i pivotul are valoarea 3. 1 2 3 4 5
3 4 1 5 2

Elementul din poziia i (3) nu este mai mic dect pivotul; i j


indicele i nu avanseaz (i=1). Elementul din poziia j (2) 1 2 3 4 5
IC

nu este mai mare dect pivotul; indicele j nu avanseaz 2 4 1 5 3


(j=5). Valorile din poziiile i i j se interschimb.
Elementul din poziia i (2) este mai mic dect pivotul; i j
CT

indicele i avanseaz pn la primul element mai mare 1 2 3 4 5


dect pivotul (i=2). Elementul din poziia j (3) nu este mai 2 3 1 5 4
mare dect pivotul; indicele j (j=5) nu avanseaz. Valorile
din poziiile i i j se interschimb.
DA

Elementul din poziia i (3) nu este mai mic dect pivotul; i j


indicele i nu avanseaz (i=2). Elementul din poziia j (4) 1 2 3 4 5
este mai mare dect pivotul; indicele j avanseaz pn la 2 1 3 5 4
primul element mai mic dect pivotul (j=3). Valorile din
DI

poziiile i i j se interschimb.
Elementul din poziia i (1) este mai mic dect pivotul; indi- j i
cele i avanseaz la primul element mai mare dect pivotul 1 2 3 4 5
(i=4). Elementul din poziia j (3) nu este mai mare dect 2 1 3 5 4
RA

pivotul; indicele j nu avanseaz (j=3). Indicele i fiind mai


mare dect indicele j, algoritmul se termin.

Observaie. n ambele cazuri algoritmul continu cu divizarea vectorului n subvectorii cu


indicii [1,2] i [4,5] i rearanjarea elementelor n cei doi subvectori.
TU

Complexitatea algoritmului de sortare rapid. Pentru divizarea problemei n subpro-


bleme se calculeaz mijlocul intervalului de indici i O(D(n))=(1). Pentru combinarea
soluiilor se parcurge vectorul cu ajutorul celor doi indici, de la primul element pn la
ultimul element, i O(D(n))=O(n(1))=O(n). Timpul de execuie este T(n)= 2T(n/2)+n.
I

k
ED

Considernd c n=2 , rezult:


Informatic 53

C
k k k-1 k-1 k k-1 k k
T(n)=T(2 )+2 = 2(T(2 )+ 2 ) +2 = 2T(2 ) +2 +2 = ... =
k-2 k-2 k k 2 k-2 k-2 k k k k
22(T(2 )+ 2 ) +2 +2 = 2 (T(2 )+ 2 ) +2 +2 +2 = k2 = log2n n.
Ordinul de complexitate al algoritmului este O(nlog2n).

I
OG
1.4.5. Sortarea prin interclasare (MergeSort)
Algoritmul de interclasare se execut pe doi vectori, ordonai dup acelai criteriu, pentru a
obine un al treilea vector, care s conin elementele primilor doi vectori, ordonate dup

AG
acelai criteriu. Algoritmul de sortare prin interclasare se bazeaz pe observaia c orice
vector care conine un singur element este un vector sortat. Algoritmul de interclasare se
poate folosi pentru sortarea unui vector cu ajutorul metodei divide et impera, astfel:
PAS1. Se descompune problema n subprobleme
10 8 7 9 5
similare, prin mprirea vectorului n doi sub-

ED
vectori, avnd mulimea indicilor [s,m] i
[m+1,d], unde m este indicele din mijlocul 10 8 7 9 5
intervalului: m=(s+d)/2.
PAS2. Dac subvectorul conine un singur element,

P
atunci se consider sortat (corespunde 10 8 7 9 5
cazului de baz); altfel, se continu descom-
I
punerea lui n subvectorii care au mulimea 10 8
indicilor [s,m] i mulimea indicilor [m+1,d].
PAS3. Se combin soluiile celor dou subpro-
bleme, prin interclasarea celor doi vectori 8 10

sortai, obinndu-se un vector sortat.


Vectorul care se sorteaz este x. Prin subprogramul
IC

interclaseaza() se realizeaz combinarea soluii- 7 8 10 5 9


lor prin interclasarea subvectorului x, care are muli-
mea indicilor [s,m], cu subvectorul x, care are muli-
CT

5 7 8 9 10
mea indicilor [m+1,d], n vectorul auxiliar v. Vectorul v
se copiaz n vectorul x, care are mulimea indicilor [s,d].
#include<iostream.h>
DA

int x[100],n;
void divizeaza(int s,int d,int &m) {m=(s+d)/2;}
void interclaseaza(int s,int d,int m)
{int i=s,j=m+1,k=1,v[100];
DI

while (i<=m && j<=d)


{if (x[i]<x[j]) {v[k]=x[i]; i++;}
else {v[k]=x[j]; j++;}
k++;}
RA

if (i<=m) while (i<=m) {v[k]=x[i]; i++; k++;}


else while (j<=d) {v[k]=x[j]; j++; k++;}
for (k=1,i=s;i<=d;k++,i++) x[i]=v[k];}
void MergeSort(int s,int d)
TU

{int m;
if (s<d) {divizeaza(s,d,m);
MergeSort(s,m);
MergeSort(m+1,d);
I
ED

interclaseaza(s,d,m);}}
54 Tehnici de programare

C
void main()
{int i; cout<<"n= ";cin>>n;
for(i=1;i<=n;i++) {cout<<"x["<<i<<"]= ";cin>>x[i];}

I
MergeSort(1,n);

OG
cout<<"vectorul sortat"<<endl; for(i=1;i<=n;i++) cout<<x[i]<<" ";}
Complexitatea algoritmului de sortare prin interclasare. Pentru divizarea problemei n
subprobleme se calculeaz mijlocul intervalului de indici i O(D(n))=(1). Pentru combi-
narea soluiilor se execut interclasarea a doi vectori i O(D(n))=O(n). Timpul de execuie

AG
k
este T(n)= 2T(n/2)+n. Considernd c n=2 , rezult:
k k k-1 k-1 k k-1 k k
T(n)=T(2 )+2 = 2(T(2 )+ 2 ) +2 = 2T(2 ) +2 +2 = ... =
k-2 k-2 k k 2 k-2 k-2 k k k k
22(T(2 )+ 2 ) +2 +2 = 2 (T(2 )+ 2 ) +2 +2 +2 = k2 = log2n n.
Ordinul de complexitate al algoritmului este O(nlog2n).

ED
Observaie. n comparaie cu algoritmii de sortare prin metoda seleciei directe i prin metoda
2
bulelor, care au ordinul de complexitate O(n ), algoritmii de sortare care folosesc strategia
divide et impera sunt mai eficieni.

P
1. S se rearanjeze elementele unui vector astfel nct n vector s se
Tem gseasc mai nti numerele impare i apoi numerele pare. Se vor
realiza dou versiuni ale programului, cte una pentru fiecare meto-
I
d de sortare care folosete strategia divide et impera.
2. ntr-un fiier text sunt scrise urmtoarele informaii: pe primul rnd numrul de elevi din
clas n, iar pe urmtoarele n rnduri urmtoarele informaii despre un elev: numele,
prenumele i mediile semestriale la disciplina informatic. n cadrul unui rnd datele

sunt separate prin spaiu. S se scrie un program care s realizeze urmtoarele cerine.
IC

Fiecare cerin va fi rezolvat printr-un subprogram. Ordonarea elementelor vectorului i


cutarea unui elev n vector se vor face folosind algoritmii cei mai eficieni.
a. Se citesc datele din fiierul text i se calculeaz media anual a fiecrui elev.
CT

b. Se rearanjeaz datele n ordinea alfabetic a numelui i prenumelui elevilor.


c. Pentru numele i prenumele unui elev, citite de la tastatur, se afieaz mediile
semestriale i media anual.
d. Se scriu informaiile obinute n urma prelucrrilor ntr-un alt fiier text.
DA

1.4.6. Problema turnurilor din Hanoi


Pe trei tije notate cu A, B i C se pot monta discuri perforate de diferite dimensiuni. Iniial
DI

pe tija A (tija surs) sunt aezate unele peste altele n discuri n ordinea descresctoare a
diametrelor, iar celelalte tije sunt goale. S se afieze toate mutrile care trebuie fcute
ca discurile de pe tija A s fie aranjate pe tija B (tija destinaie) n aceeai ordine n care
erau pe tija A, folosind tija C ca tij de manevr. O mutare nu se poate face dect cu un
RA

disc i el nu poate fi aezat pe o tij dect peste un disc cu diametrul mai mare.
S analizm mutrile care trebuie fcute pentru n=3:
Se mut discul de pe tija A pe tija B (1).
Se mut discul de pe tija A pe tija C (2).
TU

n discuri

Se mut discul de pe tija B pe tija C (3).


Se mut discul de pe tija A pe tija B (4).
Se mut discul de pe tija C pe tija A (5).
Se mut discul de pe tija C pe tija B (6).
I
ED

Se mut discul de pe tija A pe tija B (7).


Informatic 55

C
B B
1

I
A

OG
C C
3
Mut primele 2

AG
discuri pe tija de
2 manevr
B B

ED
4
A A

P
C C

Mut discul cu
I
diametrul maxim
pe tija destinaie
B B

7
IC

A A
CT

C 6 C

Mut cele dou


discuri pe tija
DA

5 destinaie
Folosind metoda divide et impera problema iniial va fi descompus n subprobleme astfel:
PAS1. Se mut primele n-1 discuri de pe tija surs pe tija de manevr.
PAS2. Se mut discul cu diametrul cel mai mare de pe tija surs pe tija destinaie.
DI

PAS3. Se mut cele n-1 discuri de pe tija de manevr pe tija destinaie.


#include<iostream.h>
RA

void hanoi(int n, char a, char b, char c)


{if (n==1) cout<<"Mutarea: "<<a<<"->"<<b<<endl;
else
{hanoi(n-1,a,c,b);
TU

cout<<"Mutarea: "<<a<<"->"<<b<<endl;
hanoi(n-1,c,b,a);}}
void main()
{int n; char a='A',b='B',c='C'; cout<<"n= "; cin>>n;
I

hanoi(n,a,b,c);}
ED
56 Tehnici de programare

C
1. S se determine numrul de partiii distincte ale 4
Tem unui numr natural n. Indicaie. Se descompune
numrul n n dou numere n1 i n2, dup care 3+1 2+2

I
fiecare numr nou obinut se descompune n alte 2+1

OG
dou numere. Procesul de descompunere continu pn cnd n1<n2.
Numrul de partiii este egal cu numrul de descompuneri obinute. 1 1
2. ntr-un parc cu o suprafa dreptunghiular care are coordonatele colului din stnga sus
(X1,Y1) i ale colului din dreapta jos (X2,Y2) se gsesc n copaci. Poziia fiecrui copac

AG
pe teren este dat de coordonatele (xi,yi). n parc trebuie amenajat un teren de joac
pentru copii, de form dreptunghiular, cu laturile paralele cu laturile parcului. S se
determine dreptunghiul cu arie maxim pe care se poate amenaja terenul de joac fr
s se taie nici un copac. Indicaie. Considernd c un copac i mparte dreptunghiul
iniial n patru dreptunghiuri cu laturile paralele cu dreptunghiul iniial, problema se

ED
descompune n patru subprobleme, fiecare subproblem rezolvnd cazul unuia dintre
cele patru dreptunghiuri, care au coordonatele colurilor ((X1,Y1); (xi, Y2)), ((xi, Y1);
(X2,Y2)), ((X1,Y1); (X2,yi)) i ((X1, yi); (X2,Y2)). La cazul de baz se ajunge atunci cnd
dreptunghiul nu conine nici un copac. Pentru fiecare dreptunghi care nu conine nici un

P
copac se calculeaz aria i se memoreaz coordonatele colurilor. Din combinarea
soluiilor obinute se identific dreptunghiul care are aria cea mai mare.
I
3. ntr-un vector sunt memorate mai multe numere ntregi. S se plieze repetat vectorul,
pn cnd rmne un singur element, i s se afieze valoarea acestui element. Plierea
unui vector nseamn suprapunerea unei jumti (numit donatoare) peste cealalt
jumtate (numit receptoare). Dac numrul de elemente ale vectorului este impar,

elementul din mijloc se elimin. De exemplu, pentru vectorul {1,2,3,4,5,6,7}, considernd


prima jumtate ca fiind cea receptoare, vectorul obinut dup prima pliere este {5,6,7}.
IC

1.4.7. Generarea modelelor fractale


CT

Modelele fractale sunt modele matematice care descriu fenomene sau obiecte care au o
structur periodic. Ele pot fi folosite i n grafic, pentru desenarea unor forme geometrice
complexe.
DA

n descrierea matematic a formei geometrice se pornete de la un nucleu, care, n urma


unui proces iterativ, este generat succesiv la scri diferite. Numrul de iteraii reprezint
ordinul curbei. Un exemplu clasic este forma geometric cunoscut sub numele de curba
lui Koch, care se genereaz astfel:
DI

PAS1. Se pornete de la nucleul care este un triunghi echilateral, cu latura avnd lungi-
mea finit L.
PAS2. Fiecare latur a triunghiului este mprit n trei segmente egale. Segmentul din
mijloc este eliminat i nlocuit cu un unghi care are laturile egale cu el.
RA

PAS3. Pentru fiecare iteraie se repet Pasul 2, pentru fiecare segment al figurii obinute.
TUI
ED
Informatic 57

C
Se obine o construcie perfect regulat. Dup fiecare iteraie cresc: numrul de unghiuri,
numrul de laturi ale poligonului i perimetrul poligonului. Notm cu p perimetrul nucleu
(triunghiul echilateral de la care se pornete). n procesul de construcie a curbei, la fiecare

I
iteraie, fiecare latur Li a triunghiului echilateral este mprit n trei segmente de lungime

OG
egal (Li/3) i este nlocuit cu 4 astfel de segmente (4Li/3). Dup n iteraii, perimetrul
n
poligonului va fi p(4/3) .
Pentru realizarea construciei se folosesc urmtoarele 3 elemente:

AG
iniiator generator nucleu
(n=0) (n=1)

ED
Pentru construirea poligonului trebuie desenat fiecare latur. Pentru fiecare latur se
cunosc: coordonatele x1 i y1, lungimea segmentului L i x2,y2
unghiul . Coordonatele x2 i y2 se pot determina:
L
x2=x1+Lcos() i y2=y1+Lsin().
x1,y1

P
Pentru desenarea segmentului se folosete funcia line()
implementat n biblioteca graphics.h: line(x1,y1,x2,y2).
Desenarea poligonului nseamn desenarea fiecrei laturi, care este determinat de coor-
I
donatele x1 i y1, lungimea segmentului L i unghiul . Problema se reduce la generarea
datelor care caracterizeaz fiecare latur i la desenarea unei linii folosind aceste date.
Generarea laturilor poligonului este un proces recursiv n care iniiatorul care are lungimea

L este nlocuit cu generatorul. Generatorul este format din patru segmente, fiecare segment
avnd lungimea L/3. Acest proces poate fi descompus n patru procese.
IC

Folosind metoda divide et impera pentru a genera curba lui Koch de ordinul n, problema
iniial va fi descompus n patru subprobleme, astfel (subprogramul Koch()):
PAS1. Se genereaz primul segment, care este un segment cu lungimea L/3 i cu aceeai
CT

orientare cu a iniiatorului. El devine iniiatorul curbei lui Koch de ordinul n-1.


0
PAS2. Se genereaz al doilea segment, prin rotirea segmentului obinut cu 60 spre stn-
ga (subprogramul stanga()). El devine iniiatorul curbei lui Koch de ordinul n-1.
0
PAS3. Se genereaz al treilea segment, prin rotirea segmentului obinut cu 120 spre dreap-
DA

ta (subprogramul dreapta()). El devine iniiatorul curbei lui Koch de ordinul n-1.


0
PAS4. Se genereaz al patrulea segment, prin rotirea segmentului obinut cu 60 spre
stnga (subprogramul stanga()). El devine iniiatorul curbei lui Koch de ordinul n-1.
DI

Procesul de descompunere se termin cnd se ajunge la ordinul 0 i se obine iniiatorul, care


se va desena (subprogramul deseneaza()).
Pentru desenarea poligonului, se construiete nucleul (se genereaz cele trei laturi ale
triunghiului echilateral de lungime L) i pentru fiecare latur se construiete curba lui
RA

Koch de ordinul n (subprogramul nucleu_Koch()) .


#include<iostream.h>
#include<math.h>
TU

#include<graphics.h>
int x,y;
float alfa;
void stanga(float unghi)
I

{alfa+=unghi*M_PI/180.;}
ED
58 Tehnici de programare

C
void dreapta(float unghi)
{alfa-=unghi*M_PI/180.;}
void deseneaza(float L)

I
{x1=x; y1=y; x+=(int)(L *cos(alfa); y+=(int)(L*sin(alfa);

OG
line(x,y,x1,y1);}
void Koch(int n, float L)
{if (n==0) deseneaza(L);
else

AG
{Koch(n-1,L/3); stanga(60);
Koch(n-1,L/3); dreapta(120);
Koch(n-1,L/3); stanga(60);
Koch(n-1,L/3);}}

ED
void nucleu_Koch(int n,float L)
{Koch(n,L); dreapta(120);
Koch(n,L); dreapta(120);
Koch(n,L); dreapta(120);}

P
void main()
{int n,L;
cout<<"n= "; cin>>n; cout<<"L= "; cin>>L;
I
nucleu_Koch(n,L);}
1. Desenai praful lui Cantor, care este generat astfel: un segment de
Tem lungimea L, care este paralel cu axa Ox, este mprit n cinci

segmente egale, din care se elimin segmentul din mijoc i se


repet acest proces de n ori pentru fiecare segment rmas.
IC

2. Desenai curba lui Koch, definit prin urmtoarele trei elemente, n care fiecare
segment al generatorului are lungimea L/4, unde L este lungimea segmentului iniiator.
CT

iniiator
(n=0) generator nucleu
DA

(n=1)
3. Desenai curba dragonului, definit prin urmtoarele trei elemente, n care fiecare seg-
ment al generatorului are lungimea L/sqrt(2), unde L este lungimea segmentului iniiator.
DI

iniiator
(n=0)
RA

generator curba de nucleu


(n=1) ordinul n=2
4. S se deseneze figura geometric obinut astfel: se deseneaz un ptrat cu latura L,
se deseneaz un ptrat care unete mijloacele laturilor ptratului iniial i se repet
TU

acest proces de n ori pentru fiecare ptrat obinut.


5. S se deseneze covorul lui Sierpinski, astfel: se deseneaz un ptrat cu latura L, se
mparte acest ptrat n 9 ptrate egale, se haureaz ptratul din mijloc i se repet
acest proces de n ori pentru fiecare ptrat nehaurat.
I
ED
Informatic 59

C
1. 5. Metoda greedy

I
1.5.1. Descrierea metodei greedy

OG
Metoda greedy se poate folosi pentru problemele n care, dndu-se o mulime finit A,
trebuie determinat o mulime SA care s ndeplineasc anumite condiii. Metoda furni-
zeaz o singur soluie, reprezentat prin elementele mulimii S. Ca i n cazul metodei
backtracking, soluia problemei este dat de un vector S = {x1, x2, , xn} ale crui elemente

AG
aparin ns unei singure mulimi A. Spre deosebire de metoda backtracking, metoda Greedy
nu gsete dect o singur soluie i, n general, aceast soluie este soluia optim.

ED
Scop: identificarea problemelor n care soluia optim este o submulime inclus ntr-o
mulime dat, care trebuie s ndeplineasc anumite condiii.
Enunul problemei 1: S se repartizeze optim o resurs (de exemplu, o sal de specta-

P
cole, o sal de conferine, o sal de sport) mai multor activiti (spectacole, prezentri de
produse, respectiv meciuri) care concureaz pentru a obine resursa respectiv.
I
Mulimea A este format din cele n activiti. Fiecare activitate i (1 i n) are un timp de
ncepere ti i un timp de terminare fi, unde ti < fi i ocup resursa n intervalul de timp
[ti,fi]. Dou activiti i i j sunt compatibile dac intervalele lor de ocupare [ti,fi] i [tj,fj] sunt
disjuncte, adic dac fi tj sau dac fj ti. Cerina problemei este de a selecta o mulime

maximal de activiti compatibile. n acest caz, mulimea S este format din activitile
care vor folosi resursa, iar condiia pe care trebuie s o ndeplineasc elementele mulimii S
IC

este ca ele s fie activiti compatibile. n plus, pentru ca repartizarea resursei s fie optim,
trebuie ca mulimea S s conin maximul de elemente care ndeplinesc aceast condiie.
CT

Enunul problemei 2: S se ocupe optim un mijloc de transport (de exemplu, un ruc-


sac, un autocamion) care are o capacitate maxim de ocupare (care poate transporta o
greutate maxim G) cu n obiecte, fiecare obiect avnd greutatea gi i un profit obinut n
urma transportului ci, iar din fiecare obiect putnd s se ia o fraciune xi[0,1] .
DA

Mulimea A este format din cele n obiecte. Fiecare obiect i (1in) are o eficien a trans-
portului ei care reprezint profitul pentru o unitatea de greutate. Cerina problemei este de a
selecta o mulime de obiecte astfel nct eficiena transportului s fie maxim. Mulimea S
este format din obiectele care vor ocupa mijlocul de transport, iar condiia pe care trebuie s
DI

o ndeplineasc elementele mulimii S este ca, prin contribuia adus de fiecare obiect la
eficiena transportului, s se obin o eficien maxim, iar greutatea obiectelor selectate s
fie egal cu greutatea maxim a transportului.
RA

Enunul problemei 3: Pentru dou mulimi de numere ntregi nenule: C cu n elemente,


C = {c1,c2, , cn} i A cu m elemente, A = {a1,a2, , am}, i nm, s se selecteze o
submulime de n numere din mulimea A, astfel nct expresia:
E = c1 x1 + c2 x2 + + cn xn
TU

n care xiA, s aib valoarea maxim.


n acest caz, mulimea S = {x1,x2, , xn}, n care xiA, trebuie s ndeplineasc condiia:
E = c1 x1 + c2 x2 + + cn xn = Emax
Criteriul de alegere a elementelor xi este urmtorul: dac n mulimea A mai exist elemente
I
ED

care au acelai semn cu coeficientul ci, se va alege elementul aj pentru care termenul ci xj
60 Tehnici de programare

C
are valoarea maxim (deoarece acest termen se adun la valoarea expresiei), iar dac n
mulimea A nu mai exist elemente care au acelai semn cu coeficientul ci, se va alege
elementul aj pentru care termenul ci xj are valoarea minim (deoarece acest termen se

I
scade din valoarea expresiei).

OG
Enunul problemei 4: S se plteasc o sum s cu un numr minim de bancnote cu
valori date. Se consider c din fiecare tip de bancnot se poate folosi un numr nelimitat
de bancnote, iar pentru ca problema s aib soluie, vom considera c exist i bancnote
cu valoarea 1.

AG
Mulimea A este format din cele n valori distincte ale bancnotelor. Cerina problemei este
de a selecta o mulime minim de bancnote pentru plata sumei s. n acest caz, mulimea S
este format din valorile cu care se va face plata, iar condiia pe care trebuie s o nde-
plineasc elementele mulimii S este ca, prin adunarea sumelor pariale pltite cu

ED
bancnotele cu valorile alese, s se obin suma de plat s. Pentru ca numrul de
bancnote s fie ct mai mic, trebuie s se caute ca plata s se fac n bancnote cu
valori ct mai mari.

P
Metoda greedy construiete soluia prin selectarea, dintr-o mulime de elemente,
a elementelor care ndeplinesc o anumit condiie. Pentru ca elementele
care se selecteaz s aparin soluiei optime, la pasul k se alege candidatul
I
optim pentru elementul xk al soluiei.
Spre deosebire de metoda backtracking, la metoda greedy, alegerea elementului xk al
soluiei este irevocabil (nu se mai poate reveni asupra alegerii fcute).

Metoda greedy poate duce la obinerea soluiei optime n cazul problemelor care au pro-
IC

prietatea de optim local, adic soluia optim a problemei cu dimensiunea n a datelor de


intrare conine soluiile optime ale subproblemelor similare cu problema iniial, dar de
dimensiune mai mic. Metoda greedy se mai numete i metoda optimului local.
CT

Paii algoritmului greedy sunt:


PAS1. Se iniializeaz mulimea S cu mulimea vid: S.
PAS2. Ct timp S nu este soluie a problemei i A, execut:
PAS3. Se alege din mulimea A elementul a care este candidatul optim al soluiei.
DA

PAS4. Se elimin elementul a din mulimea A.


PAS5. Dac el poate fi element al soluiei, atunci elementul a se adaug la
mulimea S. Se revine la Pasul 2.
PAS6. Dac mulimea S este soluia problemei, atunci se afieaz soluia; altfel, se
DI

afieaz mesajul Nu s-a gsit soluie


Algoritmul greedy este un algoritm iterativ, care determin soluia optim a problemei n
urma unor succesiuni de alegeri care reduc dimensiunea problemei respective: se alege
RA

elementul x1 al soluiei, apoi elementul x2 al soluiei, .a.m.d. Altfel spus, elementul xk al


soluiei este determinat prin alegerea, din elementele rmase n mulimea A, a candidatului
optim pentru elementul xk al soluiei, iar determinarea urmtoarele n-k elemente ale soluiei
(rezolvarea subproblemei) se face numai dup ce a fost determinat elementul xk al soluiei.
TU

Alegerea fcut pentru elementul xk al soluiei poate depinde de alegerile fcute pentru
determinarea primelor k-1 elemente ale soluiei, dar nu depinde de alegerile ulterioare.
Pentru ca algoritmul greedy s conduc la obinerea soluiei optime, trebuie s fie ndepli-
I

nite dou condiii:


ED
Informatic 61

C
1. Alegerea optimului local pentru fiecare element al soluiei duce la alegerea soluiei
optime globale.
2. Soluia optim a problemei conine soluiile optime ale subproblemelor.

I
Aceasta nseamn c, pentru a fi siguri c algoritmul greedy construiete soluia optim a

OG
problemei, trebuie s se demonstreze c sunt ndeplinite cele dou condiii.
n rezolvarea multor probleme folosind strategia greedy, pentru a alege optimul local care
s duc la alegerea soluiei optime globale, mulimea A este ordonat dup criteriul
candidatului optim. Ordonarea mulimii dup criteriul candidatului optim nseamn rearan-

AG
jarea elementelor mulimii A astfel nct, dup extragerea unui element, urmtorul element
din mulimea A s reprezinte elementul care este cel mai ndreptit s fie ales ca element
al mulimii S. De exemplu:
n cazul repartizrii optime a unei resurse, o activitate nu poate ncepe dect dac se

ED
termin cea anterioar. A repartiza optim resursa nseamn a organiza ct mai multe
activiti. Din mulimea activitilor se alege ntotdeauna activitatea care are timpul de
terminare ct mai mic. n acest caz, candidatul optim este activitatea care are timpul de
terminare cel mai mic, iar ordonarea activitilor dup criteriul candidatului optim

P
nseamn ordonarea cresctoare dup timpul de terminare.
n cazul ocuprii optime a mijlocului de transport, trebuie ca eficiena transportului s
fie maxim. Din mulimea obiectelor, se aleg obiectele care au eficiena de transport ct
I
mai mare. n acest caz, candidatul optim este obiectul care are eficiena transportului
cea mai mare, iar ordonarea obiectelor dup criteriul candidatului optim nseamn ordo-
narea descresctoare dup eficiena transportului.
n cazul plii unei sume cu un numr minim de bancnote cu valoare dat, ca s se

foloseasc ct mai puine bancnote, trebuie ca plata s se fac n ct mai multe


IC

bancnote cu valoare foarte mare. n acest caz, candidatul optim este bancnota cu valoa-
rea cea mai mare, iar ordonarea dup criteriul candidatului optim nseamn ordonarea
descresctoare dup valoarea bancnotelor.
CT

1.5.2. Implementarea metodei greedy


Pentru implementarea metodei greedy se vor folosi dou subprograme:
DA

subprogramul sort() care ordoneaz mulimea A dup criteriul candidatului optim;


subprogramul greedy() care implementeaz metoda propriu-zis.
n exemplele urmtoare, datele de intrare vor fi citite dintr-un fiier text.
Exemplul 1. Problema planificrii optime a activitilor.
DI

Se folosesc urmtoarele date i structuri de date:


Pentru numrul de elemente ale celor dou mulimi se folosesc variabilele n numrul
de activiti (numrul de elemente ale mulimii A) i m numrul de activiti selectate
RA

pentru a forma soluia problemei (numrul de elemente ale mulimii S).


Pentru mulimea activitilor (mulimea A) se folosete vectorul a, ale crui elemente
sunt de tip nregistrare activitate care conine trei cmpuri, x i y pentru ora la
care ncepe activitatea, respectiv ora la care se termin activitatea i k pentru numrul
TU

activitii (este folosit ca un identificator al activitii).


Soluia (mulimea S) va fi memorat n vectorul s. n fiecare element al vectorului s se
memoreaz indicele elementului selectat din vectorul a, dup ce a fost sortat dup
criteriul candidatului optim.
I

Se folosesc urmtoarele subprograme:


ED
62 Tehnici de programare

C
Subprogramul citeste() pentru citirea datelor din fiierul text. n fiierul text, pe
primul rnd este scris numrul de activiti n, iar pe urmtoarele n rnduri perechi de
numere ntregi, separate prin spaiu, care reprezint ora de nceput i ora de sfrit ale

I
unei activiti. Fiecrei activiti i se atribuie ca identificator numrul de ordine de la citi-

OG
rea din fiier. n urma execuiei acestui subprogram, se creeaz vectorul activitilor a.
Subprogramul sort() sorteaz vectorul a cresctor dup timpul de terminare a
activitilor (cmpul y).
Subprogramul greedy() implementeaz strategia greedy pentru aceast problem.

AG
Subprogramul afiseaza() afieaz soluia problemei folosind informaiile din
vectorul s indicele fiecrei activiti selectate.
Strategia greedy este implementat astfel:
PAS1. Se iniializeaz vectorul s cu indicele primului element din vectorul a (se selec-

ED
teaz, ca prim activitate, activitatea care are ora de terminare cea mai mic).
PAS2. Pentru urmtoarele n-1 elemente ale vectorului a, execut
PAS3. Dac ora la care ncepe activitatea din elementul curent al vectorului a
este mai mare sau egal cu ora la care se termin ultima activitate adu-

P
gat la soluie (n vectorul s), atunci activitatea este adugat la soluie.
Mulimea activitilor
I
Activitatea 1 2 3 4 5 6 7 8
Ora de ncepere 9 12 8 10 16 14 20 19
Ora de terminare 11 13 10 12 18 16 22 21

Mulimea activitilor dup ce a fost sortat


IC

Activitatea 3 1 4 2 6 5 8 7
Ora de ncepere 8 9 10 12 14 16 19 20
Ora de terminare 10 11 12 13 16 18 21 22
CT

Soluia problemei
Activitatea 3 4 2 6 5 8
DA

Ora de ncepere 8 10 12 14 16 19
Ora de terminare 10 12 13 16 18 21
Programul este:
#include<fstream.h>
DI

struct activitate {int x,y,k;};


activitate a[20];
int n,m,s[20];
RA

fstream f("greedy1.txt",ios::in);
void citeste()
{int i; f>>n;
for(i=1;i<=n;i++) {f>>a[i].x>>a[i].y; a[i].k=i;} f.close();}
TU

void sort()
{int i,j; activitate aux;
for (i=1;i<n;i++)
for (j=i+1;j<=n;j++)
I

if (a[i].y>a[j].y) {aux=a[i]; a[i]=a[j]; a[j]=aux;}}


ED
Informatic 63

C
void greedy()
{int i,j; s[1]=1; j=1;
for (i=2;i<=n;i++)

I
if (a[i].x>=a[s[j]].y) {j++; s[j]=i;}

OG
m=j;}
void afiseaza()
{cout<<"Planificarea activitatilor: "<<endl;
for (int i=1;i<=m;i++)

AG
cout<<"Activitatea "<< a[s[i]].k<<" incepe la ora ";
cout<<a[s[i]].x <<" si se termina la ora "<<a[s[i]].y<<endl;}
void main()
{citeste(); sort(); greedy(); afiseaza();}

ED
ntr-o sal de spectacole trebuie planificate n spectacole care au loc n
Tem aceeai zi, fiecare spectacol avnd o or la care trebuie s nceap i o
durat de desfurare. Scriei un program care s planifice optim ocu-
parea slii de spectacole.

P
Exemplul 2. Problema ocuprii optime a mijlocului de transport (problema rucsacului).
Se folosesc urmtoarele date i structuri de date:
I
Pentru numrul de elemente ale celor Mulimea obiectelor G=20
dou mulimi se folosesc variabilele n
numrul de obiecte (numrul de elemente Obiectul 1 2 3 4 5
ale mulimii A) i m numrul de obiecte Greutatea 5 4 4 8 10

selectate pentru a forma soluia problemei Profitul 10 20 10 10 22


IC

(numrul de elemente ale mulimii S).


Eficiena 2 5 2,5 1,25 2,2
Pentru greutatea maxim care se poate
transporta, se folosete variabila G, iar Mulimea obiectelor dup ce a fost sortat
CT

pentru greutatea obiectelor care se mai pot Obiectul 2 3 5 1 4


selecta, se folosete variabila Gr (greuta-
tea rmas). Variabila Gr este iniializat Greutatea 4 4 10 5 8
cu valoarea G (iniial, greutatea obiectelor Profitul 20 10 22 10 10
DA

care se pot selecta este greutatea maxim Eficiena 5 2,5 2,2 2 1,25
de transport), iar dup ce s-a construit
soluia, variabila Gr are valoarea 0 (nu se Soluia problemei
mai pot selecta obiecte, deoarece a fost Obiectul 2 3 5 1 4
DI

ocupat toat capacitatea de transport). Greutatea 4 4 10 5 8


Pentru mulimea obiectelor (A) se folo-
sete vectorul a, ale crui elemente sunt Fraciunea 1 1 1 0,2 0
de tip nregistrare obiect, care conine Greutatea 4 4 10 2 0
RA

patru cmpuri: g greutatea obiectului, c


profitul obinut n urma transportului, e eficiena transportului i k numrul
obiectului (este folosit ca un identificator al obiectului).
Soluia (mulimea S) va fi memorat n vectorii s i x. n fiecare element al vectorului s se
TU

memoreaz indicele obiectului selectat din vectorul a, dup ce a fost sortat dup criteriul
candidatului optim, iar n elementul din vectorul x care are acelai indice cu cel din
vectorul s se memoreaz fraciunea de cantitate care se va lua din obiectul selectat.
Elementele vectorului x sunt iniializate cu valoarea 0 (vectorul este declarat global).
I
ED
64 Tehnici de programare

C
Se folosesc urmtoarele subprograme:
Subprogramul citeste() pentru citirea datelor din fiierul text. n fiierul text, pe primul
rnd este scris numrul de obiecte n i greutatea maxim a transportului G, iar pe

I
urmtoarele n rnduri perechi de numere reale, separate prin spaiu, care reprezint

OG
greutatea i profitul transportului unui obiect. Fiecrui obiect i se atribuie, ca identificator,
numrul de ordine de la citirea din fiier. Pentru fiecare obiect se calculeaz eficiena
transportului. n urma execuiei acestui subprogram se creeaz vectorul obiectelor, a.
Subprogramul sort() sorteaz vectorul a, cresctor dup eficiena transportului

AG
obiectelor (cmpul e).
Subprogramul greedy() implementeaz strategia greedy pentru aceast problem.
Subprogramul afiseaza() afieaz soluia problemei folosind informaiile din vectorii
s i x indicele fiecrui obiect selectat i fraciunea din greutate care se va transporta.

ED
Strategia greedy este implementat astfel:
PAS1. Se iniializeaz greutatea Gr cu valoarea G i selectarea obiectelor ncepe cu obi-
ectul cu cea mai mare eficien a transportului (primul obiect din vectorul a).
PAS2. Ct timp mai exist obiecte care nu au fost selectate i greutatea obiectelor

P
selectate nu este greutatea maxim, execut
PAS3. Dac greutatea obiectului din elementul curent al vectorului a este mai
mic sau egal cu greutatea rmas, Gr, atunci obiectul este adugat la
I
soluie, lundu-se ntreaga cantitate disponibil din obiect; altfel, se ia din
obiect fraciunea egal cu greutatea rmas Gr. Se actualizeaz greutatea
Gr diminund-o cu greutatea obiectului care a fost adugat n rucsac.

Programul este:
#include<fstream.h>
IC

struct obiect {int k;


float g,c,e;};
obiect a[20];
CT

int n,m,s[20];
float G,Gr,x[20];
fstream f("greedy2.txt",ios::in);
void citeste()
DA

{int i; f>>n>>G;
for(i=1;i<=n;i++)
{f>>a[i].g>>a[i].c; a[i].k=i; a[i].e=a[i].c/a[i].g;} f.close();}
void sort()
DI

{int i,j; obiect aux;


for (i=1;i<n;i++)
for (j=i+1;j<=n;j++)
RA

if (a[i].e<a[j].e) {aux=a[i]; a[i]=a[j]; a[j]=aux;}}


void greedy()
{int i,j=0; Gr=G;
for (i=1;i<=n && Gr!=0;i++)
TU

if (Gr>a[i].g) {j++; s[j]=i; x[j]=1; Gr-=a[i].g;}


else {j++; s[j]=i; x[j]=Gr/a[i].g; Gr=0;}
m=j;}
void afiseaza()
I

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


ED
Informatic 65

C
{cout<<"Obiectul "<< a[s[i]].k<<" in cantitatea ";
cout<<x[i]* a[s[i]].g<<endl;}}
void main()

I
{citeste(); sort(); greedy(); afiseaza();}

OG
Observaie. n problema rucsacului exist dou situaii:
1. Obiectele pot fi fracionate problema continu a rucsacului;
2. Obiectele nu pot fi fracionate problema discret a rucsacului.
Algoritmul greedy furnizeaz soluia optim numai n cazul problemei continue a

AG
rucsacului. De exemplu, pentru patru obiecte: a (20 kg, 110 lei), b (9 kg, 45 lei), c (9 kg, 45
lei) i d (6 kg, 30 lei) i greutatea maxim de transport 25 kg:
Soluia greedy: obiectul a profitul transportului = 110;
Soluia optim: obiectele b, c i d profitul transportului = 120.

ED
ntr-un rucsac se pot transporta maximum G kg. Exist n obiecte, fieca-
Tem re obiect avnd greutatea gi i valoarea vi. Obiectele pot fi fracionate.
Scriei un program care s gseasc obiectele care trebuie transportate

P
n rucsac, astfel nct s se obin cea mai valoroas ncrctur.
Exemplul 3. Problema expresiei de valoare maxim.
I
Se folosesc urmtoarele date i structuri de date:
Pentru mulimea coeficienilor C se folosete vectorul c cu n elemente, iar pentru
mulimea numerelor A se folosete vectorul a cu m elemente. Elementele vectorilor sunt
de tip int.

Pentru calcularea valorii expresiei se folosete variabila exp, care este iniializat cu
valoarea 0 (este variabil global), iar pentru a numra elementele selectate din
IC

mulimea A se folosete variabila k, care este iniializat cu valoarea 0.


Se folosesc urmtoarele subprograme:
CT

Subprogramul citeste() pentru citirea datelor din fiierul text. n fiierul text, pe
primul rnd sunt scrise dou numere ntregi, n i m, care reprezint numrul de
elemente ale celor dou mulimi, pe rndul al doilea cei n coeficieni, iar pe rndul al
treilea cele m numere ntregi din mulimea A. Valorile numerice de pe un rnd sunt
DA

separate prin spaiu. n urma execuiei acestui subprogram se creeaz vectorii c i a.


Subprogramul sort() se folosete pentru a sorta cresctor cei doi vectori c i a.
Subprogramul greedy() implementeaz strategia greedy pentru aceast problem i
afieaz soluia n timp ce o construiete.
DI

Strategia greedy este implementat astfel:


PAS1. Se calculeaz termenii pentru care valorile coeficientului ci i ale numrului aj sunt
pozitive. Pentru ca expresia s fie maxim, parcurgerea celor doi vectori se face de la
ultimul element ctre primul element (de la cele mai mari numere pozitive, ctre cele
RA

mai mici numere pozitive). Se memoreaz, n variabila p, indicele elementului din


vectorul c care urma s fie selectat la terminarea parcurgerii, iar n variabila r indi-
cele elementului din vectorul a care urma s fie selectat la terminarea parcurgerii.
PAS2. Se calculeaz termenii pentru care valorile coeficientului ci i ale numrului aj
TU

sunt negative. Pentru ca expresia s fie maxim, parcurgerea celor doi vectori se
face de la primul element ctre ultimul element (de la cele mai mari numere nega-
tive, ctre cele mai mici numere negative).
I
ED
66 Tehnici de programare

C
PAS3. Coeficienii rmai pot fi numai pozitivi n=5 i m=7 Emax = 97
sau numai negativi. n cazul n care sunt
Indici 1 2 3 4 5 6 7
numai negativi, n mulimea A au rmas

I
numai numere pozitive. Termenii care se ci -2 -1 3 4 5

OG
calculeaz fiind negativi, pentru ca ai -5 -4 -1 2 5 7 8
expresia s fie maxim vor trebui s aib si -5 -4 5 7 8
valoarea ct mai mic i vectorii se vor
parcurge n continuare, ctre ultimul n=6 i m=7 Emax = 77

AG
element (coeficienii sunt numere negati- Indici 1 2 3 4 5 6 7
ve din ce n ce mai mici, iar numerele din ci -5 -4 -3 -1 4 5
vectorul a sunt numere pozitive din ce n
ai -5 -4 1 2 3 4 5
ce mai mari). n cazul n care coeficienii
rmai sunt numai pozitivi, n mulimea A si -5 -4 1 2 4 6

ED
au rmas numai numere negative. n=6 i m=7 Emax = 21
Termenii care se calculeaz fiind nega- Indici 1 2 3 4 5 6 7
tivi, pentru ca expresia s fie maxim vor
trebui s aib valoarea ct mai mic i ci -2 -1 3 4 5 5

P
vectorii se vor parcurge astfel: vectorul c ai -6 -5 -4 -3 -1 1 2
ncepnd de la elementul p ctre primul si -6 -5 -3 -1 1 2
I
element, iar vectorul a ncepnd de la
elementul r ctre primul element (coeficienii sunt numere pozitive din ce n ce mai
mici, iar numerele din vectorul a sunt numere negative din ce n ce mai mari).
Programul este:

#include<fstream.h>
IC

int n,m,p,r,c[20],a[20],exp;
fstream f("greedy3.txt",ios::in);
void citeste()
CT

{int i; f>>n>>m;
for(i=1;i<=n;i++) f>>c[i];
for(i=1;i<=m;i++) f>>a[i];
f.close();}
DA

void sort(int v[], int n)


{int i,j,aux;
for (i=1;i<n;i++)
for (j=i+1;j<=n;j++)
DI

if (v[i]>v[j]) {aux=v[i]; v[i]=v[j]; v[j]=aux;}}


void greedy()
{int i=n,j=m,k=0; //indici: ivector c, jvector a, kvector b
cout<<"E= ";
RA

while (c[i]>0 && a[j]>0 && k<n)


{k++; cout<<"("<<c[i]<<")*("<<a[j]<<")+";
exp+=c[i]*a[j]; i--; j--;}
p=j; i=1; j=1;
TU

while (c[i]<0 && a[j]<0 && k<n)


{k++; cout<<"("<<c[i]<<")*("<<a[j]<<")+";
exp+=c[i]*a[j]; i++; j++;}
I

if (c[i]<0)
ED

while (k<n)
Informatic 67

C
{k++; cout<<"("<<c[i]<<")*("<<a[j]<<")+";
exp+=c[i]*a[j]; i++; j++;}
else

I
{i=p;j=r;

OG
while (k<n)
{k++; cout<<"("<<c[i]<<")*("<<a[j]<<")+";
exp+=c[i]*a[j]; i--; j--;}}
cout<<'\b'<<" = "<<exp;}

AG
void main()
{citeste(); sort(c,n); sort(a,m); greedy();}
Justificarea criteriului candidatului optim. Considerm cazul n care coeficienii sunt
numere ntregi pozitive care au fost ordonate cresctor i exist cel puin n numere pozitive

ED
n mulimea A. Conform criteriului candidatului optim, mulimea A a fost ordonat cresctor.
Dac C={c1,c2, , cn} cu cicj, pentru i<j i A={a1,a2, , am} cu aiaj, pentru i<j, atunci
S={x1,x2, , xn} cu xixj, pentru i<j i xn=am, xn-1=am-1, , x1=am-n+1. Este evident c
pentru a obine valoarea maxim a expresiei trebuie s se aleag cele mai mari n numere

P
din mulimea A. Trebuie s demonstrm dac este corect modul n care s-a construit
mulimea S cu aceste numere. Pentru alegerea fcut, expresia are valoarea E1.
E1 = c1 x1 + c2 x2 + + ci xi + + cj xj + + cn xn
I
S presupunem c exist o expresie E2 a crei valoare este mai mare dect a expresiei E1
(E2 >E1). n cel mai bun caz, n expresie ordinea numerelor din mulimea S difer numai
prin valorile din poziiile i i j, cu i<j i ci<cj i xi<xj.

E2 = c1 x1 + c2 x2 + + ci xj + + cj xi + + cn xn
Conform presupunerii fcute, nseamn c E2 E1 > 0. Dar,
IC

E2 E1 = ci (xj - xi) + cj (xi - xj) = (cj - ci) (xi - xj) < 0 i E2 <E1
ceea ce contrazice ipoteza de la care s-a plecat. n mod analog se justific i alegerea
elementelor mulimii S atunci cnd cei n coeficieni sunt negativi i n mulimea A exist cel
CT

puin n numere negative.


1. Justificai criteriul prioritii de alegere pentru cazul n care coeficienii
Tem sunt pozitivi i n mulimea A nu exist dect numere negative.
DA

2. Justificai criteriul prioritii de alegere pentru cazul n care coeficienii


sunt negativi i n mulimea A nu exist dect numere pozitive.
3. Refacei programul astfel nct s se determine valoarea minim a expresiei.
4. Fiind dat o mulime A cu n numere reale, s se determine o submulime a sa care are
DI

proprietatea c suma elementelor submulimii este maxim. Indicaie. Submulimea va


fi format din toate numerele pozitive, iar dac nu exist numere pozitive, din cel mai
mare numr din mulime.
5. Fiind date mulimea de numere reale A = {a1,a2, , am} i n, gradul unui polinom, cu nm,
RA

s se selecteze, din mulimea A, o submulime de n+1 numere pentru coeficienii


polinomului, astfel nct valoarea polinomului P(x) ntr-un punct x precizat s fie maxim.
6. La un cabinet medical, n sala de ateptare, se gsesc n pacieni. Timpul necesar
pentru consultarea unui pacient i este ti. Cunoscnd numrul de pacieni n i timpul
TU

necesar pentru fiecare consultaie ti, scriei un program care s afieze ordinea de
tratare a pacienilor, astfel nct timpul total de ateptare al pacienilor s fie minim.
Indicaie. Deoarece timpul de ateptare al unui pacient este egal cu suma timpilor de
consultaie ai pacienilor tratai naintea sa, ordonarea pacienilor dup criteriul
I
ED
68 Tehnici de programare

C
candidatului optim nseamn ordonarea cresctoare dup timpul de consultaie.
Demonstrai c soluia obinut astfel este soluia optim.
Exemplul 4. Problema plii unei sume cu un numr minim de bancnote cu valori

I
OG
date.
Se folosesc urmtoarele date i structuri de date:
Pentru valorile bancnotelor se folosete vectorul a cu n elemente (n reprezint numrul
de tipuri de bancnote).
Pentru suma care trebuie pltit se folosete variabila S.

AG
Se folosesc urmtoarele subprograme: n=4 i S=147 Numr total bancnote=9
Subprogramul citeste() pentru
Valoare bancnot 50 10 5 1
citirea datelor din fiierul text. n fiierul
text, pe primul rnd sunt scrise dou nu- Numr de bancnote 2 4 1 2

ED
mere ntregi, n i S, iar pe rndul urmtor cele n valori ale bancnotelor. Valorile
numerice de pe fiecare rnd sunt separate prin spaiu.
Subprogramul sort() se folosete pentru a sorta descresctor vectorul a.
Subprogramul greedy() implementeaz strategia greedy pentru aceast problem i

P
afieaz soluia n timp ce o construiete.
Strategia greedy este implementat astfel:
I
PAS1. Selectarea bancnotelor ncepe cu bancnota cu valoarea cea mai mare (prima
valoare din vectorul a).
PAS2. Ct timp nu a fost pltit toat suma, execut
PAS3. Dac o parte din suma rmas poate fi pltit n bancnote care au valoa-

rea elementului curent din vectorul a, atunci se determin numrul maxim


IC

de bancnote cu care se face plata (ctul dintre suma rmas i valoarea


bancnotei) i se calculeaz restul din sum care mai rmne de pltit.
PAS4. Se trece la urmtoarea valoare a bancnotei i se revine la Pasul 2.
CT

#include<fstream.h>
int n,m,S,a[20];
fstream f("greedy4.txt",ios::in);
void citeste()
DA

{int i; f>>n>>S;
for(i=1;i<=n;i++) f>>a[i]; f.close();}
void sort()
{int i,j,aux;
DI

for (i=1;i<n;i++)
for (j=i+1;j<=n;j++)
if (a[i]<a[j]) {aux=a[i]; a[i]=a[j]; a[j]=aux;}}
void greedy()
RA

{int i=1;
while (S!=0)
{if (S/a[i]!=0)
{cout<<S/a[i]<<" bancnote cu valoarea "<<a[i]<<endl;
TU

S=S%a[i];}
i++;}}
void main()
I

{citeste(); sort(n); greedy();}


ED
Informatic 69

C
Observaie. n plata sumei S cu bancnote de valori date pot s apar dou cazuri
(presupunnd c n moneda respectiv exist bancnote cu valorile precizate mai jos):
1. Suma este 48 i bancnotele au valorile 15, 5 i 4 (n=3). Algoritmul greedy nu va gsi nici

I
o soluie, deoarece va alege 3 bancnote cu valoarea 15, rmnnd un rest de sum cu

OG
valoarea de 3, pentru care nu mai exist bancnote ca s se plteasc. n realitate,
problema are o soluie: 2 bancnote cu valoarea 15, 2 bancnote cu valoarea 5, i 2 banc-
note cu valoarea 8.
2. Suma este 22 i bancnotele au valorile 9, 7, 5 i 1 (n=4). Algoritmul greedy nu va gsi

AG
soluia optim, deoarece va alege 2 bancnote cu valoarea 9, i 4 bancnote cu valoarea
1, n total 6 bancnote. Soluia optim este de a plti cu 4 bancnote: 3 bancnote cu
valoarea 7 i o bancnot cu valoarea 1.
Metoda greedy care nu furnizeaz soluia optim a problemei se numete metoda

ED
euristic greedy.
Ce relaie trebuie s existe ntre valorile bancnotelor pentru ca soluia
Tem greedy s furnizeze soluia optim?

P
Complexitatea algoritmului greedy
Algoritmul greedy propriu-zis are complexitatea O(n), deoarece se parcurg cele n elemente
I
ale mulimii A pentru a alege fiecare dintre cele m elemente ale soluiei. Algoritmul de sortare
folosit pentru aranjarea elementelor mulimii A dup criteriul candidatului optim are complexi-
tatea O(nlog2n) dac se alege un algoritm de sortare eficient, cum este de exemplu

algoritmul QuickSort. Complexitatea metodei greedy este O(n)+ O(nlog2n)= O(nlog2n).


Metoda greedy se recomand n urmtoarele cazuri:
IC

se dorete numai obinerea soluiei optime i suntem siguri c aplicnd strategia greedy
se obine soluia optim;
se dorete obinerea unei soluii acceptabile, nu neaprat optime, i algoritmul greedy
CT

este mult mai eficient dect ali algoritmi care pot duce la obinerea mai multor soluii sau
a soluiei optime.
1. Un automobilist pornete dintr-un ora A i trebuie s ajung n
Tem oraul B. Rezervorul autoturismului, dac este plin, i permite s
DA

parcurg n kilometri. Pe hart sunt trecute m staii de alimentare i


distanele dintre ele. Automobilistul dorete s opreasc la ct mai puine staii pentru
alimentarea autoturismului. Scriei un program care s determine staiile de benzin la
care trebuie s se opreasc pentru alimentare.
DI

2. ntr-un camping exist k csue care pot fi nchiriate 365 de zile din an. Orice turist poate
nchiria o csu pentru exact m zile consecutive din an. Campingul a adunat solicitrile
a n turiti pe un an ntreg, cu un an nainte. Fiecare turist precizeaz prima zi cu care
RA

dorete s nchirieze o csu (1, 2, ). S se determine numrul maxim de turiti care


vor putea fi primii n camping (k100, m20, n1000).
(Concursul Nemes Tihamr, 1998)
3. Un turist trebuie s strbat un traseu de munte. Pe hart, zona prin Nord
TU

care trebuie s treac are o form dreptunghiular, care este 2 1 1 3


mprit, prin caroiaje, n subzone, care au fiecare o anumit 2 1 2 1
nlime. Zona prin care trece turistul poate fi reprezentat printr-o 0 0 4 2
matrice ale crei elemente memoreaz nlimea fiecrei subzone. 3 1 2 3
I

Turistul pornete din sud, din orice subzon de pe hart, i trebuie s


ED

Sud
70 Tehnici de programare

C
ajung n nord, n orice subzon de pe hart, astfel nct s urce ct mai puin pe ntreg
traseul. El poate trece dintr-o zon n alta, numai mergnd n direciile: Est, Nord-Est,
Nord, Nord-Vest i Vest. Datele de intrare sunt dimensiunile matricei i matricea nlimilor

I
i se vor citi din fiier.

OG
4. ntr-o fabric s-a automatizat procesul de producie i, la sfritul zilei de munc, piesele
sunt adunate de roboi industriali. Fiecare robot poate strnge un anumit numr de piese.
Harta halei a fost mprit printr-un caroiaj i poate fi reprezentat printr-o matrice (nm)
ale crei elemente pot avea valorile: 0 (pentru locurile n care nu exist maini) i 1 (pentru

AG
locurile n care exist maini). Roboii se deplaseaz n spaiul de deasupra mainilor,
corespunztor aceluiai caroiaj. Roboii pornesc din colul din stnga sus (1,1) i trebuie
s duc piesele n colul din dreapta jos (n,m). Roboii sunt programai astfel nct s se
deplaseze doar la dreapta sau n jos. S se scrie un program care s determine numrul

ED
minim de roboi care trebuie pornii pentru a strnge toate piesele fabricate ntr-o zi.
(Concursul Nemes Tihamr, 1998)
5. ntr-un depozit al monetriei statului sosesc n saci cu monede. eful depozitului
cunoate numrul de monede din fiecare sac i vrea s modifice coninutul sacilor, prin

P
mutarea de monede dintr-un sac n altul, astfel nct, la sfrit, s fie n fiecare sac
acelai numr de monede. S se scrie un program care s determine, dac este posibil,
numrul minim de mutri prin care fiecare sac s conin acelai numr de monede,
I
altfel s se afieze un mesaj. Fiecare mutare se afieaz sub forma: sac iniial, sac final,
numr de monede. (n2000, iar numrul total de monede 1.000.000.000)
(ONI Oradea, 1998)

1.6. Metoda programrii dinamice


IC

1.6.1. Descrierea metodei programrii dinamice


Metoda programrii dinamice se poate folosi pentru problemele n care trebuie s fie
CT

gsit soluia optim i care au urmtoarele caracteristici:


1. Soluia optim se alege dintr-o mulime de soluii, fiecrei soluii putnd s i se asocieze
o valoare. Alegerea soluiei optime nseamn alegerea soluiei care are valoarea
DA

optim (minim sau maxim).


2. Problema poate fi descompus n subprobleme similare cu problema iniial ce
respect principiul optimalitii: soluia problemei este optim dac ea conine soluiile
optime ale subproblemelor.
DI

3. Subproblemele n care se descompune problema nu sunt independente.


4. Soluia problemei este dat de un vector S = {x1, x2, , xm} i:
exist o mulime finit A din care se poate alege un element xi al soluiei;
fiecare etap de determinare a unui element xi al soluiei se bazeaz pe rezultatele
RA

etapelor n care s-au determinat elementele anterioare ale soluiei;


numrul de posibiliti de a alege un element xi al soluiei se reduce din cauza cerin-
elor de optimizare i a restriciilor impuse soluiei.
TU

Metoda clasic de rezolvare a acestor probleme este de a cuta toate soluiile problemei
i de a alege, dintre soluiile gsite, soluia optim. Algoritmul de generare a tuturor
soluiilor nseamn generarea tuturor submulimilor de indici ai mulimii A cu n elemente
n
i are ordinul de complexitate O(2 ). Acest ordin de complexitate este inacceptabil
I

pentru o dimensiune mare a datelor de intrare n.


ED
Informatic 71

I C
Scop: identificarea problemelor care pot fi descompuse n subprobleme similare care

OG
nu sunt independente i care respect principiul optimalitii, soluiilor putnd s li se
asocieze o valoare, iar soluia optim determinndu-se prin calcularea valorii optime.
Enunul problemei 1: Se consider un triunghi de numere naturale
a11
aij cu n linii. Pornind de la numrul din linia 1, mergnd n jos pn la
linia n, s se determine o selecie de elemente astfel nct suma a21 a22

AG
elementelor s fie maxim. Trecerea la linia urmtoare se poate .
face numai mergnd n jos, direct sau pe diagonal, la dreapta. an1 an2 ann
Metoda clasic de rezolvare a acestei probleme este de a calcula toate sumele care se pot

ED
forma respectnd restricia de deplasare n triunghi i de a alege, dintre sumele gsite, suma
care are valoarea cea mai mare.
Mulimea datelor de intrare o reprezint mulimea A format din elementele aij ale triunghiului.
Valoarea asociat unei soluii este suma elementelor. Valoarea soluiei optime este valoa-

P
rea maxim (suma elementelor trebuie s fie maxim). Soluia problemei este dat de un
vector S = {x1, x2, , xn}, unde xiA. Pentru construirea soluiei se pornete de la elementul
a11 i se merge n jos, pn la linia n. Trecerea la linia urmtoare nu se poate face dect
I
direct, n jos sau pe diagonal, la dreapta, astfel nct succesorul elementului aij nu poate fi
dect elementul ai+1,j sau elementul ai+1,j+1. Problema poate fi descompus n subprobleme:
subproblema i este alegerea elementului xi al soluiei de pe linia i a triunghiului. Restricia

impus pentru soluie este ca elementul xi al soluiei s se obin, prin deplasarea n triunghi,
numai pe dou direcii, de la elementul anterior, limitnd mulimea elementelor din care se
IC

alege elementul xi al soluiei numai la elementele din triunghi care se gsesc ntr-o anumit
poziie fa de elementul anterior al soluiei. Pentru a respecta principiul optimalitii, suma
elementelor alese anterior trebuie s fie maxim. Subproblemele nu sunt independente
CT

deoarece n subproblema i alegerea elementului xi al soluiei se bazeaz pe alegerile fcute


n subproblemele anterioare.
Enunul problemei 2: Dndu-se un ir de numere s se determine subirul cresctor
de lungime maxim.
DA

Fiind dat un ir de numere a1, a2, , an, se definete ca subir cresctor, irul ai1, ai2, , aik,
cu ai1 ai2 aik i 1 i1 i2 ik. De exemplu, n irul de numere 1, -2, 3, 2, 4, 4,
un subir cresctor este 1, 3, 4, 4.
DI

Metoda clasic de rezolvare a acestei probleme este de a genera fiecare subir al mulimii A
i de a verifica dac este subir cresctor. Dintre subirurile cresctoare gsite se alege apoi
subirul care are lungimea cea mai mare.
Mulimea datelor de intrare o reprezint mulimea format din elementele irului: A={a1, a2,
RA

, an}. Valoarea asociat unei soluii este lungimea subirului cresctor. Valoarea
soluiei optime este valoarea maxim (lungimea subirului trebuie s fie maxim).
Soluia problemei este dat de un vector S = {x1, x2, , xm}, unde xiA. Problema poate
fi descompus n subprobleme: subproblema i este de a gsi subirul cresctor de lungime
TU

maxim care ncepe cu elementul ai. Restricia impus pentru soluie este ca elementul ai
cu care ncepe subirul s aib valoarea mai mic sau cel mult egal cu cea a succe-
sorului su n subir (aj), iar n mulimea A numrul lui ordine (i) trebuie s fie mai mic dect
numrul de ordine al succesorului (j), limitnd mulimea elementelor din care se alege
I
ED

succesorul aj. Metoda cea mai simpl de a gsi subirul de lungime maxim care ncepe cu
72 Tehnici de programare

C
elementul ai este de a cuta printre subirurile de lungime maxim descoperite n
subproblemele rezolvate anterior, cel mai lung subir care ncepe cu un element aj ce
poate fi succesor n subir al elementului ai, obinndu-se un nou subir, de lungime mai

I
mare, care ncepe cu elementul ai. Pentru a respecta principiul optimalitii, lungimea

OG
subirurilor descoperite anterior trebuie s fie maxim. Subproblemele nu sunt indepen-
dente deoarece n subproblema i alegerea subirului care ncepe cu elementul ai al
soluiei se bazeaz pe alegerile fcute n subproblemele anterioare.
Enunul problemei 3: O eav cu lungimea L trebuie s se confecioneze din n buci de

AG
eav, fiecare bucat avnd lungimea ai. O bucat de eav nu poate fi tiat. S se
gseasc, dac exist, soluia de a obine eava de lungime L prin sudarea unor buci de
eav cu lungimea ai.
Metoda clasic de rezolvare a acestei probleme este de a genera toate evile care se pot

ED
forma cu cele n buci de eav cu lungimile date i de a verifica dac lungimea evii obinute
este egal cu L.
Mulimea datelor de intrare o reprezint mulimea A format din lungimile bucilor de eav
ai. Valoarea asociat unei soluii este lungimea evii. Valoarea soluiei optime este L

P
(lungimea evii construite trebuie s fie L). Soluia problemei este dat de un vector S
= {x1, x2, , xm}, unde xiA. Problema poate fi descompus n subprobleme: subpro-
blema i este de a gsi toate evile care se pot confeciona adugnd bucata de eav cu
I
lungimea ai la evile care au fost construite n subproblema anterioar. Restricia impus
pentru evile care se construiesc este ca ele s nu depeasc lungimea L. Aceast
restricie limiteaz mulimea evilor construite anterior. Pentru a respecta principiul opti-

malitii, construcia evilor cu ajutorul bucii de eav cu lungimea ai se bazeaz numai


pe evile construite n subproblema anterioar, iar subproblemele nu sunt independente.
IC

Enunul problemei 4: ntr-un rucsac se poate transporta o greutate maxim G i exist n


obiecte, fiecare obiect avnd greutatea gi i un profit obinut n urma transportului ci, iar
CT

obiectele nu pot fi fracionate. S se selecteze obiectele care vor fi transportate n rucsac,


astfel nct s se obin profitul maxim (problema discret a rucsacului).
Metoda clasic de rezolvare a acestei probleme este de a genera toate posibilitile de a
ncrca rucsacul alegnd obiecte din cele n obiecte i de a verifica dac greutatea obiectelor
DA

nu depete greutatea de ncrcare a rucsacului G. Dintre variantele de ncrcare a rucsa-


cului se alege cea care are profitul cel mai mare.
Mulimea datelor de intrare o reprezint mulimea A format din cele n obiecte ai care pot fi
transportate n rucsac. Valoarea asociat unei soluii este profitul transportului. Valoarea
DI

soluiei optime este valoarea maxim (profitul trebuie s fie maxim). Soluia problemei
reprezint ncrctura optim a rucsacului i este dat de un vector S = {x1, x2, , xm},
unde xkA i 1km. Problema poate fi descompus n subprobleme: subproblema i este
RA

de a verifica dac obiectul ai poate fi element al soluiei. Restricia impus pentru soluia
care se construiete este ca obiectul ai s nu aib o greutate mai mare dect greutatea
disponibil a rucsacului i profitul lui s fie mai mare sau egal cu profitul utimului obiect
adugat n rucsac ai-1. Aceast restricie limiteaz mulimea elementelor din care se alege
TU

elementul xk al soluiei. Pentru a respecta principiul optimalitii, elementul xk al soluiei


se determin prin alegerea dintre dou obiecte a celui care are profitul mai mare.
Subproblemele nu sunt independente deoarece rezolvarea subproblemei i se
bazeaz pe rezolvarea subproblemei i-1 (elementul xi al soluiei este determinat n
I

funcie de elementul xi-1 al soluiei).


ED
Informatic 73

C
Metoda programrii dinamice se bazeaz pe descompunerea unei probleme n
subprobleme similare problemei iniiale, care nu sunt independente, i
construiete soluia rezolvnd fiecare subproblem, prin selectarea, dintr-o

I
mulime de elemente, a elementelor care ndeplinesc o anumit condiie. .Pentru

OG
ca elementele care se selecteaz s aparin soluiei optime, la pasul k alegerea
se face n funcie de valoarea optim a unei funcii asociate soluiei i se bazeaz
pe alegerile care s-au fcut pn atunci (pe elementele soluiei care au fost
descoperite anterior).

AG
Etapele de rezolvare a unei probleme prin metoda programrii dinamice sunt:
PAS1. Se demonstreaz c problema are o substructur optim (prin reducere la absurd).
PAS2. Se caracterizeaz structura unei soluii optime (descompunerea problemei n sub-
probleme).

ED
PAS3. Se definete recursiv valoarea soluiei optime.
PAS4. Se calculeaz valoarea soluiei optime ntr-o manier de jos n sus (bottomup).
PAS5. Se construiete soluia optim din informaiile obinute prin calcularea valorii solu-
iei optime.

P
Observaie. Valoarea soluiei optime este definit recursiv n funcie de valorile optime ale
subproblemelor. Dac pentru calcularea funciei recursive s-ar folosi un algoritm recursiv,
n
I
ordinul de complexitate ar fi O(2 ), la fel ca i n cazul metodei clasice de rezolvare. Din
aceast cauz, calcularea funciei recursive se face de jos n sus obinndu-se un
algoritm iterativ:
PAS1. Se rezolv subproblema obinut din descompunerea problemei iniiale care are

cea mai mic dimensiune i se memoreaz soluia ei.


PAS2. Ct timp nu s-a ajuns la rezolvarea problemei cu dimensiunea n, execut: se
IC

rezolv o subproblem de dimensiunea i folosind soluiile obinute n subproble-


mele cu dimensiune mai mic dect i.
CT

1.6.2. Implementarea metodei programrii dinamice


Pentru implementarea metodei programrii dinamice se vor folosi subprogramele:
subprogramul init() care iniializeaz variabilele de memorie i structurile de date
DA

folosite pentru construirea soluiei;


subprogramul p_dinamica() care calculeaz valoarea soluiei optime;
subprogramul afiseaza() care afieaz soluia problemei folosind informaiile
obinute prin calcularea valorii soluiei optime.
DI

n exemplele urmtoare datele de intrare vor fi citite dintr-un fiier text.


Exemplul 1. Problema sumei maxime n triunghi.
Cerina problemei este ca pentru calculul sumei s se porneasc de la elementul a11 i s
RA

se mearg n jos, pn la linia n. Trecerea la linia urmtoare nu se poate face dect direct,
n jos, sau pe diagonal, la dreapta, astfel nct succesorul elementului aij nu poate fi dect
elementul ai+1,j sau elementul ai+1,j+1.
PAS1. Problema are substructur optim. Fie un ir de n numere din triunghi, care res-
TU

pect condiiile de deplasare n triunghi ale problemei, i care formeaz suma maxim. n
subproblema i a fost ales numrul de pe linia i pe baza sumelor maxime calculate n
subproblemele anterioare, altfel se contrazice ipoteza c irul formeaz suma maxim.
I
ED
74 Tehnici de programare

C
PAS2. Descompunerea problemei n subprobleme. Se determin pe rnd sumele maxi-
me ale numerelor care apar pe traseele care pornesc de pe ultima linie n ctre vrf i ajung
pe linia i (1in-1). Pe linia i, suma maxim pentru fiecare element se va calcula pe baza

I
sumelor maxime care s-au calculat n subproblemele anterioare (sumele de la linia n pn

OG
la linia i+1). Aceste sume sunt sumele maxime pentru fiecare linie i principiul optimalitii
este respectat.
PAS3. Valoarea soluiei fiind suma ele- aij dac i=n, 1ji
mentelor selectate, funcia recursiv S(i,j) =

AG
care definete suma maxim pornind aij + max(S(i+1,j), S(i+1,j+1)) dac 1in-1
de la elementul aij al triunghiului este
prezentat alturat.
PAS5. Pentru a calcula valoarea soluiei optime ntr-o manier de de jos n sus, se va

ED
forma un triunghi al sumelor maxime, pornind de la baz (linia n) ctre vrf (linia 1).
Sumele maxime de pe linia n sunt egale fiecare cu elementul corespunztor de pe linia n a
triunghiului. Valoarea maxim a sumei elementelor este S11.
PAS5. Pentru reconstituirea elementelor soluiei,

P
1 dac S(i+1,j) S(i+1,j+1)
se folosete o matrice p, n care se memoreaz p(i,j) =
direcia de deplasare (valoarea 1 pentru depla- 2 dac S(i+1,j) S(i+1,j+1)
sarea n jos i valoarea 2 pentru deplasarea pe
I
diagonal). Matricea p este definit alturat.
Se folosesc urmtoarele date i structuri de date:
Pentru numrul de linii ale triunghiului se folosete variabila n.

Pentru memorarea triunghiului se folosete matricea a, pentru a 0 ... 0


11
memorarea sumelor maxime matricea S, iar pentru memo-
IC

a a 22 ... 0
rarea direciei de deplasare matricea p. Toate aceste matri- 21
ce sunt ptrate, cu dimensiunea n. ... ... ... 0

a n1 an2 ... a nn
CT

Se folosesc urmtoarele subprograme:


Subprogramul citeste() pentru citirea datelor din fiierul text. n fiierul text, pe
primul rnd este scris numrul de linii, n, iar pe urmtoaree n rnduri numerele de pe
fiecare linie a triunghiului. Numerele sunt separate prin spaiu. n urma execuiei acestui
DA

subprogram se creeaz matricea triunghiului a.


Subprogramul init() iniializeaz linia n a matricei S cu elementele de pe linia n a
triunghiului.
Subprogramul p_dinamica calculeaz valoarea soluiei optime (elementul S11 al ma-
DI

tricei sumelor).
Subprogramul afiseaza() afieaz suma maxim i soluia problemei folosind infor-
maiile din matricea p.
Strategia programrii dinamice este implementat astfel:
RA

PAS1. Se iniializeaz linia n a matricei sumelor maxime S cu elementele de pe linia n a


matricei triunghiului a.
PAS2. Pentru urmtoarele linii ale matricei sumelor maxime ncepnd cu linia n-1 pn la
linia 1, execut:
TU

PAS3. Se calculeaz suma maxim astfel: dac suma maxim S(i+1,j) de sub
elementul curent din triunghi este mai mare dect suma maxim
S(i+1,j+1) de pe diagonala elementului curent, atunci la elementul
I
ED
Informatic 75

C
curent se adun suma S(i+1,j) i direcia de deplasare este 1; altfel, la
elementul curent se adun suma S(i+1,j+1) i direcia de deplasare este 2.

I
Matricea triunghiului a Matricea sumelor Matricea direciei de

OG
Suma maxim = 20 maxime S deplasare p
1 2 3 4 1 2 3 4 1 2 3 4
1 5 0 0 0 1 20 0 0 0 1 1 0 0 0
2 4 2 0 0 2 15 1 0 0 2 1 1 0 0

AG
3 5 4 3 0 3 11 10 8 0 3 2 1 2 0
4 4 6 2 5 4 4 6 2 5 4 0 0 0 0
Programul este:

ED
#include<fstream.h>
int n,a[20][20],p[20][20],S[20][20];
fstream f("pd1.txt",ios::in);
void citeste()

P
{int i,j; f>>n;
for(i=1;i<=n;i++)
for(j=1;j<=i;j++) f>>a[i][j]; f.close();}
I
void init()
{for (int i=1;i<=n;i++) S[n][i]=a[n][i];}
void p_dinamica()
{int i,j;

for (i=n-1;i>=1;i--)
IC

for (j=1;j<=i;j++)
if (S[i+1][j]>S[i+1][j+1])
{S[i][j]=a[i][j]+S[i+1][j]; p[i][j]=1;}
CT

else {S[i][j]=a[i][j]+S[i+1][j+1]; p[i][j]=2;} }


void afiseaza()
{int i,j ,q=1,r=1;
cout<<"Suma maxima= "<<S[1][1]<<"= "<<a[1][1]<<"+";
DA

for (i=1,j=1;i<n;i++)
{if (p[i][j]==2) {r=r+1; j++;}
q=q+1; cout<<a[q][r]<<"+";}
cout<<'\b'<<" "<<endl;}
DI

void main()
{citeste(); init(); p_dinamica(); afiseaza();}
Exemplul 2. Problema irului de lungime maxim.
RA

Pentru a determina irul de lungimea maxim, trebuie calculat, pentru fiecare element ai al
irului, lungimea celui mai mare subir cresctor care se poate forma ncepnd cu el, dup
care se alege subirul cu lungimea maxim.
PAS1. Problema are substructur optim. Fie un ir cresctor de m numere din irul
TU

iniial A care ncepe cu numrul ai i respect condiia c este subir al irului A, i care are
lungimea maxim dintre toate subirurile cresctoare care ncep cu numrul ai. n subpro-
blema i se alege subirul cresctor de lungime maxim care ncepe cu numrul ai astfel: se
adaug la numrul ai subirul cu lungime maxim dintre subirurile din subproblemele ante-
I
ED
76 Tehnici de programare

C
rioare care ncep cu numrul aj, cu ai aj i ij, altfel se contrazice ipoteza c subirul are
lungimea maxim.
PAS2. Descompunerea problemei n subprobleme. Se determin pe rnd lungimea

I
maxim a unui subir cresctor care ncepe cu elementul ai din ir, pornind de la subirurile

OG
cresctoare de lungime maxim care ncep cu elementul an, pn la subirurile care ncep
cu elementul ai+1. Pentru elementul ai din ir, lungimea maxim a subirurilor cresctoare
care se pot forma, ncepnd cu el, se va calcula pe baza lungimilor maxime care s-au calculat
n subproblemele anterioare. Aceste lungimi sunt lungimile maxime pentru fiecare subir care

AG
se poate forma ncepnd cu acel element i principiul optimalitii este respectat.
PAS3. Valoarea soluiei fiind lungimea 1 dac i=n
subirului cresctor, funcia recursiv L(i) =
care definete lungimea maxim a sub- 1 + max(L(j)) dac ai aj , in i i jn

ED
irului care se poate forma pornind de la
elementul ai al irului este prezentat alturat.
PAS4. Pentru a calcula valoarea soluiei optime ntr-o manier de jos n sus, se va forma
un vector al lungimilor maxime, pornind de la ultimul element din ir (elementul n) ctre

P
primul element din ir. n acest vector se va memora n poziia i lungimea maxim a unui
subir cresctor care se poate forma ncepnd cu elementul ai al irului. Cum lungimea
maxim a unui subir cresctor care se poate forma cu un singur element este 1, lungimea
I
maxim corespunztoare elementului an se iniializeaz cu valoarea 1.
PAS5. Pentru reconstituirea elementelor soluiei, se folosete vectorul p n care, n poziia i, se
memoreaz indicele elementului urmtor din subirul de lungime maxim care ncepe cu ai.

Se folosesc urmtoarele date i structuri de date:


IC

Pentru numrul de elemente ale irului se folosete variabila n.


Pentru memorarea irului de numere se folosete vectorul a, pentru memorarea lungi-
milor maxime vectorul L, iar pentru memorarea indicelui elementului urmtor din
CT

subir vectorul p. Toi aceti vectori au dimensiunea n.


Se folosesc urmtoarele subprograme:
Subprogramul citeste() pentru citirea datelor din fiierul text. n fiierul text, pe
primul rnd este scris lungimea irului n, iar pe urmtorul rnd cele n numere din ir.
DA

n urma execuiei acestui subprogram se creeaz vectorul pentru irul de numere a.


Subprogramul init() iniializeaz elementul n al vectorilor L i p.
Subprogramul p_dinamica calculeaz valoarea soluiei optime (lungimea maxim a
subirurilor care ncep cu fiecare element ai din ir).
DI

Subprogramul cauta_soluia() caut cea mai mare lungime maxim a unui subir
pentru a gsi elementul cu care ncepe subirul.
Subprogramul afiseaza() afieaz lungimea irului gsit i soluia problemei
folosind informaiile din vectorul p.
RA

Strategia programrii dinamice este implementat astfel:


PAS1. Se iniializeaz elementul n al vectorului lun-
Indici 1 2 3 4 5 6
gimilor maxime cu 1 i al vectorului p cu n.
TU

PAS2. Pentru urmtoarele elemente i ale vecto- a 1 -2 3 2 4 4


rului, lungimilor maxime ncepnd cu ele- L 4 4 3 3 2 1
mentul n-1 pn la elementul 1, execut:
p 3 3 5 5 6 6
PAS3. Se iniializeaz lungimea maxim
I

a subirului care ncepe cu acest Subirul 1 3 4 4


ED
Informatic 77

C
element cu valoarea 1 i poziia cu care ncepe subirul cu poziia elemen-
tului n ir.
PAS4. Se calculeaz lungimea maxim a subirului care ncepe cu elementul

I
curent din ir, astfel: pentru toate elementele j din ir care urmeaz dup

OG
elementul i, execut
PAS5. Dac ai este mai mic dect aj i lungimea subirului care ncepe
cu aj este mai mare dect lungimea subirului care ncepe cu ai,
atunci L(i) este egal cu 1+L(j) i indicele elementului care urmea-

AG
z n subir dup elementul ai este j.
PAS6. Se determin cea mai mare lungime maxim L(k). Subirul de lungime maxim va
ncepe cu elementul ak.
Programul este:

ED
#include<fstream.h>
int n,k,a[20],p[20],L[20];
fstream f("pd2.txt",ios::in);
void citeste()

P
{int i; f>>n;
for(i=1;i<=n;i++) f>>a[i]; f.close();}
void init()
I
{L[n]=1; p[n]=n;}
void p_dinamica()
{int i,j;

for (i=n-1;i>=1;i--)
{L[i]=1; p[i]=i;
IC

for (j=i+1;j<=n;j++)
if (a[i]<=a[j] && L[i]<=L[j])
{L[i]=L[j]+1; p[i]=j;}}}
CT

void cauta_solutia()
{int i,max=-1;
for (i=1;i<=n;i++)
if (max<L[i]) {max=L[i]; k=i;}}
DA

void afiseaza()
{int i,j;
cout<<"Lungime subsir= "<<L[k]<<endl;
for (i=1,j=k;i<=L[k];i++,j=p[j]) cout<<a[j]<<" ";}
DI

void main()
{citeste();p_dinamica(); cauta_solutie(); afiseaza(); }
Exemplul 3. Problema evii.
RA

Dac se poate construi o eav de lungimea D folosind buci de eav cu lungimea a1, a2,
, ai, atunci se poate construi i o eav cu lungimea D+ai+1 folosind buci de eav cu
lungimea a1, a2, , ai, ai+1.
PAS1. Problema are substructur optim. Fie o eav care s-a obinut prin sudarea bu-
TU

cii de eav cu lungimea ai, la o eav care a fost obinut anterior din buci de eav cu
lungimea aj, i care are lungimea mai mic dect L. n subproblema i se aleg dintre evile
obinute anterior numai acelea care au lungimea mai mic dect L-ai, altfel se contrazice
ipoteza c se poate construi noua eav.
I
ED
78 Tehnici de programare

C
PAS2. Descompunerea problemei n subprobleme. Se determin pe rnd lungimile
evilor care se pot forma cu bucata de eav cu lungimea ai, pornind de la eava format
numai cu bucata de eav cu lungimea a1, pn la evile formate cu primele i-1 buci de

I
eav. evile formate nu depesc lungimea L i principiul optimalitii este respectat.

OG
PAS3. Valoarea soluiei fiind lungimea -1 dac j=0
unei evi, funcia recursiv care define- T(i,j) =
te lungimea evilor care se pot forma ai dac T(i,j- ai) 0 pentru 1in i 1jL
cu bucata de eav cu lungimea ai este

AG
prezentat alturat.
PAS4. Pentru a calcula valoarea soluiei optime ntr-o manier de jos n sus, se vor
forma toate evile cu lungimea mai mic sau egal cu L, pornind de la eava care se poate
construi cu bucata de eav cu lungimea a1, i adugnd la evile obinute, pe rnd, urm-

ED
toarele n-1 buci de eav cu lungimea ai. Pentru a ine evidena evilor care s-au construit
n subproblema i se folosete un vector al lungimilor evilor care se construiesc T, care
are lungimea logic L. n acest vector se va memora n poziia j lungimea ultimei buci de
eav care se adaug la una dintre evile construite anterior pentru a obine o eav cu

P
lungimea j. Principiul optimalitii este respectat prin modul n care se construiete o eav
cu lungimea j: prin adugarea unei buci de eav la una dintre evile confecionate n
subproblema anterioar.
I
PAS5. Pentru reconstituirea elementelor soluiei, se folosete vectorul T. Pornind de la
elementul din poziia L care corespunde evii cu lungimea L, se scade bucata de eav cu
lungimea T(L), obinndu-se lungimea evii la care a fost adugat aceast bucat de eav

(indicele din vectorul T). Procesul continu pn se obine eava cu lungimea 0.


Se folosesc urmtoarele date i structuri de date:
IC

Pentru numrul de buci de eav se folosete variabila n, pentru lungimea evii care
trebuie confecionat, variabila L, iar pentru lungimea maxim a unei evi care se poate
forma adugnd o nou bucat de eav la evile construite anterior variabila max.
CT

Variabila max are iniial valoarea 0 (nu s-a construit nici o eav), iar la sfrit, dac
problema are soluie, are valoarea L (lungimea evii care trebuie confecionat).
Pentru memorarea lungimii fiecrei buci de eav se folosete vectorul a, de lungime
DA

n, iar pentru memorarea evilor care se pot confeciona, vectorul T, de lungime L.


Se folosesc urmtoarele subprograme:
Subprogramul citeste() pentru citirea datelor din fiierul text. n fiierul text, pe
primul rnd sunt scrise numrul de buci de eav n i lungimea evii L, iar pe
DI

urmtorul rnd, lungimile celor n buci de eav. n urma execuiei acestui subprogram
se creeaz vectorul cu lungimile bucilor de eav a.
Subprogramul init() iniializeaz elementul 0 al vectorului T i variabila max.
Subprogramul p_dinamica calculeaz valoarea soluiei optime (lungimile evilor ce se
RA

pot obine adugnd fiecare bucat de eav ai).


Subprogramul soluie() verific dac s-a gsit soluia problemei.
Subprogramul afiseaza() dac este posibil s se confecioneze eava, afieaz
lungimile bucilor de eav din care se confecioneaz.
TU

Strategia programrii dinamice este implementat astfel:


PAS1. Se iniializeaz elementul 0 al vectorului T cu -1 i variabila max cu valoarea 0.
PAS2. Pentru fiecare bucat de eav cu lungimea ai ncepnd cu bucata de eava cu
I

lungimea a1 pn la bucata de eav cu lungimea an, execut:


ED
Informatic 79

C
PAS3. Pentru evile cu lungimea j ncepnd cu eava cu lungimea max pn la
eava cu lungimea 1, execut:
PAS4. Dac adugnd la eava cu lungimea j bucata de eav cu lungi-

I
mea ai se obine o eav care va putea fi folosit la confecionarea

OG
evii cu lungimea L, atunci construirea evii cu lungimea j+ai
ncepe cu bucata de eav cu lungimea ai. Se revine la Pasul 3.
PAS5. Se determin lungimea maxim a unei evi care se poate construi din evile
construite anterior, astfel: dac adugnd la eava cu lungimea maxim

AG
bucata de eav cu lungimea ai, se obine o eav cu lungimea mai mic
dect L, atunci lungimea maxim a unei evi care se poate construi va fi
mrit cu lungimea bucii de eav ai; altfel, ea va fi L. Se revine la Pasul 2.
PAS6. Dac nu exist soluie (nu exist o bucat de eav cu care se poate ncepe
construirea evii de lungime L), atunci se afieaz un mesaj de informare; altfel, se

ED
trece la Pasul 7 pentru a afia soluia.
PAS7. Pentru fiecare eav cu lungimea i din care s-a obinut eava final, ncepnd de la
eava cu lungimea L, pn la eava cu lungimea 0, execut:
PAS8. Se afieaz lungimea bucii de eav cu care ncepe construirea evii i: T(i).

P
PAS9. Se calculeaz lungimea evii rmase, scznd lungimea bucii de eav
din lungimea i.
I
L=10 indici 1 2 3 4 5
n=5 a 2 2 3 5 6
indici vectorul T = lungime eav

max a(i) 0 1 2 3 4 5 6 7 8 9 10
IC

iniial -1 0 0 0 0 0 0 0 0 0 0
0 a(1) -1 0 2 0 0 0 0 0 0 0 0
CT

2 a(2) -1 0 2 0 2 0 0 0 0 0 0
4 a(3) -1 0 2 3 2 3 0 3 0 0 0
7 a(4) -1 0 2 3 2 5 0 5 5 5 5
DA

10 a(5) -1 0 2 3 2 5 6 5 6 6 6
De exemplu, dup ce s-a luat n consideraie i bucata de eav de lungime a(2) se pot
construi evi cu lungimea 2 (din bucata de eav a(1)=2) i cu lungimea 4 (din bucile de
eav a(1)=2 i a(2)=2), lungimea maxim a unei evi fiind 4. Lundu-se n consideraie i
DI

bucata de eav de lungime a(3)=3 se pot construi evi cu lungimea 2 (din bucata de eav
a(1)=2), cu lungimea 3 (din bucata de eav a(3)=3), cu lungimea 4 (din bucile de eav
a(1)=2 i a(2)=2) i cu lungimea 5 (din bucile de eav a(1)=2 i a(3)=3).
RA

Programul este:
#include<fstream.h>
int L,n,max,T[20],a[20];
fstream f("pd3.txt",ios::in);
TU

void citeste()
{int i; f>>L>>n;
for(i=1;i<=n;i++) f>>a[i]; f.close();}
void init()
I

{T[0]=-1; max=0;}
ED
80 Tehnici de programare

C
void p_dinamica()
{int i,j,k;
for (i=1;i<=n;i++)

I
{for (j=max;j>=0;j--)

OG
if (T[j]!=0 && j+a[i]<=L) T[j+a[i]]=a[i];
if (max+a[i]<L) max=max+a[i]; else max=L;}}
int solutie()
{return T[L]!=0;}

AG
void afiseaza()
{if (!solutie()) cout<<"Teava nu se poate confectiona";
else for (int i=L;i!=0;)
{cout<<"Bucata de "<<T[i]<<" metri "<<endl;
i-=T[i];}}

ED
void main()
{citeste(); init(); p_dinamica(); afiseaza();}

Exemplul 4. Problema discret a rucsacului.

P
PAS1. Fie un ir de m obiecte a cror greutate nu depete greutatea de ncrcare a
rucsacului G i care asigur profitul maxim al transportului. n subproblema i a fost ales
I
obiectul i numai dac greutatea sa nu depete greutatea de ncrcare disponibil i
profitul adus de el este mai mare dect al obiectului adugat anterior n rucsac, altfel se
contrazice ipoteza c ncrcarea rucsacului asigur profitul maxim.

PAS2. Descompunerea problemei n subprobleme. Se determin pe rnd profitul maxim


adus de fiecare obiect ai pentru fiecare greutate de ncrcare disponibil (de la 1 la G) por-
IC

nind de la obiectul a1, pn la obiectul an, pe baza profiturilor maxime aduse de primele
i-1 obiecte.
PAS3. Valoarea soluiei fiind profitul, funcia recursiv care definete profitul maxim C(i,j)
CT

obinut prin ncrcarea optim a rucsacului cu primele i obiecte, avnd disponibil greutatea
de ncrcare a rucsacului j, este prezentat alturat. C(i,0) reprezint profitul maxim al unui
rucsac cu greutatea disponibil 0 (care
nu permite adugarea niciunui obiect i). 0 dac j=0 i 1in
DA

C(0,j) reprezint profitul maxim al unui 0 dac i=0 i 1jG


rucsac gol cu greutatea disponibil j C(i,j) =
(care nu conine niciun obiect). max(C(i-1,j-g(i))+c(i), C(i-1,j)) dac g(i) j
C(i-1,j) n rest
DI

PAS3. Pentru a calcula valoarea soluiei


optime ntr-o manier de jos n sus, se va forma o matrice a profiturilor maxime C,
pornind de la primul obiect (linia 1), pn la ultimul obiect (linia n). Matricea C are
dimensiunea nG. Elementul C(i,j) memoreaz profitul maxim obinut n subproblema i
RA

pentru o greutate disponibil j. Pe linia i, profitul maxim pentru fiecare greutate de ncr-
care j se determin pe baza profiturilor maxime ce s-au calculat n subproblemele anteri-
oare (profiturile maxime de la linia 1 pn la linia i-1). Aceste profituri sunt maxime pentru
fiecare linie i principiul optimalitii este respectat. Valoarea maxim a profitului este CnG
TU

(profitul maxim obinut pentru un rucsac cu greutatea disponibil G ocupat prin alegerea din
cele n obiecte a obiectelor care aduc profitul maxim).
PAS4. Pentru reconstituirea elementelor soluiei, se folosete matricea p cu dimensiunea
nG. Elementul p(i,j) memoreaz obiectul ales n subproblema i pentru o greutate disponi-
I
ED

bil j.
Informatic 81

C
Se folosesc urmtoarele date i structuri de date globale:
Pentru numrul de obiecte se folosete variabila n, iar pentru greutatea rucsacului,
variabila G.

I
Pentru mulimea obiectelor (A) se folosete vectorul a ale crui elemente sunt de tip

OG
nregistrare obiect care conine dou cmpuri: g greutatea obiectului i c profitul
obinut n urma transportului.
Pentru memorarea profiturilor se folosete matricea C, iar pentru memorarea obiectelor
alese ntr-o subproblem se folosete matricea p. Ambele matrice au dimensiunea nG.

AG
Se folosesc urmtoarele subprograme:
Subprogramul citeste() pentru citirea datelor din fiierul text. n fiierul text, pe
primul rnd este scris numrul de obiecte n i greutatea maxim a transportului G, iar pe
urmtoarele n rnduri perechi de numere ntregi, separate prin spaiu, care reprezint

ED
greutatea i profitul transportului unui obiect. n urma execuiei acestui subprogram se
creeaz vectorul obiectelor a.
Subprogramul p_dinamica calculeaz valoarea soluiei optime (profitul maxim obinut
pentru un rucsac cu greutatea disponibil G ocupat prin alegerea din cele n obiecte, a

P
obiectelor care aduc profitul maxim).
Subprogramul afiseaza() afieaz profitul maxim i soluia problemei folosind infor-
maiile din matricea p.
I
Matricea C
n=4 G=10 Greutatea disponibil
Obiectul Greutatea Profitul Obiect 1 2 3 4 5 6 7 8 9 10

1 2 20 1 0 20 20 20 20 20 20 20 20 20
IC

2 3 40 2 0 20 40 40 60 60 60 60 60 60
3 6 50 3 0 20 40 60 60 60 60 70 90 90
4 0 20 40 45 60 65 85 85 105 105
CT

4 4 45
Matricea p
Greutatea disponibil Soluia
Obiect 1 2 3 4 5 6 7 8 9 10 Obiectul Greutatea Profitul
DA

1 0 1 1 1 1 1 1 1 1 1 4 4 45
2 0 1 2 2 2 2 2 2 2 2 2 3 40
3 0 1 2 2 2 2 2 3 3 3 1 2 20
DI

4 0 2 4 2 4 4 4 4 4 4 Total 9 115
Strategia programrii dinamice este implementat astfel:
PAS1. Pentru fiecare obiect i ncepnd cu primul obiect pn la ultimul obiect (n), execut:
RA

PAS2. Pentru greutatea disponibil j ncepnd de la 1 pn la G, execut:


PAS3. Se calculeaz profitul maxim pentru greutatea disponibil j lund n
consideraie profitul care s-ar putea obine prin adugarea obiectului
i: dac greutatea obiectului i este mai mic sau egal cu greutatea
TU

disponibil i profitul adus la greutatea j este mai mare dect profitul


adus de obiectul i-1, atunci profitul pentru obiectul i i greutatea j
este egal cu profitul obiectului i adunat la profitul calculat pentru
I

obiectul i-1 i greutatea j diminuat cu greutatea obiectului i i n


ED
82 Tehnici de programare

C
matricea p se memoreaz obiectul i; altfel, profitul pentru obiectul i
i greutatea j este egal cu profitul obiectului i-1 i greutatea j i n
matricea p se memoreaz obiectul i-1 ales pentru greutatea j.

I
Programul este:

OG
#include<fstream.h>
struct obiect {int g,c;};
obiect a[20];
int n,G,p[20][20],C[20][20];

AG
fstream f("pd4.txt",ios::in);
void citeste()
{int i; f>>n>>G;
for(i=1;i<=n;i++) f>>a[i].g>>a[i].c; f.close();}

ED
void p_dinamica()
{for (int i=1;i<=n;i++)
for (int j=1;j<=G;j++)
if ((a[i].g<=j) && (a[i].c+C[i-1][j-a[i].g]>C[i-1][j]))

P
{C[i][j]=a[i].c+C[i-1][j-a[i].g]; p[i][j]=i;}
else {C[i][j]=C[i-1][j]; p[i][j]=p[i-1][j];}}
void afiseaza()
I
{int i=n,j=G,k; cout<<"Profit total= "<<C[n][G]<<endl;
while (p[i][j]!=0)
{k=p[i][j];

cout<<"Obiectul "<<k<<" cu greutatea "<<a[k].g;


cout<<" si profitul "<<a[k].c<<endl;
IC

j-=a[p[i][j]].g;
while (p[i][j]==k) i--;}}
void main()
CT

{citeste(); p_dinamica(); afiseaza();}


Complexitatea algoritmului programrii dinamice
Algoritmul programrii dinamice are complexitatea O(nm) deoarece se rezolv cele n
DA

subprobleme, iar pentru fiecare subproblem se calculeaz cele m elemente ale valorii
asociate soluiei.
1. Se dau n numere naturale i un numr natural S. S se gseasc,
Tem dac exist, soluia de a obine numrul S ca sum de numere
DI

naturale dintre cele n numere date.


2. S se afieze cel mai mic numr cu exact n divizori.
3. Se citesc de la tastatur dou iruri de caractere S1 i S2. S se insereze spaii n irul
S1 astfel nct dac se suprapun cele dou iruri, numrul de caractere care coincid s
RA

fie maxim.
4. Se dau dou iruri de caractere A i B de lungime n, respectiv m. ntr-un ir de carac-
tere se pot executa numai urmtoarele trei operaii prin care se poate transforma un ir:
S(i) terge caracterul din poziia i, I(i,c) insereaz caracterul c n poziia i i M(i,c)
TU

nlocuiete caracterul din poziia i cu caracterul c. S se transforme irul A n irul B


folosind un numr minim de operaii. Problema se va rezolva n dou variante: a)
transformrile se vor aplica de la stnga la dreapta; b) transformrile se vor aplica de la
I

dreapta la stnga.
ED
Informatic 83

C
5. Se dau dou iruri de numere X={x1, x2, , xm} i Y={y1, y2, , ym}. S se determine
cel mai lung subir comun al celor dou iruri. irul Z={z1, z2, , zk} este subir
comun al irurior X i Y dac el este subir al irului X i subir al irului Y. De

I
exemplu, dac X={1,2,3,2,2,1,4} i Y={2,1,3,1,2,4}, irul Z={2,3,1,4} este un subir

OG
comun al celor dou iruri. Indicaie. Valoarea asociat soluiei este lungimea unui
subir comun, iar funcia recursiv definete valoarea lungimii maxime a unui subir
comun L(i,j) unde i este indicele 0 dac i=0 sau j=0
elementului cu care ncepe subi- L(i,j) = 1+L(i-1,j-1) dac i0, j0 i xi = yj

AG
rul X, iar j este indicele elementului max(L(i,j-1), L(i-1,j) ) dac i0, j0 i xiyj
cu care ncepe subirul Y.
6. Se d un ir de n matrice A1, A2, , An i trebuie s se calculeze produsul lor: A1A2
An. Fiecare matrice Ai, cu 2in, are pi-1 linii i pi coloane (dou matrice A i B se

ED
pot nmuli numai dac numrul de coloane din matricea A este egal cu numrul de
linii din matricea B). S se pun n acest produs parantezele potrivite astfel nct
numrul de nmuliri s fie minim (deoarece nmulirea matricelor este asociativ,
inserarea parantezelor nu modific rezultatul).

P
Indicaie. Fiind date dou matrice Ap,q i Bq,r, matricea produs Cp,r conine elementele:
q
I
c ij a ik b kj
k 1

Timpul necesar pentru calculul matricei produs este determinat de numrul de nmuliri
scalare: aikbkj. De exemplu, pentru produsul A1A2A3, n care matricele au dimen-

siunile 1020, 205 i, respectiv, 540, numrul de nmuliri scalare pentru paranterizarea
IC

((A1A2)A3) este 10205+10540=1200, iar pentru paranterizarea (A1(A2A3)) este


102040+20540=12000 (de 10 ori mai mare dect n exemplul anterior). Valoarea
asociat soluiei este numrul de nmuliri scalare, iar funcia recursiv m(i,j) definete
CT

numrul minim de nmuliri scalare pentru calculul matricei produs AiAj.


0 dac i= j
m(i,j) =
min{ m(i,k) + m(k+1,j) + pi-1pkpj | ikj } dac ij
DA

Numrul minim de nmuliri scalare pentru calculul produsului A1An este m(1,n).
Pentru a memora poziiile parantezelor optime se va folosi matricea s, n care elementul sij
are valoarea k ce reprezint poziia parantezei optime n produsul AiAj. Altfel spus, sij
DI

este egal cu k pentru care m(i,j) = m(i,k) + m(k+1,j) + pi-1pkpj.

1.7. Compararea metodelor de construire a algoritmilor


RA

Metodele backtracking, greedy i programarea dinamic se recomand n cazul proble-


melor care au urmtoarele caracteristici:
soluia poate fi dat de un vector sau o matrice cu elemente de tip ntreg;
elementele soluiei aparin unui subdomeniu limitat.
TU

Algoritmul backtracking are cea mai mare complexitate (complexitatea exponenial), iar
algoritmul greedy, cea mai mic. Alegerea uneia dintre aceste metode se face n funcie de
cerinele problemei:
I

Dac se cere determinarea tuturor soluiilor, se va alege metoda backtracking.


ED
84 Tehnici de programare

C
Dac se cere determinarea soluiei optime, se va alege metoda greedy, dac se
poate demonstra c ea furnizeaz un rezultat corect; altfel, se va alege metoda
programrii dinamice.

I
OG
Metodele greedy i programarea dinamic se folosesc n problemele n care trebuie gsit
soluia optim. n ambele metode alegerea elementului xk al soluiei este irevocabil i
poate duce la obinerea soluiei optime n cazul problemelor care au proprietatea de optim
local, adic soluia optim a problemei cu dimensiunea n a datelor de intrare conine solu-
iile optime ale subproblemelor similare cu problema iniial, dar de dimensiune mai

AG
mic. Deosebirea dintre cele dou metode const n modul n care este construit soluia:
1. n cazul metodei programrii dinamice, se pornete de la structura problemei iniiale
care corespunde soluiei optime globale i se descompune aceast problem n sub-
probleme n care se determin soluiile optime ale subproblemelor (optimul local). Ea se

ED
poate aplica n problemele n care optimul global implic optimul local. Din aceast
cauz, etapa cea mai dificil la aceast metod este cea de determinare a structurii
soluiei optime. Dac se cunoate structura soluiei optime, metoda garanteaz
obinerea soluiei optime a problemei prin determinarea optimului local.

P
2. n cazul metodei greedy, se pornete de la soluiile optime locale i pe baza lor se
construiete soluia optim global. Problema este descompus n subprobleme i
I
soluia este construit treptat: se pornete de la mulimea vid i se alege pe rnd
pentru fiecare element al soluiei candidatul optim pentru acea subproblem. Alegerea
soluiilor optime locale nu garanteaz ns c soluia global obinut este i soluia
optim, deorece optimul local nu implic ntotdeauna optimul global. Din aceast

cauz, pentru a fi siguri c soluia aleas este soluia optim, pentru fiecare problem
trebuie s se demonstreze c modul de alegere a candidatului optim (optimul local)
IC

implic optimul global. Metoda greedy este mai simpl dect metoda programrii
dinamice deoarece la fiecare pas se trateaz numai subproblema curent, iar ordinul de
complexitate este mai mic dect n cazul programrii dinamice.
CT

Metodele greedy i backtracking construiesc treptat soluia problemei. Deosebirea dintre


cele dou metode const n modul n care se construiete soluia. n cazul metodei greedy,
cnd se alege elementul xk al soluiei, dac elementul ai care este candidatul optim al soluiei
DA

nu este element al soluiei, el este ndeprtat din mulimea elementelor candidate la soluie
(A). n acest mod el nu va mai fi verificat atunci cnd se alege un alt element al soluiei,
micornd foarte mult ordinul de complexitate al algoritmului.
Pentru a obine soluia dorit folosind un algoritm ct mai eficient se pot combina
DI

metodele nvate.
Exemplu. Problema plii unei sume cu un numr minim de bancnote cu valori date.
Problema a fost rezolvat cu ajutorul metodei greedy. Folosind aceast metod este posibil
RA

s nu obinei nicio soluie, sau soluia obinut s nu fie soluia optim. Problema poate fi
rezolvat combinnd metoda greedy (prin ordonarea vectorului cu valorile bancnotelor
dup criteriul candidatului optim) cu metoda backtracking. Soluia optim va fi printre
primele soluii generate. Apelul subprogramului bt() se va opri imediat ce se depete
TU

numrul minim de bancnote Prin combinarea celor dou metode se obine un algoritm mai
eficient dect algoritmul backtracking, care va permite gsirea soluiei optime.
I
ED
Informatic 85

C
Metodele divide et impera i programarea dinamic se bazeaz pe descompunerea pro-
blemei n subprobleme similare cu problema iniial. Deosebirile dintre cele dou meto-
de sunt:

I
Divide et impera Programarea dinamic

OG
1. Subproblemele
Subproblemele sunt independente i nu se Subproblemele nu sunt independente i n des-
cunosc de la nceput subproblemele care apar compunerea iniial exist subprobleme comune
n urma descompunerii. De multe ori descompu- unor subprobleme de dimensiuni mai mari. Pen-

AG
nerea n subprobleme depinde de distribuia da- tru a se putea rezolva problema trebuie s se cu-
telor de intrare i este posibil ca n aceeai pro- noasc, de la nceput, subproblemele n care se
blem, pentru date de intrare diferite, s se obi- descompune problema iniial. Aceasta presupu-
n descompuneri diferite (de exemplu, algoritmul ne cunoaterea structurii problemei iniiale i a
cutrii binare sau algoritmul sortrii rapide). relaiei de recuren care determin soluia.

ED
2. Asigurarea eficienei metodei
Este eficient numai dac este respectat regula Este eficient numai dac o subproblem este
de descompunere a problemei n subprobleme rezolvat o singur dat, soluia sa este

P
independente. Dac nu este asigurat indepen- memorat i folosit pentru a obine soluiile
dena problemelor, metoda devine ineficient celorlalte subprobleme.
deoarece, n apelurile recursive, aceeai subpro-
I
blem este rezolvat de mai multe ori.
3. Modul de descompunerea n subprobleme
Descompunerea se face ntr-o manier de sus n Descompunerea se face ntr-o manier de jos n

jos (topdown): problema iniial este descom- sus (bottomup): se rezolv problemele de dimen-
pus n subprobleme din ce n ce mai mici pn se siunile cele mai mici care apar n problema iniial,
IC

obin subprobleme cu rezolvare imediat, se rezolv se memoreaz soluiile lor i se rezolv subprobe-
aceste subprobleme, dup care se combin soluiile mele de dimensiuni din ce n ce mai mari prin com-
subproblemelor de dimensiuni din ce n ce mai mari. binarea soluiilor problemelor mai mici i memorarea
CT

noilor soluii.
4. Algoritmul
Algoritmul este recursiv. Algoritmul este iterativ.
DA

Din cauza acestor deosebiri aceste metode se folosesc pentru clase diferite de probleme. De
exemplu, problema determinrii termenului n al irului lui Fibonacci. Rezolvarea acestei
probleme prin metoda divide et impera este ineficient deoarece pentru a calcula termenul fn
trebuie s se calculeze termenii fn-1 i fn-2. Dar, n calculul termenului fn-1, reapare calculul
DI

termenului fn-2, iar n calculul ambilor termeni apare calculul termenului fn-3 .a.m.d. n acest
caz, se recomand metoda programrii dinamice, calculnd pe rnd termenii f3, f4, , fn,
pornind de la termenii f1=f2=1. Formula de recuren este: fi = fi-1+fi-2, pentru 3in. Deoa-
rece termenul fi nu depinde dect de doi termeni fi-1 i fi-2, nu este necesar s se memoreze
RA

ntregul ir de termeni, ci pentru fiecare subproblem i, numai termenii obinui n subpro-


blemele i-1 i i-2.
TU

Adevrat sau Fals:


1. n algoritmul metodei backtracking iniializarea elementului k al soluiei se face cnd
I

se revine de pe nivelul k+1 la nivelul k.


ED
86 Tehnici de programare

C
2. Algoritmul metodei backtracking se ncheie dac s-au testat toate valorile posibile
pentru primul element al soluiei.
3. n algoritmul backtracking, dup gsirea unei soluii, se revine la nivelul anterior al soluiei.

I
4. n algoritmul backtracking, trecerea de la nivelul k la nivelul k-1 al soluiei se face

OG
dup ce s-au gsit toate valorile posibile pentru nivelul k.
5. n algoritmul backtracking iniializarea nivelului k al soluiei se face cu valoarea de pe
nivelul anterior al soluiei.
6. n algoritmul backtracking, dac s-a trecut la nivelul k al soluiei, nseamn c s-au

AG
gsit primele k-1 elemente ale soluiei.
7. n algoritmul backtracking, trecerea la nivelul k+1 al soluiei se face dup ce au fost
testate toate valorile posibile pentru nivelul k al soluiei.
8. n implementarea recursiv a metodei backtracking revenirea din autoapel este echi-
valent cu revenirea la nivelul anterior al soluiei din varianta iterativ.

ED
9. n implementarea recursiv a metodei backtracking autoapelul este echivalent cu
trecerea la nivelul urmtor al soluiei din varianta iterativ.
10. Divide et impera este metoda prin care problema iniial se descompune n subpro-
bleme care nu sunt independente.

P
11. Prin metoda divide et impera se gsete soluia optim a problemei.
12. Metoda programrii dinamice pornete de la soluiile optime locale i, pe baza lor,
I
construiete soluia optim global.
13. n metoda programrii dinamice descompunerea n subprobleme se face de sus n jos.
14. Metoda greedy se bazeaz pe teorema c optimul local implic ntotdeauna optimul global.

Alegei:
1. Algoritmul care implementeaz metoda backtracking este:
IC

a. polinomial b. logaritmic c. exponenial d. liniar logaritmic


2. Algoritmul care implementeaz metoda sortrii rapide este:
CT

a. liniar b. logaritmic c. ptratic d. liniar logaritmic


3. Algoritmul care implementeaz metoda cutrii binare este:
a. liniar b. logaritmic c. ptratic d. liniar logaritmic
4. Se utilizeaz metoda backtracking pentru generarea anagramelor cuvntului masca.
DA

S se precizeze cuvntul precedent i cuvntul urmtor secvenei camas, camsa,


caams:
a. csaam i casma b. csama i casma c. csaam i casma d. csaam i caasm
5. Se utilizeaz metoda backtracking pentru generarea tuturor numerelor cu 4 cifre dis-
DI

tincte care se pot forma cu cifrele 0, 2, 4 i 8. S se precizeze numrul precedent i


numrul urmtor secvenei 2840 4028 4082:
a. 2480 i 4280 b. 2804 i 4280 c. 2804 i 4208 d. 2480 i 4280
RA

6. Se utilizeaz metoda backtracking pentru generarea irului de opt paranteze rotunde


astfel nct ele s formeze o succesiune corect. S se precizeze irul de paranteze
precedent i irul de paranteze urmtor secvenei (()(())) (()()()) (()())():
a. ((()())) i ()((())) b. ((()))() i ()((())) c. ((()))() i (())(()) d. ((()())) i (())(())
TU

7. Se utilizeaz metoda backtracking pentru generarea submulimilor mulimii {1,2,3}.


S se precizeze submulimea precedent i submulimea urmtoare secvenei de
submulimi {1} {1,3} {1,2} :
a. {} i {2,3} b. {} i {2} c. {2,3} i {1,2,3} d. {} i {3}
I
ED
Informatic 87

C
8. Dac se utilizeaz metoda backtracking pentru a genera toate permutrile de 5
obiecte i primele 4 permutri generate sunt: 5 4 3 2 1, 5 4 3 1 2, 5 4 2 3 1, 5 4 2 1 3,
atunci a cincea permutare este:

I
a. 5 4 3 2 1 b. 5 3 4 2 1 c. 5 4 1 2 3 d. 5 4 1 3 2

OG
(Bacalaureat Sesiunea special 2003)
9. Se cere determinarea tuturor modalitilor de planificare n zile diferite a 4 probe
(rezisten, aruncarea suliei, srituri, tir) n oricare dintre cele 7 zile din sptmn.
Problema este echivalent cu:

AG
a. generarea combinrilor de 4 obiecte luate cte 7
b. generarea aranjamentelor de 4 obiecte luate cte 7
c. generarea combinrilor de 7 obiecte luate cte 4
d. generarea aranjamentelor de 7 obiecte luate cte 4
(Bacalaureat Sesiunea special 2003)

ED
10. Generarea tuturor irurilor de 3 elemente, fiecare element putnd fi oricare numr din
mulimea {1,2,3,4,5,6}, se realizeaz cu ajutorul unui algoritm echivalent cu algoritmul
de generare a:
a. aranjamentelor b. permutrilor c. combinrilor d. produsului cartezian

P
(Bacalaureat Sesiunea special 2003)
11. Se cere determinarea tuturor modalitilor distincte de aezare n linie a tuturor celor
n sportivi aflai la o festivitate de premiere. Problema este echivalent cu generarea:
I
a. partiiilor unei mulimi de n obiecte b. aranjamentelor de n obiecte luate cte 1
c. permutrilor de n obiecte d. submulimilor unei mulimi cu n obiecte
(Bacalaureat Sesiunea iunie-iulie 2003)

12. Condiia ca dou dame Q i D (de tip structur) s se afle pe aceeai diagonal a
tablei de ah este:
IC

a. (Q.linie==D.linie)|| (Q.coloana==D.coloana)
b. abs(Q.linie-D.linie)==abs(Q.coloana-D.coloana)
c. Q.linie-D.linie == Q.coloana-D.coloana
CT

d. abs(Q.linie-D.coloan)==abs(D.linia-D.coloana)
(Bacalaureat Sesiunea iunie-iulie 2003)
13. Se cere determinarea tuturor numerelor formate cu cifre aflate n ordine strict cresc-
toare, cifre alese dintr-o mulime cu k cifre distincte date. De exemplu, pentru cifrele
DA

alese din mulimea {1,5,2} se obin numerele 1, 2, 12, 5, 15, 25, 125 (nu neaprat n
aceast ordine). Problema este echivalent cu generarea:
a. partiiilor unei mulimi b. aranjamentelor de 10 obiecte luate cte k
c. permutrilor de k obiecte d. submulimilor nevide ale unei mulimi
DI

(Bacalaureat Sesiunea august 2003)


14. Cineva dorete s obin i s prelucreze toate numerele formate din trei cifre din
irul 2, 9, 4 i le genereaz exact n ordinea 222, 229, 224, 292, 299, 294, 242, 249,
244, 922, 929, 924, 992, 999, 994, 942, 949, 944, 422, 429, 424, 492, 499, 494, 442,
RA

449, 444. Dac dorete s obin prin acelai procedeu numerele formate din 4 cifre,
atunci dup numrul 4944 va urma:
a. 4949 b. 9222 c. 4422 d. 4924
(Bacalaureat Simulare 2004)
TU

15. Un elev folosete metoda backtracking pentru a genera submulimile mulimii


{1,2,5,6,9}. Cte soluii (submulimi) care obligatoriu conin elementul 2 i nu conin
elementul 6 a generat?
a. 7 b. 16 c. 6 d. 8
I
ED

(Bacalaureat Sesiunea special 2004)


88 Tehnici de programare

C
16. Pentru a determina toate modalitile de a scrie pe 9 ca sum de numere naturale
nenule distincte (abstracie fcnd de ordinea termenilor), un elev folosete metoda
backtracking genernd, n aceast ordine, toate soluiile: 1+2+6, 1+3+5, 1+8, 2+3+4,

I
2+7, 3+6 i 4+5. Aplicnd exact aceeai metod, el determin soluiile pentru

OG
scrierea lui 12. Cte soluii de forma 3+ exist?
a. 7 b. 1 c. 2 d. 4
(Bacalaureat Sesiunea iunie-iulie 2004)
17. Pentru problema anterioar, care este a opta soluie determinat?

AG
a. 2+3+7 b. 3+4+5 c. 1+5+6 d. 1+11
(Bacalaureat Sesiunea iunie-iulie 2004)
18. Pentru problema anterioar stabilii care este soluia cu proprietatea c imediat dup
ea este generat soluia 3+4+5?

ED
a. 3+4+6 b. 2+3+7 c. 2+10 d. 4+8
(Bacalaureat Sesiunea iunie-iulie 2004)
19. Se genereaz toate permutrile distincte de 4 obiecte numerotate de la 1 la 4, avnd
proprietatea c 1 nu este vecin cu 3 (1 nu se afl imediat dup 3, i nici 3 imediat

P
dup 1) i 2 nu este vecin cu 4. Cte astfel de permutri se genereaz?
a. 12 b. 24 c. 6 d. 8
(Bacalaureat Sesiunea august 2004)
I
20. Se cere s se determine toate modalitile distincte de a programa n spectacole n z
zile (de exemplu, dou spectacole Micul Prin i Pcal se pot programa n trei
zile, mari, miercuri i joi, astfel: Micul Prin mari i Pcal miercuri sau; Micul

Prin miercuri i Pcal mari; Micul Prin miercuri i Pcal joi; Micul
Prin mari i Pcal joi; Micul Prin joi i Pcal miercuri etc.).
IC

Rezolvarea se bazeaz pe algoritmul de generare a:


a. combinrilor de n obiecte luate cte z b. aranjamentelor de n obiecte luate cte z
c. combinrilor de z obiecte luate cte n d. aranjamentelor de z obiecte luate cte n
CT

(Bacalaureat Simulare 2005)


21. Se consider algoritmul care determin toate permutrile distincte de n obiecte
(numerotate de la 1 la n) n care nu exist poziii fixe. O permutare (p1, p2, , pn) are
puncte fixe dac exist cel puin o component pi=i. De exemplu, pentru n=5,
DA

permutarea (2,3,5,4,1) are puncte fixe deoarece p4=4. Pentru n=4, stabillii cte
permutri fr puncte fixe exist.
a. 8 b. 9 c. 10 d. 12
(Bacalaureat Sesiunea special 2005)
DI

22. Se consider algoritmul care determin toate permutrile distincte de n obiecte (nume-
rotate de la 1 la n) n care pe orice poziie de rang par se afl o valoare par. De
exemplu, pentru n=5, primele trei permutri generate n ordine lexicografic sunt
(1,2,3,4,5), (1,2,5,4,3), (1,4,3,2,5). Pentru n=4, numrul total de astfel de permutri este:
RA

a. 2 b. 4 c. 8 d. 12
(Bacalaureat Sesiunea iunie-iulie 2005)
23. Se consider algoritmul care genereaz, n ordine strict cresctoare, toate numerele
formate din n cifre distincte (cifrele de la 1 la n), numere n care pe fiecare poziie par
TU

se af o cifr impar. Poziia se numr de la stnga ctre dreapta, pornind de la


poziia 1. De exemplu, pentru n=4, primele trei numere generate sunt: 2143, 2341,
4123. Pentru n=5, primul numr generat este:
a. 21345 b. 21435 c. 12345 d. 13254
I
ED

(Bacalaureat Sesiunea august 2005)


Informatic 89

C
24. Se genereaz toate submulimile formate din dou elemente ale mulimii {5,6,7,8} n
ordinea: 5 6, 5 7, 5 8, 6 7, 6 8, i 7 8. Dac se utilizeaz exact aceeai metod pentru
a genera submulimile de trei elemente ale mulimii {2,3,4,5,6}, atunci penultima mul-

I
ime generat este:

OG
a. 3 4 5 b. 3 5 6 c. 4 5 6 d. 2 5 6
(Bacalaureat Simulare 2006)
Miniproiecte:
Pentru realizarea miniproiectelor se va lucra n echip. Fiecare miniproiect va conine:

AG
a. dou metode pentru construirea algoritmului (care sunt precizate n cazul pri-
melor 8 miniproiecte);
b. justificarea folosirii metodelor care au fost alese pentru rezolvarea problemei;
c. explicarea metodelor folosite pentru construirea agoritmului;

ED
d. compararea celor dou metode din punct de vedere al corectitudinii soluiei;
e. compararea celor doi algoritmi din punct de vedere al complexitii.
1. Rezolvai problema acoperirii tablei de ah de dimensiunea nn cu un cal care pornete

P
din ptratul de coordonate (x,y) folosind metoda backtracking i metoda greedy.
2. Rezolvai problema costruirii evii de lungime L din buci de eav de lungimi ai folosind
metoda backtracking i metoda programrii dinamice.
I
3. Rezolvai problema gsirii unui traseu pentru a iei din labirintul de dimensiunea nm,
tiind c se pornete din ptratul de coordonate (x,y), folosind metoda greedy i metoda
backtracking.

4. Rezolvai problema plii unei sume cu bancnote cu valori date, pentru fiecare valoare
de bancnot avnd la dispoziie un anumit numr de bancnote, folosind metoda
IC

programrii dinamice i metoda backtracking.


5. Rezolvai problema turistului care trebuie s gseasc un traseu de munte n care s
urce ct mai puin, folosind metoda programrii dinamice i metoda greedy.
CT

6. Rezolvai problema determinrii sumei maxime ntr-un triunghi folosind metoda greedy
i metoda programrii dinamice.
7. Rezolvai problema determinrii unui subir cresctor de lungime maxim folosind
metoda greedy i metoda programrii dinamice.
DA

8. Se dau n paralelipipede avnd fiecare dimensiunile ai, bi i ci. S se construiasc un


turn de nlime maxim prin suprapunerea acestor paralelipipede. Un paralelipiped
poate fi aezat pe orice fa. Un paralelipiped poate fi aranjat peste un alt paralelipiped
numai dac faa lui nu depete faa paralelipipedului pe care este pus. Rezolvai
DI

problema folosind metoda backtracking i metoda programrii dinamice.


9. Pe o tabl de ah de dimensiunea nn un cal pornete din ptratul de coordonate
(x1,y1) i trebuie s ajung n ptratul de coordonate (x2,y2). S se gseasc traseul de
RA

lungime minim.
10. Se dau n piese de domino, fiecare pies i fiind descris prin perechi de dou numere
(xi,yi). S se gseasc o secven de lungime maxim de piese n care oricare dou
piese alturate au nscrise la capetele cu care se nvecineaz acelai numr.
TUI
ED
C
2. Implementarea

I
structurilor de date

OG
2.1. Tipuri de date specifice pentru adresarea memoriei

AG
Memoria intern a calculatorului este organizat sub forma unor locaii de dimensiunea unui
octet, numerotate consecutiv, pornind de la 0. Aceste numere, exprimate n hexazecimal, se
numesc adrese de memorie. Locaiile de memorie pot fi manipulate individual sau n grupuri

ED
contigue. Spaiul de memorie este gestionat de sistemul de operare. Fiecrui program
aflat n execuie, sistemul de operare i rezerv (aloc) propriul spaiu de memorie. Dac pro-
gramul apeleaz subprograme, acestea pot fi privite ca blocuri care conin instruciuni i date
(variabile de memorie i structuri de date), crora sistemul de operare trebuie s le aloce

P
spaiu de memorare n interiorul zonei de memorie rezervat programului principal (care
corespunde fiierului surs). Spaiul de memorare este mprit n patru segmente, iar proce-
sorul are acces la toate cele patru segmente, ale cror adrese le gestioneaz prin intermediul
I
unor regitri:
segmentul de cod n care se ncarc instruciunile programului care se execut;
adresa de nceput se pstreaz n registrul CS;
segmentul de date n care se ncarc anumite date ale programului care se execut

(de exemplu, variabilele globale); adresa de nceput se pstreaz n registrul DS;


segmentul de stiv a sistemului n care se ncarc adresele de revenire din subpro-
IC

grame i variabilele locale cu care lucreaz subprogramele; pentru gestionarea sa se


folosesc doi regitri: SS (n care se pstreaz adresa de la baza stivei) i SP (n care se
CT

pstreaz adresa de la vrful stivei);


extrasegmentul de date n care se ncarc alte date ale programului; adresa de
nceput se pstreaz n registrul ES.
Sistemul de operare aloc spaiu datelor n mai multe zone de memorie, n funcie de
DA

modul n care au fost declarate n program.


variabile locale
zona de adrese libere (heap) (alocarea implicit)
DI

stiva sistemului (stack)


variabile globale variabile locale statice
segmentul de date
(alocarea implicit) (alocare cu static)
regitrii procesorului
RA

variabile locale
(alocare cu register)

O dat manipulat de program prin intermediul unei variabile de memorie este caracterizat
TU

de mai multe atribute pe care le primete n momentul n care este declarat n program:
Numele. Este identificatorul folosit pentru referirea datei n cadrul programului (n
exemplu a).
Adresa. Este adresa de memorie intern la care se aloc spaiu datei respective, pentru
I

a stoca valoarea datei (n exemplu, datei i se aloc adresa adr n stiva sistemului).
ED
Informatic 91

C
2 octei valoarea datei

a = nume dat 0000000001100100

I
void sb()

OG
{int a=100; ...} adr = adresa zonei de memorie adr+2

Memoria intern

AG
Valoarea. Este coninutul, la un moment dat, al zonei de memorie rezervate datei (n
exemplu 100(10) = 1100100(2)).
Tipul. Determin: domeniul de definiie intern al datei (mulimea n care poate lua
valori data), operatorii care pot fi aplicai pe acea dat i modul n care data este

ED
reprezentat n memoria intern metoda de codificare n binar a valorii datei (n
exemplu, tipul este unsigned int: domeniul de definiie intern al datei este intervalul
[0, 65535]), operatorii care pot fi aplicai pe aceast dat sunt operatorii permii de tipul
numeric aritmetici, relaionali, logici, logici pe bii etc. i reprezentarea datei n

P
memoria intern se face prin conversia numrului din zecimal n binar).
Lungimea. Este dimensiunea zonei de memorie alocate datei i se msoar n octei.
Ea depinde de modul de reprezentare intern a tipului de dat (n exemplu, datei i se
I
aloc un grup contiguu de 2 octei). Pentru a afla dimensiunea zonei de memorie alo-
cate unei variabile de memorie se poate folosi operatorul sizeof().
Durata de via. Este perioada de timp n care variabilei i se aloc spaiu de memo-
rare (n exemplu, data a este o variabil cu durat local creia i se aloc spaiu de

memorare numai pe durata de execuie a blocului n care a fost declarat, adic pe


IC

durata de execuie a subprogramului sb).


Pentru a putea manipula o dat, programul trebuie s identifice zona de memorie n care
este stocat. Identificarea acestei zone se poate face att prin numele datei (a), ct i prin
CT

adresa la care este memorat (adr). Pentru a putea manipula datele cu ajutorul adreselor
de memorie, n limbajul C++ sunt implementate urmtoarele tipuri de date:
tipul pointer sau adres;
tipul referin.
DA

Se poate folosi un nou criteriu pentru clasificarea datelor:


criteriul semnificaiei coninutului
DI

Operanzii sau datele care fac obiectul Adresele sau datele care permit
operaiilor de prelucrare. adresarea operanzilor.
Sunt date ale cror valori sunt folosite ca Sunt date ale cror valori sunt folosite pentru
RA

operanzi n cadrul expresiilor utilizate pentru localizarea pe suportul de memorare a datelor


calcularea rezultatelor cerute de problem. care sunt prelucrate (operanzii).

2.2. Tipul de dat pointer


TU

Pointerul este o variabil de memorie n care se memoreaz o adres de memorie.


Observaie. Un pointer se asociaz ntotdeauna unui tip de dat (de exemplu: int, char,
I
ED

float etc.) numit tip de baz. Se spune c un pointer indic o zon de memorie care
92 Implementarea structurilor de date

C
conine o dat care are tipul de baz. Este necesar s se asocieze pointerului un tip de
dat deoarece el memoreaz numai o adres i, pentru a manipula coninutul unei zone de
memorie, compilatorul trebuie s cunoasc dimensiunea zonei de memorie care ncepe de

I
la acea adres i semnificaia coninutului, adic ce algoritm de decodificare trebuie s

OG
foloseasc pentru a transforma secvena de bii (din acea zon de memorie) ntr-o dat.

2.2.1. Declararea variabilelor de tip pointer


Declararea unei variabile de tip pointer se poate face prin instruciunea declarativ:

AG
tip_dat *nume_variabil;
tipul datei stocate la adresa memorat numele variabilei de tip pointer n care se
n pointer (tipul de baz) memoreaz adresa unei variabile de

ED
memorie care are tipul de baz
operatorul de referin
Exemplu:
char *p;

P
int *q;
float *r;
S-au definit trei variabile de tip adres (pointeri): p ctre tipul char, q ctre tipul int i r ctre
I
tipul float. Numele acestor variabile de memorie sunt p, q i r, iar tipul de baz al fiecrei
variabile de tip pointer este char, int, respectiv float. Aadar, p este o variabil de tip
adres a unei locaii ce conine un caracter care ocup 1 octet, q este o variabil de tip

adres a unei locaii ce conine o dat numeric ntreag care ocup 2 octei, iar r este o
variabil de tip adres a unei locaii ce conine o dat numeric real care ocup 4 octei.
IC

Se poate declara un pointer ctre tipul de dat nregistrare (adresa unei nregistrri).
Exemplu:
CT

struct punct {int x,y;};


punct *p;
S-a definit variabila p de tip adres ctre tipul nregistrare punct, adic o adres a unei
locaii care conine dou date numerice ntregi de tip int ce ocup 4 octei.
DA

Pointerul zero are valoarea 0 i indic zona de memorie de la adresa 0.


Pentru limbajul C++ adresa 0 nseamn o adres care nu este valid pentru date, adic o
adres inexistent. Altfel spus, pointerul zero nu indic nimic. Acest tip de pointer este
DI

folosit ca terminator n structurile de date care sunt prelucrate cu ajutorul pointerilor.

2.2.2. Constante de tip adres


RA

O constant de tip adres este un pointer al crui


coninut nu poate fi modificat.
Exemplu. Constanta 0 care semnific adres nul (adres inexistent sau adres
nealocat) este util, n unele cazuri, pentru iniializarea valorii unui pointer. n locul
TU

constantei numerice literale 0, se poate folosi constanta simbolic predefinit NULL.


Observaie. La declararea unui tablou de memorie, acestuia i se aloc o zon de memorie
de dimensiune fix, ncepnd de la o anumit adres de memorie. Adresa de la care se
I

aloc zona de memorie este o constant (nu poate fi modificat) i ea este asociat cu
ED
Informatic 93

C
numele tabloului de memorie. Numele tabloului de memorie este folosit de compilatorul
C++ ca o constant simbolic de tip adres (pointer ctre tipul de baz dat de tipul
elementelor tabloului).

I
Tabloul de memorie este o structur de date omogen, adic o colecie de elemente de

OG
acelai tip, i fiecare element ocup acelai numr de octei. Acest mod de memorare
permite determinarea adresei fiecrui element pornind de la adresa simbolic a tabloului,
care va reprezenta i adresa primului element. Identificarea unui element de tablou de
memorie se face folosind pentru fiecare element un grup de indici (numrul de indici fiind

AG
egal cu dimensiunea tabloului), adresa elementului calculndu-se fa de un element de
referin care este adresa tabloului. Deoarece adresa tabloului este i adresa primului
element, n limbajul C++ numerotarea indicilor se face pornind de la 0, indicele repre-
zentnd deplasarea elementului fa de adresa tabloului.

ED
Exemplul 1: int v[5];
Zona de memorie alocat unui vector are dimensiunea n sizeof(tip_baz). De exemplu,
vectorului v i se va aloca o zon de memorie de 5sizeof(int)=52=10 octei. Identificarea unui
element de tablou de memorie se face folosind un singur indice (i). Dac adresa tabloului v

P
este adr, ea este i adresa elementului v[0], iar adresa elementului v[i] este:
adr + isizeof(tip_baz).
I
2 octei

v[0] v[1] v[2] v[3] v[4]


adr adr+2 adr+4 adr+6 adr+8


IC

adr este o adres de memorie care are valoarea


constantei simbolice v
CT

Pentru exemplul de mai sus, adresa elementului v[2] este:


adr + 2sizeof(int) = adr + 22 = adr + 4.
Exemplul 2: int a[4][2];
DA

4 octei

linia 0 linia 1 linia 2 linia 3


DI

a[0][0] a[0][1] 2 octei a[3][0] a[3][1]

a[1][0] a[1][1] a[2][0] a[2][1]


adr adr+2 adr+12 adr+14
RA

adr+4 adr+6 coloana 0 coloana 1

adr este o adres de memorie care are valoarea constantei simbolice a

Alocarea memoriei unei matrice se face n mod contiguu, memorarea elementelor fcn-
TU

du-se linie cu linie, astfel nct matricea apare ca un vector de linii. Dac matricea are m linii
i n coloane, ea va avea mn elemente. De exemplu, matricea a are 42=8 elemente i este
memorat ca un vector cu m elemente de tip vector cu n elemente, care au tipul de baz al
I

matricei (n exemplu, un vector cu 4 elemente de tip vector cu 2 de elemente de tip int). Zona
ED
94 Implementarea structurilor de date

C
de memorie alocat unei matrice are dimensiunea m n sizeof(tip_baz). n exemplu,
matricei a i se aloc o zon de memorie de 42sizeof(int) =422=16 octei. Identificarea unui
element al matricei se face folosind doi indici (i i j). Adresa tabloului este i adresa primului

I
element, a[0][0]. Dac adresa tabloului este adr, adresa elementului a[i][j] este:

OG
adr + insizeof(tip_baza) + jsizeof(tip_baza)= adr + (in+j)sizeof(tip_baza).
Pentru exemplul de mai sus, adresa elementului a[3] [1] este:
adr + 32sizeof(int) + 1sizeof(int) = adr + 322 + 12 = adr + 14.

2.2.3. Operatori pentru variabile de tip pointer

AG
Pe variabilele de tip pointer se pot aplica urmtoarele tipuri de operatori:
operatori specifici,
operatorul de atribuire,

ED
operatori aritmetici,
operatori relaionali.
2.2.3.1. Operatorii specifici

P
Operatorii specifici variabilelor de tip pointer sunt:
Operatorul & operatorul de adresare. Se aplic pe o variabil de memorie sau un
I
element de tablou de memorie i furnizeaz adresa variabilei de memorie, respectiv a
elementului de tablou. Rezultatul obinut prin aplicarea acestui operator este de tip
pointer. Operaia se numete referenierea unei variabile de memorie.
Operatorul * operatorul de redirectare. Se aplic pe o variabil de tip pointer i

furnizeaz valoarea variabilei de memorie care se gsete la adresa memorat n


IC

pointer. Rezultatul obinut prin aplicarea acestui operator este de tipul datei asociate
pointerului. Operaia se numete dereferenierea unui pointer.
& - operatorul de adresare
CT

referenierea
nume variabil de variabilei de memorie adres variabil de
memorie memorie
(coninut) (pointer)
DA

* - operatorul de redirectare
dereferenierea pointerului
Observaii:
DI

1. Pointerii reprezint adrese ale unei zone de memorie (coninutul unei variabile de me-
morie p de tip pointer este o adres de memorie).
2. Accesul la o zon de memorie se poate face fie folosind identificatorul asociat zonei
RA

de memorie (numele variabilei de memorie), fie aplicnd operatorul de redirectare * pe


adresa zonei de memorie (coninutul adresei de memorie indicate de un pointer p se
refer cu *p).
3. Dimensiunea i semnificaia coninutului unei zone de memorie indicate de un pointer
TU

depind de tipul pointerului.


Exemplul 1
int a=10, *p=&a;
cout<<*p<<endl<<a<<endl;
I

cout<<p<<endl<<&a<<endl;
ED
Informatic 95

C
S-a definit o variabil de memorie de tip int (a) i o variabil de tip pointer ctre tipul
int (*p) creia i s-a atribuit ca valoare adresa variabilei a. n memoria intern se vor aloca
dou zone de memorie: una de 2 octei, pentru variabila de memorie identificat prin numele

I
a, n care se pstreaz o valoare numeric ntreag, i una de 2 octei pentru variabila pointer

OG
identificat prin numele p, n care se pstreaz o adres de memorie (n exemplu, adresa
variabilei de memorie a). Coninutul acestor zone de memorie este prezentat n figur.
2 octei 2 octei

AG
adr 10

p a adr

ED
Memoria intern

Prin instruciunea cout<<*p; se afieaz coninutul variabilei de memorie a. Referirea la


aceast variabil de memorie se face nu prin numele variabilei, ci prin operatorul de redirec-
tare * aplicat pe variabila pointer p n care este memorat adresa variabilei a. Aceast instruc-

P
iune are acelai efect ca i instruciunea cout<<a;. Prin instruciunea cout<<p; se afiea-
z o constant hexazecimal care reprezint o adres de memorie (adresa adr la care este
I
memorat variabila a). Aceast instruciune are acelai efect ca i instruciunea cout<<&a;.
Exemplul 2
int a=10,b=20,*p=&a;
b=*p; /*variabilei b i se atribuie valoarea de la adresa

memorat n variabila p, adic valoarea variabilei a */


IC

cout<<a<<" "<<b; //afieaz 10 10


*p=100; /*variabilei a crei adres este memorat n
pointerul p (adic, variabilei a) i se atribuie valoarea 100 */
CT

cout<<a<<" "<<b; //afieaz 100 10


Observaie. Dac tipul de dat indicat de pointer este tipul nregistrare, data conine mai
multe cmpuri. Operatorul de redirectare prin care se furnizeaz coninutul unui cmp
este operatorul > i se numete operatorul de selecie indirect a membrului unei
DA

structuri.
<nume variabil pointer> > <nume cmp>
El conine dou referine: una la coninutul adresei indicate de pointer i alta ctre un
DI

membru al nregistrrii (cmpul). Rezultatul furnizat de expresie este valoarea membrului


selectat (a cmpului). Este un operator binar care are prioritate maxim i asociativi-
tatea de la stnga la dreapta.
Exemplu
RA

struct punct {int x,y;};


punct a={3,4},*p=&a;
cout<<a.x<<" "<<a.y<<endl; //afieaz 3 4
cout<<p->x<<" "<<p->y; //afieaz 3 4
TU

Observaii:
1. Operatorul * se poate folosi n ambii membri ai unei operaii de atribuire:
int a=10,b=20,*p=&a,*q=&b; // (1)
I
ED

*q=*p; // (2)
96 Implementarea structurilor de date

C
/* variabilei de la adresa memorat n variabila q, adic variabi-
lei b, i se atribuie valoarea de la adresa memorat n
variabila p, adic valoarea variabilei a

I
cout<<a<<" "<<b; //afieaz 10 10

OG
adr_a 10 adr_a 10

p a p a
adr_a *p adr_a *q=*p

AG
*p
adr_b 20 adr_b 10

q b adr_b q *q b adr_b
*q

ED
Memoria intern (1) Memoria intern (2)

2. Construcia *p (p fiind un pointer ctre un tip de dat) poate aprea n orice expresie n

P
locul unei variabile de memorie care are acelai tip ca i cel asociat pointerului:
int a=10,*p=&a;
I
*p=*p+5; /* incrementeaz cu 5 valoarea variabilei de la adresa
memorat n variabila p, adic valoarea variabilei a*/
cout<<a<<" "<<*p; //afieaz 15 15

3. Operatorii * i & sunt operatori unari i au prioritate mai mare dect operatorii
aritmetici, relaionali, logici i de atribuire.
IC

int a=10,*p=&a;
*p+=1; /* incrementeaz cu 1 valoarea variabilei de la adresa memo-
rat n p, adic valoarea variabilei a */
CT

cout<<a; //afieaz 11
4. Asociativitatea operatorilor unari este de la dreapta la stnga. Din aceast cauz,
trebuie folosii cu grij operatorii unari * i ++ (respectiv - -). Astfel, *p++ incrementeaz
DA

cu 1 adresa memorat n variabila p, i nu valoarea de la adresa memorat n p:


int a=10,*p=&a;
++*p; /* incrementeaz cu 1 valoarea variabilei de la adresa
memorat n p, adic valoarea variabilei a */
DI

cout<<a; //afieaz 11
(*p)++; /* incrementeaz cu 1 valoarea variabilei de la adresa
memorat n p, adic incrementeaz cu 1 valoarea variabilei a */
cout<<a; //afieaz 12
RA

5. Datorit tehnicii de suprancrcare a operatorilor permis de limbajul C++, caracterul *


(asterisc) este folosit i ca operator de redirectare (operator unar) i ca operator de
multiplicare (operator aritmetic). Pentru a nmuli valorile memorate la dou adrese de
memorie indicate de doi pointeri p i q este obligatoriu s se foloseasc parantezele:
TU

int a,b=10,c=20,*p=&b,*q=&c;
a=(*p)*(*q); /*variabilei a i se atribuie produsul dintre valoarea de
la adresa memorat n p, adic valoarea variabilei b, i valoarea
I

de la adresa memorat n q, adic valoarea variabilei c */


ED

cout<<a; //afieaz 200


Informatic 97

C
Considernd declaraia: int a,b,*p=&a; instruciu- b=a+10; b=*p+10;
nile de atribuire din tabelul alturat sunt echivalente: a=b; *p=b;
Aadar, localizarea unei date memorate ntr-o varia- a++; (*p)++;

I
a=a+5; *p=*p+5;

OG
bil de memorie se poate face prin:
adresare direct folosind numele variabilei de b=a*a; b=(*p)*(*p);
memorie (n exemplu a); a*=5; *p*=5;
adresare indirect folosind o variabil de tip pointer n care este memorat adresa
zonei de memorie n care este stocat data (n exemplu, p).

AG
1. Scriei un program n care declarai o variabil de memorie de tip
Tem float i un pointer ctre tipul float, citii de la tastatur valoarea
variabilei i i afiai valoarea folosind cele dou metode de adresare:
adresarea direct i adresarea indirect.

ED
2. Scriei un program n care declarai o variabil de memorie de tip nregistrare care va
conine dou cmpuri, corespunztoare numitorului i numrtorului unei fracii, i o
variabil de tip pointer ctre tipul nregistrare , citii de la tastatur valorile cmpurilor

P
din nregistrare i afiai valorile acestor cmpuri folosind cele dou metode de adre-
sare: adresarea direct i adresarea indirect.
I
2.2.3.2. Operatorul de atribuire
Unei variabile de tip pointer i se poate atribui numai o valoare care reprezint o adres de
memorie. Ea poate fi exprimat prin:

O adres de memorie obinut prin aplicarea operatorului de adresare pe o variabil


de memorie definit anterior, de acelai tip cu tipul de baz al pointerului. Dup operaia
IC

de atribuire, variabila de tip pointer va adresa zona de memorie n care este stocat
variabila de memorie.
O alt variabil de tip pointer care se refer la acelai tip de baz. Dup operaia de
CT

atribuire, cele dou variabile de tip pointer vor adresa aceeai zon de memorie.
O constant de tip adres de acelai tip cu tipul de baz al pointerului.
Numele unui tablou de memorie este o constant de tip adres. Dup operaia de
atribuire, variabila de tip pointer va adresa zona de memorie n care este stocat pri-
DA

mul element al tabloului n cazul vectorului, elementul cu indicele 0.


Constanta 0 sau constanta simbolic predefinit NULL care corespunde pointe-
rului zero poate fi atribuit oricrui tip de pointer.
Rezultatul unei expresii construite cu operanzi de tip adres a unor date definite
DI

anterior i care aparin tipului de baz al pointerului.


Observaie. Unui pointer i se poate atribui un pointer de alt tip dect tipul de baz
numai dac se aplic operatorul de conversie explicit de tip. Acest operator trebuie
RA

aplicat ns cu foarte mare precauie, deoarece de multe ori rezultatul obinut nu este cel
dorit.
int a=10, *p=&a; float *q;
q=(float*)p; //Memoria intern (1)
TU

/*tipul expresiei (float*)p este float*, adic pointer ctre tipul


float, i n acest mod pointerului q i s-a putut atribui adresa
memorat n pointerul p*/
cout<<*q<<endl; // Afieaz 1.401298e-44, un numr real.
I
ED
98 Implementarea structurilor de date

C
/* Pointerul q indic o zon de memorie de tip float de 4 octei, din
care primii 2 octei conin reprezentarea n complement fa de 2 a nu-
mrului ntreg 10, iar urmtorii 2 octei o valoare rezidual. Instruc-

I
iunea de afiare face conversia valorii memorate, din reprezentarea n

OG
format intern n reprezentarea n format extern, interpretnd-o ca pe un
numr real reprezentat n virgul mobil simpl precizie */
*q=10; cout<<*q<<endl; // Afieaz 10
p=(int*)q; // Memoria intern (2)

AG
//pointerului p i s-a atribuit adresa memorat n pointerul q
cout<<*p; // Afieaz 0, un numr ntreg.
/*Pointerul p indic o zon de memorie de tip int de 2 octei, care re-
prezint primii 2 octei din grupul de 4 octei n care a fost reprezen-
tat n virgul mobil simpl precizie numrul real 10. Instruciunea de

ED
afiare face conversia valorii memorate din reprezentarea n format
intern n reprezentarea n format extern, interpretnd-o ca pe un numr
ntreg reprezentat n complement fa de 2 */

P
2 octei 2 octei
valoare rezidual
adr
I
10

p 2 octei a
adr
adr

q
Memoria intern (1)
IC

2 octei reprezentat n virgul


2 octei mobil simpl precizie
CT

adr 10

p 2 octei a
adr 4 octei
adr
DA

q
Memoria intern (2)

Exemplul 1:
DI

char c='A',*p;
p=&c; /*variabilei p de tip pointer ctre caracter i se atribuie
adresa variabilei de memorie c */
cout<<c<<" "<<*p; //afieaz A A
RA

Exemplul 2:
int a=10,*p=&a,*q;
q=p; /* pointerului q i se atribuie valoarea pointerului p, adic
TU

adresa variabilei a */
cout<<*p<<" "<<*q; //afieaz 10 10
Exemplul 3: Numele unui vector este numele unei variabile de memorie, dar i o con-
stant de tip adres cu tipul de baz al elementelor vectorului, care indic primul element
I

al vectorului. Pointerului p i se poate atribui adresa vectorului a exprimat prin:


ED
Informatic 99

C
constanta simbolic a;
operatorul de adresare & aplicat pe numele variabilei a;
operatorul de adresare & aplicat pe identificatorul primului element al vectorului a[0],

I
iar urmtoarele operaii de atribuire sunt echivalente:

OG
p=a p=&a p=&a[0] i *p a[0]
int a[10],i,k=1,*p;
for (i=0;i<10;i++) a[i]=k++;
p=a; /*variabilei p i se atribuie numele vectorului a, care

AG
este o constant simbolic de tip adres */
cout<<*p<<" "<<a[0]<<endl; //afieaz 1 1 - valoarea elementului a[0]
Exemplul 4: Numele unei matrice este numele unei variabile de memorie, dar i o con-
stant de tip adres cu tipul de baz al elementelor matricei, care indic primul element

ED
al matricei. Pentru un pointer p cu tipul de baz al elementelor matricei a, care trebuie s
indice primul element al matricei, urmtoarele operaii de atribuire sunt echivalente:
p=a p=&a p=a[0] p=&a[0][0] i *p a[0][0]
int a[10][10],i,j,k=1,*p;

P
for (i=0;i<10;i++)
for (j=0;j<10;j++) a[i][j]=k++;
I
p=a; /*variabilei p i se atribuie numele matricei a, care
este o constant simbolic de tip adres */
cout<<*p<<" "<<a[0][0]<<endl; //afieaz 1 1 - valoarea elementului a[0][0]
Exemplul 5:

int a[4][5],i,j,k=1,*p;
IC

for (i=0;i<4;i++)
for (j=0;j<5;j++) a[i][j]=k++;
p=a[0]; /*variabilei p i se atribuie adresa vectorului format
CT

din prima linie a matricei a, care este o constant */


cout<<*p<<" "<<a[0][0]<<endl;
//afieaz 1 1 - valoarea elementului a[0][0]
DA

Exemplul 6:
int *q;
q=0; // pointerului q i se atribuie constanta 0
cout<<*q<<endl; /*nu afieaz nimic, deoarece pointerul q are
DI

valoarea 0 i el nu indic nici o adres de memorie */


q=NULL; // pointerului q i se atribuie constanta simbolic NULL
cout<<*q; /*nu afieaz nimic deoarece pointerul q are
valoarea NULL i el nu indic nici o adres de memorie */
RA

Unui pointer nu i se poate atribui valoarea unei constante ntregi,


Atenie chiar dac este o constant hexazecimal, deoarece programatorul
nu are acces direct la adresele de memorie pentru a le gestiona.
TU

Unei date nu poate s i atribuie o adres de memorie dect sistemul de operare.


Deoarece numele tabloului de memorie este folosit de compila-
Atenie torul C++ ca o constant simbolic de tip adres, unei variabile
de tip tablou nu i se poate atribui o alt variabil de tip tablou sau un
I
ED

pointer, ca n exemplul urmtor:


100 Implementarea structurilor de date

C
int a[10],b[10],*p=&b;
a=b; a=p; // Eroare! Unei constante nu i se poate modifica valoarea
Scriei un program n care declarai o variabil de memorie de tip nre-

I
Tem

OG
gistrare, care conine dou cmpuri corespunztoare numitorului i nu-
mrtorului unei fracii i o variabil de tip pointer ctre tipul nregistrare
i care s realizeze urmtoarele:
a. atribuie pointerului adresa variabilei nregistrare;
b. citete de la tastatur valorile pentru numrtor i numitor;

AG
c. afieaz fracia simplificat rezultatele se obin n dou variante, folosind cte una
dintre cele dou metode de adresare (adresarea direct i apoi adresarea indirect)
i se compar rezultatele obinute.

ED
2.2.3.3. Operatorii aritmetici
Operaiile aritmetice permise asupra pointerilor sunt:
Adunarea i scderea unei constante operatorii + i -.
Incrementarea i decrementarea unui pointer operatorii ++ i --.

P
Scderea a doi pointeri de acelai tip operatorul -.
Toate operaiile aritmetice cu pointeri ctre un tip de baz se execu-
I
Atenie t considernd unitatea egal cu sizeof(tip_baz), adic egal cu
numrul de octei necesari pentru a memora o dat care are tipul
tip_baz. De exemplu, incrementarea unui pointer ctre tipul int va considera unitatea
egal cu 2 (numrul de octei necesari pentru reprezentarea tipului int) i noua adres se

va obine prin adunarea constantei 2 la adresa iniial memorat de pointer.


IC

Operatorul pentru adunarea sau scderea unei constante este:


p + k sau p - k
CT

unde p este un pointer ctre tipul tip_baza care memoreaz o adres adr, iar k o constan-
t. Rezultatul este o adres care se calculeaz astfel: adr+ksizeof(tip_baza), respectiv
adr-ksizeof(tip_baza).
Observaie: Operaia de adunare este comutativ: p+k = k+p.
DA

Operatorul pentru incrementarea i decrementarea unui pointer este:


p++ sau p- -
unde p este un pointer ctre tipul tip_baza care memoreaz o adres adr. Rezultatul este
DI

o adres care se calculeaz astfel: adr+sizeof(tip_baza), respectiv adr-sizeof(tip_baza).


Operatorul pentru scderea a doi pointeri este:
p-q
RA

unde p i q sunt doi pointeri ctre acelai tip de baz, care indic elementele aceluiai
tablou de memorie, adresa memorat de p fiind mai mare dect cea memorat de q (p
indic un element de tablou situat n memorie dup elementul indicat de pointerul q).
Rezultatul este un numr ntreg care reprezint numrul de elemente aflate ntre p i q.
TU

Operaiile aritmetice cu pointeri au sens numai dac adresele indi-


Atenie cate de pointerii operanzi i de pointerul rezultatului expresiei se
pstreaz n spaiul de adrese ale unui tablou de memorie. Sin-
I
ED
Informatic 101

C
gura excepie acceptat este cea a pointerului care indic adresa unui element situat
imediat dup ultimul element al tabloului.
Exemplul 1 n cazul n care operatorii aritmetici se aplic pe pointeri care nu-i pstreaz

I
valorile n spaiul unui tablou de memorie, rezultatele obinute nu au nici un fel de relevan.

OG
int a=10,*p=&a,*q=p; cout<<p<<" "<<*p<<endl;
p++; cout<<p<<" "<<*p<<endl; p++; cout<<p<<" "<<*p<<endl;
/*Zona de memorie indicat de pointer dup fiecare operaie de
incrementare conine o valoare rezidual care nu are nici un fel de

AG
relevan n cadrul programului*/
cout<<p-q; // afieaz 2
Exemplul 2 Se inverseaz un vector n el nsui. Se folosesc doi pointeri p i q ctre ele-
mentele vectorului care se interschimb.

ED
int a[20],n,*p,*q,aux;
cout<<"n= ";cin>>n;
for (p=a;p<a+n;p++) {cout<<"elementul "<<p-a+1<<"= "; cin>>*p;}
for(p=a,q=a+n-1;p<q;p++,q--) {aux=*p; *p=*q; *q=aux;}

P
for(p=a;p<a+n;p++) cout<<*p<<" ";
Observaie. Prin definiie, operatorul indice al tabloului ([ ]):
I
se aplic pe doi operanzi x i y (x[y] sau y[x]), x fiind un pointer i y un ntreg;
realizeaz adunarea dintre pointerul x i constanta y, obinnd adresa elementului
y al vectorului de la adresa x;

rezultatul furnizat este valoarea indicat de pointerul obinut, adic valoarea ele-
mentului y al vectorului de la adresa x: x[y]=y[x] =*(x+y).
IC

Este un operator binar i are prioritate maxim i asociativitatea de la stnga la dreapta.


Elementul i al vectorului a poate fi identificat prin a[i], deoarece operatorul indice al ta-
bloului ([ ]) execut suma dintre pointerul a (o adres) i constanta numeric i. Prin apli-
CT

carea acestui operator se obine valoarea de la adresa elementului i. Deoarece operaia


de adunare dintre un pointer i o constant este comutativ, urmtoarele expresii sunt
echivalente i se pot folosi pentru identificarea elementului i al vectorului:
a[i] *(a+i) *(i+a) i[a]
DA

Un element al matricei a poate fi identificat, folosind cei doi indici i i j, prin a[i][j].
Asociativitatea operatorului indice al tabloului fiind de la stnga la dreapta i prioritatea
sa fiind cea mai mare, calcularea adresei elementului se va face astfel: mai nti se
DI

execut suma dintre pointerul a i constanta i i apoi suma dintre rezultatul obinut
anterior i constanta j. Prin aplicarea operatorilor indice al tabloului se obine adresa
elementului din linia i i coloana j, urmtoarele expresii fiind echivalente:
a[i][j] *(a[i]+j) (*(a+i))[j] *(*(a+i)+j)
RA

*(&a[0][0]+n*i+j)

2.2.3.4. Operatorii relaionali


Operatorii relaionali care pot fi aplicai asupra pointerilor sunt:
TU

Operatorii de inegalitate: <, >, <= i >=.


Operatorii de egalitate: == i !=.
Evaluarea unui operator relaional aplicat pe doi pointeri p i q se face prin analiza dife-
I

renei p-q.
ED
102 Implementarea structurilor de date

C
Exemplu Se afieaz ordinea n care apar dou valori x i y ntr-un vector cu numere
ntregi. Se folosesc doi pointeri p i q ctre elementele vectorului. Se parcurge vectorul
folosind pointerul p pentru localizarea valorii x i pointerul q pentru localizarea valorii y.

I
Stabilirea ordinii de apariie n vector se face prin compararea celor doi pointeri (a adreselor

OG
memorate n pointeri).
int x,y,a[100],*p=a,*q=a;
cout<<"n= ";cin>>n;
for (;p<a+n;p++) {cout<<"elementul "<<p-a+1<<"= "; cin>>*p;}

AG
cout<<"prima valoare= "; cin>>x;
cout<<"a doua valoare= "; cin>>y;
p=a;
while (*p!=x) p++;

ED
while (*q!=y) q++;
if (p>q) cout<<"valoarea "<<y<<" apare inaintea valorii "<<x;
else cout<<"valoarea "<<x<<" apare inaintea valorii "<<y;
Scriei urmtoarele programe, n care prelucrarea vectorilor se va face cu

P
Tem ajutorul pointerilor. Elementele vectorilor se citesc de la tastatur.
1. Se terge elementul cu valoarea k dintr-un vector cu numere ntregi.
Valoarea numrului k se citete de la tastatur.
I
2. Se insereaz elementul cu valoarea x naintea elementului cu valoarea y. Valorile
numerice x i y se citesc de la tastatur.
3. Se insereaz elementul cu valoarea x dup elementul cu valoarea y. Valorile

numerice x i y se citesc de la tastatur.


4. Se ordoneaz cresctor elementele vectorului.
IC

5. Se afieaz elementele comune din doi vectori a i b o singur dat.

2.3. Tipul de dat referin


CT

Acest tip de dat permite folosirea mai multor identificatori pentru aceeai variabil de me-
morie. Declararea unei variabile de tip referin se poate face prin instruciunea declarativ:
DA

tip_dat &nume_variabil = nume_variabil_referit;


tipul datei la care se
numele variabilei de memorie la care se refer
refer variabila de
variabila de memorie definit
DI

memorie definit
numele variabilei de memorie care se definete
operatorul de refereniere prin referina la o alt variabil de memorie
Exemplu: int a=10;
RA

int &b=a;
sau
int a=10,&b=a;
Variabila de memorie b este o referin ctre variabila de memorie a. Aceasta nseamn
TU

c, prin referin, variabilei de memorie (a) i s-a mai dat un nume (b). Cele dou variabile
de memorie (a i b) au aceleai atribute (adres de memorie, lungime, valoare, tip etc.), cu
excepia numelui. Chiar dac n program s-au declarat dou variabile de memorie (a i b),
se lucreaz cu o singur zon de memorie, care poate fi identificat cu dou nume diferite,
I
ED

iar urmtoarele dou instruciuni vor afia aceleai valori:


Informatic 103

C
cout<<"a = "<<a<<"adresa lui a= "<<&a<<endl;
cout<<"b = "<<b<<"adresa lui b= "<<&b;
Orice operaie de modificare a valorii variabilei referite prin numele b, va modifica valoarea

I
OG
variabilei identificate prin numele a, deoarece ambele nume de variabile se refer la coni-
nutul aceleiai zone de memorie. Urmtoarele dou instruciuni vor afia aceleai valori:
b=15;
cout<<"a = "<<a<<"adresa lui a= "<<&a<<endl;
cout<<"b = "<<b<<"adresa lui b= "<<&b;

AG
Observaii:
1. Tipul de dat referin, la fel ca i tipul de dat pointer, conine o adres. Pentru a
avea acces prin referin la o variabil de memorie nu este ns nevoie s se

ED
foloseasc adresa de memorie, ci numele variabilei referin.
Exemplu:
int a=10,b=200; //s-au declarat dou variabile ntregi

P
int &x=a; //s-a declarat o referin la variabila a
int *p=&a; //s-a declarat un pointer care indic variabila a
int *q=&x; //s-a declarat un pointer care indic variabila x
I
cout<<a<<" "<<x<<" "<<*p<<" "<<*q<<" "<<endl;
//afieaz 10 10 10 10
*p=20; cout<<a<<" "<<x<<" "<<*p<<" "<<*q<<" "<<endl;

//afieaz 20 20 20 20
x=30; cout<<a<<" "<<x<<" "<<*p<<" "<<*q<<" "<<endl;
IC

//afieaz 30 30 30 30
p=&b; //p indic variabila b
cout<<b<<" "<<*p<<endl; //afieaz 200 200
CT

p=&x; //p indic variabila x care se refer la variabila a


cout<<b<<" "<<*p<<endl; //afieaz 200 30
2. Operatorii aritmetici aplicai pe variabile referin nu modific valoarea adresei refe-
rite, ci valoarea memorat la adresa variabilei referite. Operatorii relaionali aplicai pe
DA

variabile referin nu compar valorile adreselor referite, ci valorile memorate la


adresele variabilelor referite.
Exemplu:
DI

int a=10,b=20,&x=a,&y=b;
x=30; cout<<a<<" "<<x<<endl; //afieaz 30 30
x++; cout<<a<<" "<<x<<endl; //afieaz 31 31
x=--x; x+=x*2; cout<<a<<" "<<x<<endl; //afieaz 90 90
RA

if (x!=y) cout<<"adevarat" <<endl; //afieaz adevarat


x=++y; cout<<a<<" "<<x<<endl; //afieaz 21 21
cout<<b<<" "<<y<<endl; //afieaz 21 21
if (x==y) cout<<"adevarat" <<endl; //afieaz adevarat
TU

Atenie 1. Referina trebuie iniializat chiar n momentul declarrii ei.


Exemplu:
I
ED

int a,&b; // Eroare: variabila referin nu a fost iniializat


104 Implementarea structurilor de date

C
2. Dup ce a fost iniializat, referina nu mai poate fi modificat (nu se mai poate
schimba adresa de memorie la care se refer).
Exemplu:

I
OG
int a=10,b=100,&x=a;
cout<<a<<" "<<x<<endl; //afieaz 10 10
x=&b; /* Eroare: variabilei referin x nu i se poate atribui
adresa variabilei de memorie b, deoarece variabila x, prin definiie,
se refer la variabila de memorie a i memoreaz adresa ei */

AG
x=b; /* Corect: variabilei referin x i se poate atribui
valoarea variabilei de memorie b, aceasta nsemnnd c variabilei
referite de x (variabila a) i se atribuie valoarea variabilei b */
cout<<a<<" "<<x<<endl; //afieaz 100 100

ED
3. Nu se poate crea un pointer la o referin.
Exemplu:
int a=10,&x=a;

P
int *p=x; /* Eroare: pointerului p nu i se poate atribui adresa
memorat n variabila x, deoarece numele variabilei x nu identific o
adres, ci o valoare ntreag memorat la adresa variabilei a */
I
int *p=&x; /* Corect: pointerului p i se poate atribui adresa
variabilei referin x, aceasta fiind de fapt adresa variabilei a */
4. Nu este permis declararea unei referine la o adres exprimat printr-o referin

sau printr-un pointer.


Exemplu:
IC

int a=10,b=100,*p=&a,*q=&b,&x=a;
int &y=&x; /* Eroare: s-a declarat variabila y care trebuie s se re-
fere la o variabil de tip int, ca o referin la adresa variabilei x */
CT

int &y=x; /* Corect: s-a declarat variabila y ca o referin la


variabila x, care este o referin la variabila a; variabila y se refer
la variabila a */
DA

int &z=q; /* Eroare: s-a declarat variabila z, care trebuie s


se refere la o variabil de tip int, ca o referin la variabila
pointer q care memoreaz o adres */
int &z=*q; /* Corect: s-a declarat variabila z, care trebuie s
DI

se refere la o variabil de tip int, ca o referin la o variabil


a crei adres este indicat de pointerul q (adic variabila b)*/
cout<<a<<" "<<*p<<" "<<x<<" "<<y<<endl; //afieaz 10 10 10 10
cout<<b<<" "<<*q<<" "<<z<<endl; //afieaz 100 100 100
RA

*p=20; cout<<a<<" "<<*p<<" "<<x<<" "<<y<<endl;


//afieaz 20 20 20 20
x=30; cout<<a<<" "<<*p<<" "<<x<<" "<<y<<endl;
//afieaz 30 30 30 30
TU

p=&z; b=200;
cout<<a<<" "<<*p<<" "<<x<<" "<<y<<" "<<*q<<" "<<z<<endl;
//afieaz 30 200 30 30 200 200
5. Tipul referinei i tipul variabilei la care se refer trebuie s fie acelai i referina
I
ED

i obiectul la care face referirea trebuie s fie de acelai tip. Astfel, dac referina
Informatic 105

C
este o variabil de memorie, referirea trebuie s se fac tot la o variabil de memorie,
i nu, de exemplu, la o constant, chiar dac aceasta este de acelai tip cu referina. n
cazul n care nu se respect aceste reguli, compilatorul v va ateniona. Aceasta

I
nseamn c programul va putea fi executat, dar rezultatul obinut nu va fi cel ateptat,

OG
deoarece se creeaz o variabil de memorie temporar, cu tipul referinei, creia i se
atribuie valoarea variabilei referite, respectiv a constantei, iar variabila referin va
adresa aceast variabil temporar, i nu variabila referit, respectiv constanta:
Exemplu:

AG
char c='A'; float &a=c;
//echivalent cu: char c='A'; float temp=c; float &a=temp;
//temp fiind variabila de memorie temporar
cout<<a<<" "<<c<<endl; //afieaz 65 A

ED
a=a/5; cout<<a<<" "<<c<<endl; //afieaz 13 A
c++; cout<<a<<" "<<c<<endl; //afieaz 13 B
int &a=10; //echivalent cu: int temp=10; int &a=temp;
//temp fiind variabila de memorie temporar

P
cout<<a<<endl; //afieaz 10
a=20; cout<<a; //afieaz 20
I
Scriei un program n care declarai o variabil de memorie de tip float i
Tem o referin ctre aceast variabil de memorie, citii de la tastatur i
afiai valoarea variabilei de tip float folosind cele dou nume ale vari-
abilei de memorie.

Utilitatea tipului de dat referin


IC

Tipul de dat referin este util n transmiterea datelor ntre modulul apelant i subprogam prin
intermediul parametrilor de comunicaie. n timpul execuiei subprogramului, datele cu care
el lucreaz (variabilele locale i parametrii cu care a fost apelat) sunt pstrate n stiv.
CT

Instruciunile subprogramului pot modifica aceste date. Modificrile se execut asupra


valorilor memorate n stiv. Cnd se termin execuia subprogramului, spaiul ocupat n
stiv de parametri i de variabilele locale este eliberat i n cazul parametrilor de ieire
DA

sau de intrare-ieire se pierd valorile calculate n subprogram.


void sb(int a) {a=a+2; cout<<a<<endl;;} //afieaz 4
void main() {int a=2; sb(a); cout<<a; } //afieaz 2
Folosind transferul parametrului prin referin, n momentul apelrii subprogramului, n
DI

stiv este ncrcat adresa de memorie la care se gsete valoarea parametrului. Subprogra-
mul va lucra direct n zona de memorie n care se gsete data. Aadar, att modulul apelant
ct i subprogramul lucreaz asupra aceleiai date, i orice modificare a valorii acestui
parametru fcut n subprogram se va reflecta i n modulul apelant. La terminarea execuiei
RA

subprogramului, este eliberat din stiv zona n care este memorat adresa parametrului.
void sb(int &a) {a=a+2; cout<<a<<endl;;} //afieaz 4
void main() {int a=2; sb(a); cout<<a; } //afieaz 4
TU

ntre modulul apelant i subprogram se pot transmite i parametri de tip adres. Dac
adresa este transmis prin valoare i ea este modificat n subprogram, noua valoare se
pierde la terminarea execuiei subprogramului.
void sb(int *p) {int x=4; p=&x cout<<*p<<endl;} //afieaz 4
I
ED

void main() {int a=2,*p=&a; sb(p); cout<<*p;} //afieaz 2


106 Implementarea structurilor de date

C
Folosind transferul parametrului prin referin pentru pointer, n momentul apelrii subpro-
gramului, n stiv este ncrcat adresa de memorie a pointerului i subprogramul va lucra
direct n zona de memorie n care se gsete pointerul. Aadar, att modulul apelant ct i

I
subprogramul lucreaz asupra aceleiai date, i orice modificare a adresei memorate n

OG
pointer fcut n subprogram se va reflecta i n modulul apelant. La terminarea execuiei
subprogramului, este eliberat din stiv zona n care este memorat adresa pointerului.
void sb(int *&p) {int x=4; p=&x; cout<<*p<<endl;} //afieaz 4
void main() {int a=2,*p=&a; sb(p); cout<<*p;} //afieaz 4

AG
2.4. Alocarea dinamic a memoriei
Declarrile de date n cadrul programului folosesc alocarea static a memoriei.

ED
Alocarea static a memoriei se face n timpul compilrii, n funcie de modul
n care a fost declarat variabila de memorie sau structura de date,
iar n timpul execuiei programului nu mai poate fi modificat.
Variabilele care folosesc alocarea static a memoriei se numesc variabile statice.

P
Sistemul de operare le aloc spaiu n segmentul de date sau n stiva sistemului, n
funcie de modul n care au fost declarate n program (globale sau locale).
I
Structurile de date statice au un mare dezavantaj, deoarece n timpul execuiei progra-
mului pot s apar urmtoarele cazuri:
spaiul alocat structurii este insuficient i este posibil ca s se depeasc acest
spaiu i s se intre n spaiul de memorie alocat altor date;

spaiul alocat structurii este mult mai mare dect este necesar i memoria intern
nu este utilizat eficient.
IC

Acest dezavantaj poate fi eliminat prin folosirea alocrii dinamice a memoriei.


Alocarea dinamic este metoda prin care unei variabile de memorie sau unei
CT

structuri de date i se atribuie spaiu de memorie sau se elibereaz spaiul de


memorie ocupat de ea n timpul execuiei programului, n funcie de necesiti.
Variabilele care folosesc alocarea dinamic a memoriei se numesc variabile dinamice.
DA

Spaiul de memorie alocat va fi n zona de adrese libere (Heap). Sistemul de operare alo-
c unei date zon de memorie n Heap sau elibereaz spaiul de memorie alocat datei, n
urma unor cereri de alocare de memorie i de eliberare de memorie din program. Meca-
nismul prin care programatorul folosete alocarea dinamic a memoriei este urmtorul:
DI

1. Se declar o variabil de memorie de tip pointer ctre tipul de dat al variabilei


dinamice.
<tip de baza> *<nume pointer>;
RA

La compilarea programului, variabilei pointer i se va aloca spaiu n segmentul de date


sau n stiva sistemului, n funcie de modul n care a fost declarat n program (global
sau local). n variabila pointer se va memora adresa variabilei dinamice.
2. n momentul n care n program trebuie folosit variabila dinamic se cere sistemului
TU

de operare s i aloce spaiu n Heap. Pentru cererea de alocare de memorie se


folosete operatorul new:
<nume pointer> = new <tip de baza>;
Sistemul de operare caut n Heap o zon de memorie liber, de dimensiunea tipului
I
ED

variabilei dinamice, i atribuie pointerului adresa acestei zone.


Informatic 107

C
3. n momentul n care n program nu mai este folosit variabila dinamic se cere
sistemului de operare s elibereze spaiul de memorie pe care i l-a alocat n Heap.
Pentru cererea de eliberare a memoriei se folosete operatorul delete:

I
delete <nume pointer>;

OG
Sistemul de operare declar liber zona de memorie care a fost alocat variabilei
dinamice, i consider c variabila pointer nu mai este iniializat cu o adres de
memorie, iar valoarea care a fost memorat n variabila dinamic se pierde.
Observaie. Operatorii new i delete sunt operatori unari i au prioritatea i

AG
asociativitatea acestui tip de operatori.

ED
Scop: exemplificarea modului n care putei folosi alocarea dinamic a memoriei.
Enunul problemei 1: Se citesc de la tastatur trei numere ntregi a, b i c care
reprezint mrimile laturilor unui triunghi. S se afieze aria triunghiului.
Se folosete alocarea dinamic a variabilelor elementare. Pentru referirea mrimilor

P
laturilor se folosesc pointerii a, b i c ctre tipul int, iar pentru referirea ariei i a semi-
perimetrului se folosesc pointerii aria i sp ctre tipul float.
I
#include<iostream.h>
#include<math.h>
void main()
{int *a,*b,*c; float *aria, *sp; //se declar pointerii (1)

a = new int; b = new int; c = new int; //se aloc memorie pentru
aria = new float; sp = new float; //variabilele dinamice (2)
IC

//se citesc de la tastatur valorile variabilelor dinamice


//folosite pentru laturile triunghiului
CT

cout<<"a= "; cin>>*a; cout<<"b= "; cin>>*b; cout<<"c= "; cin>>*c;


//se calculeaz valorile variabilelor dinamice folosite pentru
//semiperimetru i arie
*sp=(*a+*b+*c)/2.; *aria=sqrt(*sp*(*sp-*a)*(*sp-*b)*(*sp-*c));
DA

//se afieaz valoarea variabilei dinamice folosite pentru arie


cout<<"aria= "<<*aria;
//se elibereaz zona de memorie alocat variabilelor dinamice (3)
delete a; delete b; delete c; delete aria; delete sp;}
DI

Enunul problemei 2: Se citesc de la tastatur coordonatele a dou puncte din plan a


i b. S se afieze distana dintre cele dou puncte.
Se folosete alocarea dinamic a structurii de date de tip nregistrare. Pentru referi-
RA

rea coordonatelor celor dou puncte se folosesc pointerii a i b ctre tipul nregistrare
punct, iar pentru referirea distanei se folosete pointerul d ctre tipul float.
#include<iostream.h>
#include<math.h>
TU

struct punct {int x,y;};


punct *a,*b; float *d; //se declar pointerii (1)
void main()
{//se aloc memorie pentru variabilele dinamice (2)
I

a = new punct; b = new punct; d = new float;


ED
108 Implementarea structurilor de date

C
//se citesc de la tastatur valorile variabilelor dinamice
//folosite pentru coordonatele punctelor a i b
cout<<"coordonatele punctului a - x: "; cin>>a->x;

I
cout<<" - y: "; cin>>a->y;

OG
cout<<"coordonatele punctului b - x: "; cin>>b->x;
cout<<" - y: "; cin>>b->y;
//se calculeaz valoarea variabilei dinamice folosite pentru distan
*d=sqrt(pow(a->x-b->x,2)+pow(a->y-b->y,2));

AG
//se afieaz valoarea variabilei dinamice folosite pentru distan
cout<<"distanta dintre punctele a si b este "<<*d;
//se elibereaz zona de memorie alocat variabilelor dinamice (3)
delete a; delete b; delete d;}

ED
Enunul problemei 3: Se citesc de la tastatur n numere ntregi care se memoreaz ntr-un
vector. S se inverseze vectorul n el nsui i s se afieze vectorul dup inversare.
Se folosete alocarea dinamic a structurii de date de tip vector. Pentru referirea num-
rului de elemente ale vectorului se folosete pointerul n ctre tipul int, iar pentru referirea

P
variabilei prin intermediul creia se interschimb dou elemente ale vectorului se folosete
pointerul aux ctre tipul int. Pentru referirea vectorului se folosete pointerul p ctre tipul
int[*n]. Acest pointer indic o zon continu de nsizeof(int) octei, n reprezentnd
I
valoarea citit de la tastatur pentru numrul de elemente ale vectorului i care este referit
de pointerul n. Pointerii q i r ctre tipul int se folosesc pentru a parcurge zona de
memorie alocat vectorului n vederea prelucrrii elementelor lui.

#include<iostream.h>
#include<math.h>
IC

void main()
{int *p,*q,*r,*n,*aux; //se declar pointerii (1)
//se aloc memorie pentru variabilele dinamice (2)
CT

n=new int; aux=new int; cout<<"n= "; cin>>*n;


p = new int[*n];
//se citesc de la tastatur valorile pentru elementele vectorului
DA

for (q=p;q<p+*n;q++)
{cout<<"elementul= "<<q-p+1<<"= "; cin>>*q;}
//se interschimb elementele vectorului
for (q=p,r=p+*n-1;q<r;q++,r--) {*aux=*q; *q=*r; *r=*aux;}
DI

//se afieaz elementele vectorului


for (q=p;q<p+*n;q++) cout<<*q<<" ";
//se elibereaz zona de memorie alocat variabilelor dinamice (3)
delete []p; delete n; delete aux;}
RA

Scriei urmtoarele programe n care folosii alocare dinamic a memoriei:


Tem a. Citii de la tastatur temperatura, presiunea i numrul de moli ai unui
gaz i calculai volumul lui.
b. Citii de la tastatur numrtorul i numitorul a dou fracii, calculai suma i produsul
TU

celor dou fracii, simplificai rezultatele obinute i apoi afiai suma i produsul.
c. Citii de la tastatur coordonatele a dou coluri ale unui dreptunghi (colul din stnga
sus i colul din dreapta jos) i afiai dimensiunea diagonalei dreptunghiului.
I
ED
Informatic 109

C
d. Citii de la tastatur temperaturile medii zilnice din luna precedent i afiai tempe-
ratura medie a lunii, i zilele n care temperaturile au fost mai mari dect media.

I
2.5. Clasificarea structurilor de date

OG
Organizarea n structuri de date a datelor prelucrate de algoritmi simplific multe dintre
operaiile de prelucrare. Atunci cnd organizai datele ntr-o structur de date, trebuie s
identificai modul n care putei avea acces la ele i operaiile pe care le putei executa cu

AG
datele din colecie. Procesul de organizare a datelor n colecii este un proces care se
desfoar pe trei niveluri care interacioneaz ntre ele, pornind de la nivelul conceptual:
nivel conceptual
(nivelul la care se dezvolt imaginea mental a structurii de date: modul

ED
n care trebuie organizate datele i relaiile care exist ntre ele)

nivel logic
(nivelul la care se alege un model de implementare a structurii

P
conceptuale)
I
nivel fizic
(nivelul la care sunt stocate datele n memoria calculatorului i care implic
anumite caracteristici ale operaiilor de accesare i de prelucrare a datelor din

colecie, n funcie de modul n care sunt memorate datele i de algoritmii


implementai n limbaj pentru accesarea, citirea i scrierea datelor n memorie)
IC

Ai studiat structurile de date implementate la nivel fizic n limbajul C++:


tabloul de memorie structur de date omogen, liniar, intern i temporar;
CT

fiierul structur de date omogen, liniar, extern i permanent;


irul de caractere structur de date omogen, liniar, intern i temporar;
nregistrarea structur de date neomogen, intern i temporar.
Ai mai studiat i o structur de date logic lista structur de date omogen, liniar, intern
DA

i temporar i o metod de implementare la nivel logic a listei folosind vectorul.

Scop: exemplificarea modului n care identificai structura de date pe care o folosii


DI

pentru a rezolva problema.


Enunul problemei 1. O firm de transport are un parc de 10 maini cu capaciti de
transport diferite. Trebuie s se determine cte dintre aceste maini au cea mai mare
RA

capacitate de transport.
Pentru rezolvarea problemei trebuie stabilit structura de date care se va folosi:
La nivel conceptual capacitile de transport ale mainilor reprezint un ir de
numere ntregi, aranjate ntr-o ordine aleatorie, n care trebuie cutat numrul cel mai
TU

mare i de cte ori apare n ir.


20 40 50 30 20 40 50 40 30 40
La nivel logic implementarea permis de limbajul C++ a unei colecii de date omogene
I

este vectorul, fiecare numr ntreg fiind un element al structurii. Pentru rezolvarea proble-
ED
110 Implementarea structurilor de date

C
mei se vor folosi urmtorii algoritmi: algoritmul pentru parcurgerea vectorului la memo-
rarea numerelor, algoritmul pentru determinarea valorii maxime dintr-un ir de numere i
algoritmul de cutare n vector a elementelor cu o valoare precizat (valoarea maxim).

I
int a10;

OG
La nivel fizic numerele vor fi memorate ntr-o zon continu de memorie intern, fiecrui
numr alocndu-i-se acelai spaiu pentru memorare. Identificarea unui element al
structurii se face prin numrul su de ordine (indicele).
20 40 50 30 20 40 50 40 30 40

AG
a0 a1 a2 a3 a4 a5 a6 a7 a8 a9
Dac se dorete pstrarea datelor memorate (capacitile de transport ale mainilor din
parcul auto) pentru prelucrarea lor ulterior, se vor salva ntr-un fiier text, de unde vor fi
restaurate n memoria intern ntr-un vector, la fiecare prelucrare (execuie a programului).

ED
Observaie. n structura de date folosit (vectorul), ntre elementele structurii exist o
relaie de ordine n care fiecare element are un succesor i un predecesor. Acest tip de
structur este o structur liniar.

P
a1 a2 ... ai-1 ai
I ai+1 ... an

a1 = primul element ai = element an = ultimul element


(nu are predecesor) succesorul su este ai+1 (nu are succesor)
predecesorul su este ai-1

Enunul problemei 2. Un profesor trebuie s calculeze media semestrial a fiecrui elev din
clas i s obin o list cu numele, prenumele i mediile elevilor, n ordinea descresctoare
IC

a mediilor.
Pentru rezolvarea problemei, trebuie stabilit structura de date care se va folosi:
La nivel conceptual elevii din clas reprezint un ir de entiti care sunt caracte-
CT

rizate de o list de proprieti (atribute): nume i prenume (care identific unic elevul),
cinci note i media semestrial.
Nume Prenume Nota 1 Nota 2 Nota 3 Nota 4 Nota 5 Media
DA

1 Anghel Maria 10 9 10 9 9,5



30 Vlad Mihai 7 6 8 7
La nivel logic implementarea permis de limbajul C++ a unei colecii de date omogene
DI

este vectorul, fiecare list de atribute ale unui elev fiind un element al structurii. Pentru
implementarea listei de atribute (care este format din date neomogene: numele i
prenumele sunt iruri de caractere, notele sunt numere ntregi, iar media este un numr
real) se va folosi structura de date de tip nregistrare, fiecare atribut fiind memorat ntr-un
RA

cmp. Pentru rezolvarea problemei se vor folosi urmtorii algoritmi: algoritmul pentru
parcurgerea vectorului la memorarea listei de atribute a fiecrui elev i la afiarea mediilor,
algoritmul pentru calcularea mediei aritmetice i algoritmul de sortare a elementelor
vectorului n funcie de valoarea unui atribut din lista de atribute.
TU

struct elev
{char nume[20], pren[20];
unsigned nota[5];
float media;};
I

elev clasa30;
ED
Informatic 111

C
La nivel fizic listele de atribute ale fiecrui elev vor fi memorate ntr-o zon continu de
memorie intern, fiecrei liste de atribute alocndu-i-se acelai spaiu pentru memorare.
Identificarea unei liste de atribute n cadrul structurii se face prin numrul su de ordine

I
(indicele), iar identificarea unui atribut din list se face prin numele cmpului.

OG
i n cazul acestui exemplu, dac se dorete pstrarea datelor memorate (lista de atribute
a fiecrui elev din clas), pentru prelucrarea lor ulterior, se vor salva ntr-un fiier text, de
unde vor fi restaurate n memoria intern ntr-un vector de nregistrri, la fiecare prelucrare
(execuie a programului).

AG
Clasa

clasa[0] clasa[1] ... clasa[i] ... clasa[29]

ED
nume pren nota media

P
nota[0] nota[1] nota[2] nota[3] nota[4]
I
clasa[i].nume
clasa[i].nota[2]
Observaie. n structura de date folosit pentru lista de atribute, ntre elementele structurii
exist o relaie de ordine n care fiecare element are un singur predecesor i nici unul, unul

sau mai muli succesori. Entitatea elev (corespunde unui element din vectorul clasa) are ca
predecesor entitatea clasa i ca succesori entitile: nume, pren, nota i media. Entitatea
IC

nume are un singur predecesor (entitatea elev) i nici un succesor. Entitatea nota are un
singur predecesor (entitatea elev) i cinci succesori (nota[0], nota[1], nota[2], nota[3] i
CT

nota[4]). Structurile de date de tip nregistrare pot fi ierarhizate pe unul sau mai multe
niveluri. Acest model de reprezentare a datelor se numete arbore cu rdcin, iar acest
tip de structur de date este o structur ierarhizat.
DA

a1 Nivelul 1

a11 a12 a13 Nivelul 2


DI

a111 a112 a121 a122 a123 a131 Nivelul 3

Nivelul 4
a1221 a1222
RA

ntr-o structur de date ierarhizat, datele pot fi grupate pe mai multe niveluri. Elementul
a1 se gsete pe nivelul 1. El nu are predecesor, dar are trei succesori: a11, a12 i a13.
care se gsesc pe nivelul 2. Elementul a12 are un singur predecesor (a1) i trei succesori:
TU

a121, a122 i a123. Elementele a111, a112, a121, a123 i a131 de pe nivelul 3 i elementele
a1221 i a1222 de pe nivelul 4 nu au succesori.
O matrice cu n linii i m coloane este i ea o structur de date ierarhizat pe trei niveluri:
I

pe primul nivel este matricea care are n succesori: liniile, care sunt pe nivelul 1. Fiecare
ED
112 Implementarea structurilor de date

C
linie are ca predecesor matricea i ca succesori cele m elemente de pe o linie, care se
gsesc pe nivelul 3.
Nivelul 1

I
Matricea

OG
linia 0 linia 1 linia 2 linia 3 Nivelul 2

a[0][0] a[0][1] a[3][0] a[3][1]

AG
a[1][0] a[1][1] a[2][0] a[2][1] Nivelul 3

Enunul problemei 3. O persoan dorete s viziteze apte obiective turistice care se


gsesc n apte localiti, pe care le notm cu A, B, C, E, F, G i I. ntre cele apte obiective

ED
turistice exist mai multe ci de acces. Trebuie s se gseasc un traseu, astfel nct
turistul s plece din localitatea A i s revin n localitatea A, vizitnd toate cele apte
obiective fr s treac de dou ori prin aceeai localitate. Dac exist mai multe trasee,

P
s se caute traseul cu drumul cel mai scurt.
Pentru rezolvarea problemei, trebu-
ie stabilit structura de date care se
I
va folosi. Localitile reprezint
entiti care pot fi legate sau nu prin
ci de acces. Fiecare cale de acces

este caracterizat de distana dintre


cele dou localiti. Pentru a repre-
IC

zenta la nivel conceptual aceast


structur de date vom reprezenta
n plan harta zonei turistice prin
CT

intermediul unor elemente geome-


trice, astfel: localitile se reprezint prin cercuri n interiorul crora vom scrie identificatorul
localitii, iar cile de acces prin linii drepte care unesc anumite puncte. Acest model de
reprezentare a datelor se numete graf.
DA

Observaie. n structura de date folosit pentru a reprezenta la nivel conceptual entitile


(localitile), ntre elementele structurii exist o relaie de ordine n care fiecare
element are mai muli predecesori i mai muli succesori. Acest tip de structur de
date este o reea.
DI

Din studiul de caz anterior putem folosi un nou criteriu pentru clasificarea structurilor
de date:
criteriul relaiei de ordine
RA

Liniare Ierarhizate (arborescente) Reea


Fiecare element are un ntre elemente exist o relaie de subordo- ntre elemente exist o
TU

succesor i un nare, n care fiecare element are un pre- relaie de subordonare,


predecesor, exceptnd decesor unic i poate avea unul sau mai n care fiecare element
primul element, care nu muli succesori, cu excepia primului element poate avea mai muli
are dect succesor, i (numit rdcin), care nu are predecesor, i predecesori i mai muli
ultimul element, care nu a ultimelor elemente (numite terminale), succesori.
I

are dect predecesor. care nu au succesor.


ED
Informatic 113

C
2.6. Lista liniar

I
Pe lng criteriile studiate pentru clasificarea structurilor de date, mai exist i urm-

OG
toarele criterii:
Implementarea n limbajul de programare

Structuri implicite Structuri explicite

AG
Structura creat la nivel conceptual este Structura creat la nivel conceptual nu este
implementat la nivelul limbajului de implementat la nivelul limbajului de
programare. Reprezentarea sa este programare. Reprezentarea sa se face folosind
implicit i nu mai necesit informaii structurile implicite implementate n limbaj, fiind

ED
suplimentare pentru localizarea necesare informaii suplimentare pentru
componentelor. localizarea componentelor.

Dispunerea elementelor n memorie

Structuri contigue
P Structuri dispersate
I
Elementele sunt dispuse n zone contigue Elementele sunt dispuse n zone dispersate de
de memorie, care permit localizarea uneia memorie; pentru a putea localiza elementele n
dintre ele folosind o adres de referin i structur, trebuie s se memoreze pentru fiecare
deplasarea fa de adresa de referin. element i adresa la care se gsete.

Alocarea memoriei interne


IC

Structuri statice Structuri dinamice


CT

Dimensiunea zonei alocate este fix. Dimensiunea zonei alocate nu este fix.
Alocarea ei se face n timpul compilrii, n Alocarea sau eliberarea zonelor de memorie
funcie de modul n care a fost declarat folosite de structur se face n timpul
structura, iar n timpul execuiei programului execuiei programului, n funcie de numrul
DA

nu mai poate fi modificat. de componente ale structurii.

Lista liniar este o structur de date logic, cu date omogene, n care fiecare
element are un succesor i un predecesor, exceptnd primul element, care nu
DI

are dect succesor, i ultimul element, care nu are dect predecesor.


Lista liniar, la fel ca i vectorul, din punct de vedere conceptual este o structur de
date omogen liniar. ntre cele dou structuri exist urmtoarele deosebiri:
RA

Criteriul Vectori Liste


Implementarea Sunt structuri implicite. Fiind o Sunt structuri explicite. Fiind o structur
n limbaj structur fizic, este implementat logic, trebuie aleas o metod de
TU

n limbajul de programare. Nu nece- implementare folosind structurile fizice


sit informaii suplimentare pentru lo- existente. Necesit informaii suplimentare
calizarea elementelor structurii n me- pentru localizarea elementelor structurii n
moria intern, deoarece mecanismul memoria intern, deoarece mecanismul
prin care este implementat fizic prin care este implementat fizic nu asigu-
I
ED

asigur identificarea elementelor. r identificarea elementelor.


114 Implementarea structurilor de date

C
Criteriul Vectori Liste
Dispunerea Sunt structuri contigue. Pot fi structuri dispersate. Predecesorul,
elementelor Predecesorul, elementul i elementul i succesorul nu sunt n locaii de

I
n memorie succesorul se gsesc n locaii memorie contigue. Programatorul trebuie s

OG
contigue prin mecanismul de defineasc mecanismul prin care elementele
implementare a structurii de date la structurii vor fi legate unele de altele pentru
nivel fizic. a putea fi regsite n memorie.
Alocarea Sunt structuri statice. Sunt structuri statice sau dinamice, n

AG
memoriei funcie de implementarea aleas.

Se definete lungimea listei (n) ca fiind numrul de elemente ale listei. Lista vid este lis-
ta care are lungimea 0 (nu are nici un element). Elementele listei se mai numesc i noduri.

ED
Scop: exemplificarea modului n care identificai o aplicaie n care folosii ca structur de
date lista liniar.

P
Enunurile problemelor pentru care trebuie aleas structura de date i conceput algo-
ritmul pentru prelucrarea lor:
1. ntr-o bibliotec exist o colecie de cri organizate n ordinea alfabetic a autorilor. Un
I
cititor poate mprumuta o carte (se extrage o carte din colecie) sau poate napoia o carte
(se insereaz o carte n colecie). Toate aceste operaii trebuie executate astfel nct s se
pstreze organizarea n ordine alfabetic a autorilor.

2. La o benzinrie s-a format o coad de ateptare. Mainile sunt servite n ordinea


venirii: prima main sosit este servit, iar ultima main venit se aaz la sfritul
IC

cozii. Toate aceste operaii trebuie executate astfel nct s se pstreze ordinea n
care au sosit mainile i s-au aezat la coad.
3. ntr-o stiv de cri, volumele sunt aezate n ordinea alfabetic a titlurilor. Trebuie
CT

extras o carte din stiv fr a deranja modul n care sunt ordonate crile n stiv.
Toate aceste probleme au n comun urmtoarele caracteristici:
Elementele coleciei sunt omogene (nregistrri cu aceeai structur).
Conceptual sunt structuri liniare n care fiecare element are un succesor i un pre-
DA

decesor, cu excepia primului i a ultimului element, care au numai succesor, respec-


tiv numai predecesor.
Structurile de date se modific folosind aceiai algoritmi de prelucrare: se insereaz
i se extrag elemente, pstrndu-se o anumit ordine de aranjare a elementelor.
DI

Dac s-ar alege soluia de a grupa aceste elemente ntr-o structur de date de tip vector,
algoritmii de prelucrare (de actualizare a vectorilor) vor necesita multe deplasri de elemente
care consum timp de prelucrare. Caracteristicile operaiilor de prelucrare a vectorilor sunt:
RA

Vectorul este o structur de date care are lungimea fizic fix, iar implementarea lui
la nivel fizic este un proces prin care se face conversia locaiei conceptuale a unui
element, n locaia real, din memoria intern.
Orice operaie de adugare sau extragere a unui element din colecie modific lungi-
TU

mea logic a vectorului.


Pentru a insera un element n colecie, trebuie deplasate toate elementele spre
dreapta, ncepnd cu poziia inserrii.
Pentru a extrage un element din colecie, trebuie deplasate toate elementele spre
I

stnga, de la sfrit, pn n poziia din care se extrage.


ED
Informatic 115

C
n cazul structurilor liniare care trebuie s-i pstreze n timpul exploatrii ordonarea
dup un anumit criteriu, mecanismul vectorilor este greoi. n aceste cazuri, se poate
alege ca soluie de implementare a structurii de date lista liniar ce degreveaz programa-

I
torul de ordonarea dup indice a structurii, impus de vectori.

OG
Implementarea structurilor de date cu ajutorul listelor are urmtoarele avantaje:
alocarea dinamic a memoriei care gestioneaz memoria mult mai eficient;
algoritmii de prelucrare care sunt mult mai eficieni (se execut mult mai
puine operaii pentru inserarea i tergerea unui element).

AG
n funcie de modul n care se aloc memoria intern, se pot folosi metodele:
Metode de implementare a listelor

ED
static dinamic

folosind vectori folosind pointeri

P
n funcie de modul n care sunt aranjate elementele n list, se pot folosi metodele:
Metode de implementare a listelor
I
secvenial nlnuit

numai static static dinamic


IC

Metoda de implementare Avantajul alocrii dinamice a Avantajul algoritmilor


memoriei de prelucrare
CT

static secvenial nu nu
static nlnuit nu da
dinamic nlnuit da da
DA

Implementarea static secvenial nu aduce niciunul dintre avantajele listelor, fiind o


implementare n care lista este prelucrat la fel ca un vector. n implementarea nlnuit
nodurile listei nu mai sunt stocate succesiv n memorie. Aceast implementare se poate
face att static, ct i dinamic, ntre cele dou implementri existnd urmtoarele diferene:
DI

n implementarea static, nodurile listei ocup un bloc contiguu de locaii de me-


morie (zona de memorie alocat vectorului);
n implementarea dinamic, nodurile listei ocup locaii dispersate din memorie
(a cror adres poate fi pstrat cu ajutorul pointerilor).
RA

n clasa a X-a ai nvat modul n care putei implementa static listele liniare. Algoritmii
pentru prelucrarea unei liste nlnuite sunt aceiai, att n cazul implementrii statice,
ct i n cazul implementrii dinamice.
TU

2.6.1. Implementarea dinamic a listelor n limbajul C++


Exemplu O list este format din 5 cuvinte (noduri), fiecare cuvnt avnd maxim 4
caractere. Nodurile listei se exploateaz n ordine alfabetic:
I
ED

Lista = {"alfa", "beta", "gama", "teta", "zeta"}


116 Implementarea structurilor de date

C
Memoria intern
5 locaii de memorie dispersate
identificate prin adresele adr1, adr2, adr3, adr4, adr5

I
OG
"beta" "gama" "alfa"
nodul 2 nodul 3 nodul 1 (prim)
la adresa adr2 "zeta" la adresa adr3 "teta" la adresa adr1
nodul 5 nodul 4

AG
(ultim) la adresa adr4

Deoarece nodurile listei nu sunt aranjate succesiv, ci aleatoriu, n memorie, trebuie imple-
mentat un mecanism prin care s se precizeze ordinea real a acestor noduri (ordinea n
care se nlnuie n list). Aceasta nseamn c:

ED
trebuie cunoscut locul din care ncepe lista (lanul de noduri), adic poziia primului
nod din list (nodul prim) n exemplu, nodul "alfa";
trebuie cunoscut locul n care se termin lista, adic poziia ultimului nod din list
(nodul ultim) n exemplu, nodul "zeta";

P
pentru fiecare nod din list, cu excepia ultimului nod, trebuie cunoscut nodul care
este succesorul lui de exemplu, pentru nodul "gama" trebuie cunoscut c succe-
I
sorul su este nodul "teta".
Metoda folosit pentru implementare este ca
un nod al listei s conin dou tipuri de infor- Informaia Informaia pentru
maii: informaia propriu-zis i informaia propriu-zis legtur

de legtur adresa prin care se identific nodul care urmeaz n structur. Informaia
IC

de legtur memorat n ultimul nod (n cmpul de adres) este constanta NULL (care
semnific faptul c ultimul nod nu se leag de nimic).
Memoria intern
CT

adresele nodurilor adr1, adr2, adr3, adr4, adr5


"beta" adr3 "gama" adr4 "alfa" adr2
adr2 adr3 adr1
DA

"zeta" NULL "teta" adr5


DI

adr5 adr4

nlnuirea nodurilor listei n implementarea dinamic


RA

Lista liniar nlnuit este o structur logic de date, parcurs liniar, care are dou
extremiti (nceput i sfrit), n care fiecrui element i se asociaz o informaie
suplimentar referitoare la locul elementului urmtor, din punct de vedere logic.
Un nod al listei va fi de tipul nregistrare ce conine un cmp cu informaia pentru leg-
TU

tur care este adresa succesorului exprimat printr-un pointer.


struct nod
{<tip 1> <info 11>, <info 12>, ..., <info 1n>;
<tip 2> <info 21>, <info 22>, ..., <info 2n>;
I

.............................................
ED
Informatic 117

C
<tip m> <info m1>, <info m2>, ..., <info mn>;
nod *urm;};
nod *prim, *ultim, *p;

I
Cmpurile <info ij> sunt cmpurile cu informaii, iar cmpul urm este un cmp de tip

OG
pointer ctre tipul de baz nod i conine informaia de legtur (adresa urmtorului nod
din list). Acest tip de nregistrare se numete nregistrarea autoreferit. S-au declarat
variabilele de tip adres a unei nregistrri de tip nod:
*prim i *ultim pentru a memora adresa primului nod, respectiv a ultimului nod;

AG
ele v ajut s identificai extremitile listei;
*p pentru a memora adresa unui nod curent din list (este folosit pentru parcurgerea
listei).
n liste, algoritmii de inserare i eliminare a unor noduri din structur se simplific foarte mult:

ED
Inserarea unui nod const n alocarea zonei de memorie n care se scrie nodul i
legarea lui la structur (stabilirea legturii cu predecesorul i cu succesorul lui).
Eliminarea unui nod const n ruperea nodului din structur, prin legarea predece-
sorului su cu succesorul lui, i eliberarea zonei de memorie pe care a ocupat-o.

2.6.2. Clasificarea listelor


Liste liniare P
I
Liste generale Liste restrictive

Nu exist restricii pentru operaiile de Exist restricii pentru operaiile de


inserare i tergere a elementelor din list inserare i tergere a elementelor din list
IC

(se pot face n orice poziie a listei). (se pot face numai la extremiti).
CT

Stiva Coada
Operaiile de introducere i extragere Operaia de introducere a elementelor se
a elementelor se pot face numai face pe la o extremitate, iar extragerea
printr-una dintre extremiti. elementelor prin cealalt extremitate.
DA

Lista simplu nlnuit Lista dublu nlnuit Lista circular


DI

Fiecare element pstreaz Fiecare element pstreaz Este o list nlnuit n


legtura cu un singur vecin legtura cu ambii vecini care elementul ultim se
(de obicei, succesorul). (succesorul i predecesorul). leag de elementul prim.
RA

Algoritmii ce se pot folosi pentru prelucrarea listelor:


iniializarea listei se creeaz lista vid;
crearea listei se adaug repetat elemente la list, pornind de la lista vid;
inserarea unui element n list la nceput, la sfrit, n interior;
TU

tergerea unui element din list la nceput, la sfrit, n interior;


parcurgerea listei se viziteaz elementele listei pentru a obine informaii;
cutarea n list a unui element care ndeplinete anumite condiii;
sortarea unei liste;
concatenarea a dou liste;
I
ED

divizarea n dou liste.


118 Implementarea structurilor de date

C
2.6.3. Agoritmi pentru prelucrarea listelor simplu nlnuite
Lista simplu nlnuit

I
prim

OG
ultim
info urm info urm info urm info NULL

n implementarea algoritmilor urmtori se consider c informaia propiu-zis este

AG
format numai dintr-un cmp n care se memoreaz un numr ntreg:
struct nod
{int info; //informaia propriu-zis
nod *urm;}; //informaia pentru legtur

ED
nod *prim, *ultim, *p; //pointeri pentru exploatarea listei
int x; //pentru valoarea ce se atribuie cmpului cu informaii
n lista vid: att nodul prim ct i nodul ultim nu exist, i adresa lor are valoarea NULL:
prim = ultim = NULL; Starea de list vid trebuie cunoscut atunci cnd se

P
elimin noduri din list, deoarece n lista vid nu mai exist noduri care s fie eliminate.
Aceast stare se testeaz prin condiia: prim == NULL. Pentru testarea unei liste dac
I
este vid se poate implementa funcia operand este_vida() care va furniza valoarea 1
(adevrat), dac lista este vid, i valoarea 0 (fals) dac lista nu este vid.
int este vida(nod *prim)
{return prim==NULL;}

2.6.3.1. Iniializarea listei


IC

Prin acest algoritm se creeaz lista vid. n acest caz, att nodul prim ct i nodul ultim
nu exist, i li se atribuie adresa NULL.
Implementarea algoritmului. Se folosete funcia procedural init() ai crei parametri
CT

prim i ultim de tip nod se transmit prin referin, deoarece sunt parametri de ieire.
void init(nod *&prim, nod *&ultim)
{prim = ultim=NULL;}
DA

2.6.3.2. Crearea listei


Deoarece n algoritmii de prelucrare trebuie s se cunoasc adresa primului nod, este impor-
tant adugarea primului nod la lista vid. Paii algoritmului de creare a unei liste sunt:
PAS1. Se adaug primul nod la list (nodul prim).
DI

PAS2. Ct timp mai exist informaie, execut: se adaug un nod la list.


2.6.3.3. Adugarea primului nod la list
n lista cu un singur nod, adresa de legtur a nodului prim are valoarea NULL i att
RA

nodul prim ct i nodul ultim au aceeai adres. Paii executai n acest algoritm sunt:
PAS1. Se cere alocarea de memorie pentru nodul prim.
PAS2. Se scrie informaia n nodul prim.
PAS3. Adresei de legtur a nodului prim i se atribuie valoarea NULL.
TU

PAS4. Nodului ultim i se atribuie adresa nodului prim.


Implementarea algoritmului. Se folosete funcia procedural adauga_nod() ai crei para-
metri prim i ultim de tip nod se transmit prin referin, deoarece sunt parametri de ieire.
I

void adaug nod (nod *&prim, nod *&ultim)


ED

{prim = new nod; prim->info=x; prim->urm=NULL; ultim=prim;}


Informatic 119

C
2.6.3.4. Adugarea unui nod la list
Pentru adugarea unui nod p la list, n funcie de cerinele problemei, se poate folosi

I
unul dintre algoritmii urmtori:

OG
1. adugarea n faa primului nod;
2. adugarea dup ultimul nod;
3. adugarea ntr-o poziie n interiorul listei.
Adugare n faa primului nod

AG
Paii executai n acest algoritm sunt:
PAS1. Se cere alocarea de memorie pentru nodul p.
PAS2. Se scrie informaia n nodul p.
PAS3. Nodul p se leag de nodul prim.

ED
PAS4. Nodul p inserat devine nodul prim.
Adugare n faa primului nod
prim ultim

P
info urm info urm I info urm info NULL

p info urm p devine nodul prim


Implementarea algoritmului. Se folosete funcia procedural adauga_prim() al crei para-


metru prim de tip nod se transmite prin referin, deoarece este parametru de intrare-iere.
IC

void adauga prim(nod *&prim)


{nod *p=new nod; p->info=x; p->urm=prim; prim=p;}
Adugare dup ultimul nod
CT

Paii executai n acest algoritm sunt:


PAS1. Se cere alocarea de memorie pentru nodul p.
PAS2. Se scrie informaia n nodul p.
PAS3. Nodul p este nod terminal (nu se leag de nimic adresa de legtur este NULL).
DA

PAS4. Nodul ultim se leag de nodul p adugat.


PAS5. Nodul p adugat devine nodul ultim.
Adugarea dup ultimul nod
DI

prim ultim
info urm info urm info urm info NULL
RA

p info NULL
p devine nodul ultim
TU

Implementarea algoritmului. Se folosete funcia procedural adauga_ultim() al crei para-


metru ultim de tip nod se transmite prin referin, deoarece este parametru de intrare-iere.
void adauga ultim(nod *&ultim)
{nod *p=new nod; p->info=x; p->urm=NULL; ultim->urm=p; ultim=p;}
I
ED
120 Implementarea structurilor de date

C
Adugarea n interiorul listei se poate face n dou moduri:
a. dup nodul cu adresa q;
b. nainte de nodul cu adresa q.

I
Adugarea n interiorul listei dup nodul cu adresa q

OG
Paii algoritmului sunt:
PAS1. Se cere alocarea de memorie pentru nodul p.
PAS2. Se scrie informaia n nodul p.
PAS3. Nodul p se leag de succesorul nodului q.

AG
PAS4. Nodul q se leag de nodul p adugat.
PAS5. Dac nodul q a fost ultimul nod, nodul p adugat devine nodul ultim.
Adugare dup nodul q

ED
prim q->urm ultim
info urm info urm info urm info NULL
q

P
p info urm
I
Implementarea algoritmului. Se folosete funcia procedural adauga_dupa() ai crei para-
metri sunt de tip nod: q (adresa nodului dup care se face adugarea), care se transmite prin
valoare, deoarece este parametru de intrare, i ultim (adresa ultimului nod), care se transmite

prin referin, deoarece este parametru de intrare-ieire.


void adauga dupa(nod *q, nod *&ultim)
IC

{nod *p=new nod;


p->info=x; p->urm=q->urm; q->urm=p; if (q==ultim) ultim=p;}
Adugarea n interiorul listei nainte de nodul de adres q
CT

Pentru a aduga nodul p naintea nodului q, trebuie s legm predecesorul nodului q de


nodul p. Dar, predecesorul unui nod nu este cunoscut. Adugarea unui nod n list nseam-
n, de fapt, inserarea n list a informaiei pe care o conine, ntre alte dou informaii, i
DA

anume: informaia din predecesorul nodului q trebuie s fie anterioar ei, iar informaia din

(1) Adugare naintea nodului q


prim q q->urm ultim
DI

v1 urm v2 urm v3 urm v4 NULL


RA

p v2 urm
(2)
prim q q->urm ultim
TU

v1 urm val urm v3 urm v4 NULL

p v2 urm
I
ED
Informatic 121

C
nodul q trebuie s o urmeze. Astfel, n list nu se va aduga nodul p nainte de nodul q, ci
dup el, interschimbnd apoi informaiile ntre cele dou noduri. Paii algoritmului sunt:
PAS1. Se cere alocarea de memorie pentru nodul p.

I
PAS2. Se copiaz informaia din nodul q n nodul p.

OG
PAS3. Se scrie n nodul q informaia care trebuie adugat la list.
PAS4. Nodul p se leag de succesorul nodului q.
PAS5. Nodul q se leag de nodul p adugat.
PAS6. Dac nodul q a fost ultimul nod, nodul p adugat devine nodul ultim.

AG
Implementarea algoritmului. Se folosete funcia procedural adauga_in_fata() ai crei
parametri sunt de tip nod: q (adresa nodului naintea cruia se face adugarea), care se trans-
mite prin valoare, deoarece este parametru de intrare, i ultim (adresa ultimului nod), care se
transmite prin referin, deoarece este parametru de intrare-ieire.

ED
void adauga in fata(nod *q, nod *&ultim)
{nod *p=new nod; p->info=q->info; q->info=x; p->urm=q->urm; q->urm=p;
if (q==ultim) ultim=p;}
2.6.3.5. Parcurgerea listei

P
Prin acest algoritm se viziteaz fiecare nod al listei, pornind de la primul nod, pn la
ultimul nod, n ordinea de nlnuire a nodurilor furnizat de adresa urm din nodul
I
vizitat. Lista se parcurge pentru a prelucra informaia stocat n noduri.
Implementarea algoritmului. Se folosete funcia procedural parcurge() al crei parametru
prim de tip nod se transmite prin valoare, deoarece este parametru de intrare.
void parcuge(nod *prim)

{for (nod *p=prim; p!=NULL; p=p->urm)


//se prelucreeaz p->info;}
IC

Att vectorul, ct i lista sunt structuri liniare, iar algoritmii de parcurgere sunt asemntori:
Vectorul Lista
CT

Variabila folosit i de tip int pentru indicele elementului p de tip pointer ctre tipul nod al listei
pentru parcurgere curent din vector pentru adresa elementului curent din list
Iniializarea i=0 indicele primului element din p=prim adresa primului nod din list
variabilei vector
DA

Trecerea la ele- i=i+1 se incrementeaz indicele p=p->urm pointerului i se atribuie


mentul urmtor adresa nodului urmtor
Condiia de i==n indicele i are prima valoare mai p==NULL adresa memorat n pointerul
terminare mare dect cea a ultimului element p este constanta NULL
DI

2.6.3.6. Cutarea unui nod n list


ntr-o list se poate cuta:
1. Nodul care ndeplinete o anumit condiie, pe care o notm cu conditie i care
RA

este exprimat printr-o expresie logic ce conine cel puin un cmp cu informaie din
nod; valoarea condiiei este dependent de informaia stocat n nod. Algoritmul
este: se parcurge lista ncepnd de la primul nod, n ordinea de nlnuire a nodurilor,
pn se gsete nodul care ndeplinete condiia sau pn s-a ajuns la sfritul listei.
TU

2. Nodul care se gsete ntr-o anumit poziie n list pe care o notm cu poz.
Algoritmul este: se parcurge lista ncepnd de la primul nod, n ordinea de nlnuire
a nodurilor, pn cnd s-au parcurs poz noduri sau pn s-a ajuns la sfritull listei
Implementarea algoritmului. Se folosete o funcie operand cu tipul pointer ctre tipul nod. n
I
ED

ambele variante:
122 Implementarea structurilor de date

C
parametrul funciei este prim de tip nod i se transmite prin valoare, deoarece este
parametru de intrare;
variabila local p de tip pointer ctre nod se folosete pentru parcurgerea listei este

I
iniializat cu adresa primului nod;

OG
adresa nodului gsit se memoreaz n pointerul p care va fi returnat de funcie.
Varianta 1
nod *caut(nod *prim)
{for (nod *p=prim; p!=NULL && !conditie; p=p->urm); return p;}

AG
Varianta 2 Variabila local nr de tip int se folosete pentru a numra poziiile parcurse
este iniializat cu valoarea 1.
nod *caut(nod *prim, int poz)
{nod *p=prim; int nr=1;

ED
for (;p!=NULL && nr<poz; p=p->urm,nr++); return p;}

2.6.3.7. Eliminarea unui nod din list


Dup eliminarea nodului din poziia p din list se va elibera zona de memorie ocupat de

P
nod. Eliminarea unui nod se face numai dac lista nu este vid. Pentru eliminarea unui
nod din list, n funcie de situaie, se poate folosi unul dintre algoritmii urmtori:
1. eliminarea primului nod;
I
2. eliminarea ultimului nod;
3. eliminarea unui nod din interiorul listei.
Eliminarea primului nod

Paii executai n acest algoritm sunt:


PAS1. Se salveaz adresa nodului prim n pointerul q.
IC

PAS2. Succesorul nodului prim devine nodul prim.


PAS3. Se cere eliberarea zonei de memorie de la adresa memorat n pointerul q.
CT

Eliminarea primului nod


prim ultim
info urm info urm info urm info NULL
DA

succesorul nodului prim devine nodul prim

Implementarea algoritmului. Se folosete funcia procedural elimina_prim() al crei para-


DI

metru prim de tip nod se transmite prin referin, deoarece este parametru de intrare-ieire.
void elimina prim(nod *&prim)
{nod q=prim; prim=prim->urm; delete q;}
RA

Eliminarea ultimului nod


Paii executai n acest algoritm sunt:
PAS1. Se salveaz adresa nodului ultim n pointerul q.
PAS2. Se caut predecesorul ultimului nod, prin parcurgerea listei ncepnd de la primul
TU

nod, pn la predecesorul nodului terminal (nodul care nu se leag de nimic


adresa de legtur are valoarea NULL).
PAS3. Predecesorul nodului ultim devine nod terminal (adresa de legtur este NULL).
PAS4. Predecesorul nodului ultim devine nodul ultim.
I
ED

PAS5. Se cere eliberarea zonei de memorie de la adresa memorat n pointerul q.


Informatic 123

C
Eliminarea ultimului nod
prim ultim

I
OG
info urm info urm info NULL info NULL

predecesorul nodului ultim devine nodul ultim

Implementarea algoritmului. Se folosete funcia procedural elimina_ultim() al crei para-

AG
metru ultim de tip nod se transmite prin referin, deoarece este parametru de intrare-ieire.
void elimina ultim(nod *prim,nod *&ultim)
{nod *p,*q=ultim;
for (p=prim; p->urm->urm!=NULL; p=p->urm);

ED
p->urm=NULL; ultim=p; delete q;}
Eliminarea unui nod din interiorul listei
Pentru a elimina nodul p aflat n interiorul listei, trebuie s legm predecesorul nodului p

P
de succesorul lui. Dar, predecesorul unui nod nu este cunoscut. Eliminarea unui nod din
list nseamn de fapt eliminarea din list a informaiei pe care o conine. Astfel, din list
nu se va elimina nodul p, ci succesorul su (care este cunoscut), dup ce informaia din
I
el a fost copiat n nodul p. Paii executai n acest algoritm sunt:
PAS1. Se salveaz adresa succesorului nodului p n pointerul q.
PAS2. Se copiaz n nodul p toat informaia din succesorul lui (informaia propriu-zis
i informaia de legtur).

PAS3. Se cere eliberarea zonei de memorie de la adresa memorat n pointerul q.


PAS4. Dac succesorul nodului p era nodul ultim, atunci nodul p devine nodul ultim.
IC

Implementarea algoritmului. Se folosete funcia procedural elimina() ai crei para-


metri sunt de tip nod: p (adresa nodului care se elimin), care se transmite prin valoare,
CT

deoarece este parametru de intrare, i ultim, care se transmite prin referin, deoarece
este parametru de intrare-ieire.
void elimina(nod *p,nod *&ultim)
{nod *q=p->urm;
DA

p->info=p->urm->info; p->urm=p->urm->urm; delete q;


if (p->urm==NULL) ultim=p;}

2.6.3.8. Eliberarea spaiului de memorie ocupat de list


DI

Dac n cadrul unei aplicaii care prelucreaz mai multe liste, nu mai este necesar una dintre
ele, se va elibera ntregul spaiu ocupat de list. Prin acest algoritm se viziteaz fiecare nod
al listei, pornind de la primul nod, pn la ultimul nod, n ordinea de nlnuire a nodurilor
furnizat de adresa urm din nodul vizitat, i se elibereaz zona de memorie ocupat de
RA

fiecare nod. Paii executai n acest algoritm sunt:


PAS1. Se iniializeaz pointerul p cu adresa primului nod din list prim (p prim).
PAS2. Ct timp nu s-a parcurs toat lista (pNULL) execut:
PAS3. Se salveaz adresa nodului p n pointerul q.
TU

PAS4. Se trece la succesorul nodului p (p p->urm).


PAS5. Se cere eliberarea zonei de memorie de la adresa memorat n pointerul q.
Se revine la Pasul 2.
PAS6. Primul nod nu mai are adres alocat (prim NULL).
I
ED
124 Implementarea structurilor de date

C
Implementarea algoritmului. Se folosete funcia procedural eliberare() al crei parame-
tru este prim de tip nod. Fiind parametru de intrare-ieire se transmite prin referin
void eliberare(nod *&prim)

I
{nod *p=prim,*q;

OG
while(p!=NULL) {q=p; p=p->urm; delete q;}
prim=NULL;}

2.6.3.9. Liste ordonate


n funcie de cerinele aplicaiei listele generale pot fi clasificate astfel:

AG
Liste generale

Ordonate Neordonate

ED
Nodurile listei sunt ordonate pe baza valorii Nu exist o ordine a nodurilor n list.
unui cmp cu informaie numit cmp cheie. Operaiile de adugare de noi noduri i de
Operaiile de adugare de noi noduri i de modificare a valorii cmpurilor cu infor-
modificare a valorii cmpului cheie trebuie s maii se fac fr restricii. Adugarea se

P
se fac astfel nct s se pstreze ordonarea. face de obicei pe la o extremitate a listei.

n cazul listelor ordonate, dac informaia din nodul listei este o dat elementar, cheia
I
de ordonare va fi data elementar. Dac informaia din nodul listei este o nregistrare,
cheia de ordonare va fi unul dintre cmpurile nregistrrii. Pentru prelucrarea listelor
ordonate putei folosi:
algoritmul de sortare prin inserie;

algoritmul de interclasare a dou liste ordonate.


IC

Algoritmul de sortare prin inserie


Acest algoritm se folosete pentru ntreinerea unei liste ordonate. Se pornete de la lista care
CT

conine un singur nod (considerat o list ordonat) i orice adugare a unui nod la list se face
ntr-o poziie prin care se pstreaz ordonarea n list. n implementarea algoritmului s-a folosit
o list pentru care cmpul cheie este de tip numeric ntreg, iar ordonarea este cresctoare dup
valoarea cmpului cheie. Deoarece n acest algoritm nu este necesar informaia despre
DA

adresa ultimului nod, din subprograme au fost eliminate prelucrrile care se refer la acesta.
Numerele care trebuie memorate n nodurile listei se citesc de la tastatur pn se citete
valoarea 0 (are semnificaia c nu mai exist informaie de adugat).
Varianta 1 Se pornete de la lista care conine primul nod cu informaie. Paii execu-
DI

tai n acest algoritm sunt:


PAS1. Se adaug primul nod cu informaie la list.
PAS2. Ct timp mai exist informaie de adugat execut
PAS3. Se caut nodul naintea cruia trebuie adugat noul nod.
RA

PAS4. Dac s-a ajuns la sfritul listei, atunci se adaug noul nod ca ultimul nod din
list; altfel, se adaug noul nod n faa nodului gsit. Se revine la Pasul 2.
Implementarea algoritmului.
TU

#include<iostream.h>
struct nod {int info;
nod *urm;};
int n;
void adauga nod(nod *&prim)
I
ED

{prim=new nod; prim->info=n; prim->urm=NULL;}


Informatic 125

C
void adauga_in_fata(nod *q)
{nod *p=new nod; p->urm=q->urm; p->info=q->info; q->info=n; q->urm=p;}
void adauga_ultim(nod *q)

I
{nod *p=new nod; p->info=n; q->urm=p; p->urm=NULL;}

OG
nod * cauta(nod *prim)
{nod *q=prim;
while(q->info<n && q->urm!=NULL) q=q->urm;
return q;}
void afisare(nod *prim)

AG
{for (nod *p=prim; p!=NULL; p=p->urm) cout<<p->info<<" ";}
void main()
{nod *prim,*q;
cout<<"numar "; cin>>n;
adauga_nod(prim); //Se adaug primul nod

ED
cout<<"numar "; cin>>n;
while(n!=0) //Ct timp mai exist informaie de adugat
{q=cauta(prim);
//Se caut nodul q naintea cruia trebuie adugat nodul p

P
if (q->info<n) //Dac s-a ajuns la sfritul listei
adauga_ultim(q); //nodul p se adaug ca ultim nod
else adauga_in_fata(q); //nodul p se adaug n faa nodului q
I
cout<<"numar "; cin>>n;}
afisare(prim);} //Se afieaz informaiile din list
Varianta 2 Se pornete de la lista care conine un nod santinel (un nod care

marcheaz sfritul listei). Acest nod conine n cmpul cheie o informaie care are o
valoare care face ca el s fie ntotdeauna ultimul nod din list (de exemplu, n cazul unei
IC

liste ordonate cresctor, n care cmpul folosit pentru ordonare este de tip int, se adaug
un nod care are n acest cmp cea mai mare valoare pentru tipul int MAXINT). Cnd se
va afia informaia din list, ultimul nod din list nu se mai afieaz. Paii executai n
CT

acest algoritm sunt:


PAS1. Se adaug nodul santinel la list.
PAS2. Ct timp exist informaie de adugat execut
PAS3. Dac informaia care se adaug trebuie s fie la nceputul listei, atunci se
DA

adaug noul nod ca primul nod din list i se revine la Pasul 2; altfel, se
trece la pasul urmtor.
PAS4. Se caut nodul naintea cruia trebuie adugat noul nod.
PAS5. Se adaug noul nod n faa nodului gsit. Se revine la Pasul 2.
DI

Implementarea algoritmului.
#include<iostream.h>
#include<values.h>
RA

struct nod {int info;


nod *urm;};
int n;
void adauga_santinela(nod *&prim)
{prim=new nod; prim->info=MAXINT; prim->urm=NULL;}
TU

void adauga_prim(nod *&prim)


{nod *p=new nod; p->info=n; p->urm=prim; prim=p;}
void adauga_in_fata(nod *q)
{nod *p=new nod;
I

p->urm=q->urm; p->info=q->info; q->info=n; q->urm=p;}


ED
126 Implementarea structurilor de date

C
nod *cauta(nod *prim)
{ nod *p=prim;
for (;p->info<n;p=p->urm); return p;}

I
void afisare(nod *prim) //Nu se afieaz informaia din ultimul nod

OG
{for (nod *p=prim; p->urm!=NULL; p=p->urm) cout<<p->info<<" ";}
void main()
{ nod *prim,*q;
adauga_santinela(prim); //Se adaug nodul santinel
cout<<"numar "; cin>>n;

AG
while(n!=0) //Ct timp mai exist informaie de adugat
{if (n<prim->info) /*Dac informaia trebuie s fie la
nceputul listei */
adauga_prim(prim); //nodul p se adaug ca prim nod
else {q=cauta(prim);

ED
//Se caut nodul q naintea cruia trebuie adugat nodul p
adauga_in_fata(q);} //nodul p se adaug n faa nodului q
cout<<"numar "; cin>>n;}
afisare(prim);}

Algoritmul de interclasare a dou liste ordonate


P
Acest algoritm folosete acelai principiu ca i algoritmul de interclasare a doi vectori
I
ordonai. Cele dou liste sunt ordonate dup acelai cmp cheie i criteriu de ordonare i
se obine o a treia list care conine informaia din primele dou liste ordonat dup
acelai criteriu, folosind acelai cmp cheie. Paii executai n acest algoritm sunt:

PAS1. Se creeaz Lista 1 i Lista 2 ordonate dup acelai criteriu i dup acelai cmp cheie.
PAS2. Se adaug primul nod la Lista 3 astfel: dac n conformitate cu criteriul de ordonare
IC

folosit trebuie adugat informaia din primul nod al Listei 1, atunci se adaug
informaia din nodul prim al Listei 1 i n Lista 1 se trece la succesorul nodului
prim, iar n Lista 2 la nodul prim; altfel, se adaug informaia din nodul prim al
CT

Listei 2 i n Lista 2 se trece la succesorul nodului prim, iar n Lista 1 la nodul prim.
PAS3. Ct timp nu s-a ajuns la sfritul Listei 1 sau al Listei 2, execut:
PAS4. Se adaug la Lista 3 un nod dup ultimul nod astfel: dac n conformitate cu
criteriul de ordonare folosit trebuie adugat informaia din nodul curent al Listei
DA

1, atunci se adaug informaia din acest nod i n Lista 1 se trece la succesorul


nodului curent; altfel, se adaug informaia din nodul curent al Listei 2 i n Lista
2 se trece la succesorul nodului curent. Se revine la Pasul 3.
PAS5. Dac s-a ajuns la sfritul Listei 1, atunci la Lista 3 se adaug dup ultimul nod
DI

nodurile rmase n Lista 2; altfel, la Lista 3 se adaug dup ultimul nod nodurile
rmase n Lista 1.
Implementarea algoritmului. n implementarea algoritmului s-au folosit liste pentru care
RA

cmpul cheie este de tip numeric ntreg, iar ordonarea este cresctoare dup valoarea
cmpului cheie. Numerele care trebuie memorate n nodurile listelor se citesc de la tastatur n
variabila n pn se citete valoarea 0 (are semnificaia c nu mai exist informaie de adugat).
Din subprogramele n care nu este necesar informaia despre adresa ultimului nod au fost
TU

eliminate prelucrrile care se refer la acesta. Cele trei liste se identific prin adresa primului
nod (prim1, prim2 i respectiv prim3). Deoarece n acest algoritm nu este necesar
informaia despre adresa ultimului nod, din subprograme au fost eliminate prelucrrile care se
refer la acesta. Pentru parcurgerea celor dou liste se folosesc pointerii q i respectiv r, iar
I

pentru lista care se creeaz prin interclasare pointerul p.


ED
Informatic 127

C
#include<iostream.h>
struct nod {int info;
nod *urm;};

I
int n;

OG
void adauga_nod(nod *&prim)
{prim=new nod; prim->info=n; prim->urm=NULL;}
void adauga_in_fata(nod *q)
{nod *p=new nod;
p->urm=q->urm; p->info=q->info; q->info=n; q->urm=p;}

AG
void adauga_ultim(nod *q)
{nod *p=new nod; p->info=n; q->urm=p; p->urm=NULL;}
nod *cauta(nod *prim)
{nod *p=prim;
while(p->info<n && p->urm!=NULL) p=p->urm;

ED
return p;}
void creare(nod *&prim) //Se creeaz o list ordonat
{nod *q;
cout<<"numar "; cin>>n; adauga_nod(prim);

P
cout<<"numar "; cin>>n;
while(n!=0)
{q=cauta(prim);
I
if (q->info<n) adauga_ultim(q); else adauga_in_fata(q);
cout<<"numar "; cin>>n;}}
void afisare(nod *prim)
{nod *p=prim;

while(p!=NULL) {cout<<p->info<<" "; p=p->urm;}}


void main()
IC

{nod *prim1,*prim2,*prim3,*q,*r,*p;
creare(prim1); creare(prim2);
if (prim2->info>prim1->info)
CT

{n=prim1->info; q=prim1->urm; r=prim2;}


else {n=prim2->info; r=prim2->urm; q=prim1;}
adauga_nod(prim3); p=prim3;
while(q!=0 && r!=0)
DA

{if (r->info>q->info) {n=q->info; q=q->urm;}


else {n=r->info; r=r->urm;}
adauga_ultim(p); p=p->urm;}
if (q!=0)
while (q!=0) {n=q->info; adauga_ultim(p); p=p->urm; q=q->urm;}
DI

else
while (r!=0) {n=r->info; adauga ultim(p); p=p->urm; r=r->urm;}
afisare(prim3);} //Se afieaz informaiile din lista interclasat
RA

2.6.3.10. Prelucrarea listelor simplu nlnuite


Rezolvarea problemelor n care organizai datele sub form de liste presupune folosirea
algoritmilor prezentai, astfel:
TU

1. Se creeaz lista prin folosirea urmtorilor algoritmi:


Se adaug primul nod la lista vid (algoritmul pentru adugarea la list a primu-
lui nod).
Se adaug cte un nod la list. Poziia n care se adaug nodul depinde de cerin-
I

ele problemei. Dac lista nu este ordonat, adugarea se poate face la sfritul
ED
128 Implementarea structurilor de date

C
sau la nceputul listei (algoritmul pentru adugare la nceputul sau la sfritul
listei). Dac lista este ordonat, se parcurge mai nti lista pentru a gsi poziia de
inserare (algoritmul pentru cutarea unui nod n list) dup care se insereaz

I
noul nod n poziia gsit (algoritmul pentru adugare n interiorul listei).

OG
2. Se ntreine lista prin folosirea urmtorilor algoritmi:
Se adaug noi noduri la list. Ca i la crearea listei, n funcie de cerinele proble-
mei se va folosi unul dintre algoritmii de adugare.
Se elimin noduri din list. Mai nti se parcurge lista pentru a gsi nodul care se

AG
elimin (algoritmul pentru cutarea unui nod n list) dup care se elimin
nodul din poziia gsit folosind unul dintre algoritmii pentru eliminare n
funcie de poziia n care a fost gsit nodul.
Se modific informaia dintr-un nod al listei. Mai nti se parcurge lista pentru a gsi

ED
nodul n care se va modifica informaia (algoritmul pentru cutarea unui nod n
list). Dac lista nu este ordonat sau dac informaia care se modific nu face
parte dintr-un cmp cheie dintr-o list ordonat, se modific valoarea cmpului
respectiv. Dac lista este ordonat i, prin modificarea valorii cmpului, se poate

P
distruge aceast ordonare, se modific valoarea cmpului, se salveaz informaia
din nodul listei ntr-o variabil intermediar, se elimin din vechea poziie (algoritmul
pentru eliminarea unui nod din list), se parcurge lista pentru a gsi noua poziie
I
(algoritmul pentru cutarea unui nod n list) i se insereaz nodul n poziia
gsit (algoritmul pentru adugarea unui nod la list).
3. Se obin informaii din list. Se parcurge lista (algoritmul de parcurgere a listei)

i se viziteaz fiecare nod al listei pentru a extrage din el informaiile necesare.


IC

Scop: exemplificarea modului n care, pentru rezolvarea problemei, folosii algoritmii de


prelucrare a listelor simplu nlnuite i implementarea lor cu ajutorul subprogramelor.
CT

Enunul problemei 1. Se citete dintr-un fiier text un ir de numere separate prin spaiu
cu care se creeaz o list simplu nlnuit n ordinea n care sunt citite numerele din fiier.
S se verifice dac lista conine numai numere distincte i apoi s se adauge dup fiecare
DA

numr impar din list valoarea 100 i s se afieze numerele din list. Pentru testarea
programului se vor folosi dou seturi de numere: {2, 5, 10, 3, 8} i {2, 5, 10, 5, 8, 7}.
Nodurile listei nu sunt ordonate conform unui criteriu. Numerele se vor citi din fiier i se vor
scrie n list prin adugare dup ultimul nod. Problema se descompune n urmtoarele
DI

subprobleme, iar algoritmul de rezolvare a unei subprobleme este implementat cu ajutorul


unui subprogram:
P1 Se citete primul numr din fiier i se adaug primul nod la list (nodul prim)
RA

subprogramul adauga nod().


P2 Ct timp mai exist numere n fiier execut: se citete un numr din fiier i se
adaug un nod cu numrul respectiv dup ultimul nod din list subprogramul
adauga ultim().
TU

P3 Se verific dac numerele din list sunt distincte, astfel: se parcurge lista de la primul
nod pn la penultimul nod i se verific dac numrul din nodul curent mai exist n
nodurile care urmeaz dup el pn la sfritul listei subprogramul distincte().
P4 Se parcurge lista de la primul nod pn la sfritul ei i dac numrul din nod este impar
I

se adaug dup el un nod care conine valoarea 100 subprogramul prelucrare().


ED
Informatic 129

C
P5 Se parcurge lista de la primul nod pn la sfritul ei i se afieaz informaia din
fiecare nod subprogramul afisare().
#include<fstream.h>

I
struct nod {int info;

OG
nod *urm;};
fstream f("lista1.txt",ios::in);
int n;
void adauga nod(nod *&prim, nod *&ultim)
{prim=new nod; prim->info=n; prim->urm=NULL; ultim=prim;}

AG
void adauga ultim(nod *&ultim)
{nod *p=new nod; p->info=n; p->urm=NULL; ultim->urm=p; ultim=p;}
void adauga_dupa(nod *&q, nod *&ultim)
{nod *p=new nod; p->info=100; p->urm=q->urm; q->urm=p;

ED
if (q==ultim) ultim=p;}
int distincte(nod *prim)
{for (nod *p=prim; p->urm!=NULL; p=p->urm)
for (nod *q=p->urm; q!=NULL; q=q->urm)
if (p->info==q->info) return 0;

P
return 1;}
void prelucrare(nod *prim, nod *&ultim)
{for (nod *p =prim; p!=NULL; p=p->urm)
I
if (p->info%2==1) adauga dupa (p,ultim);}
void afisare(nod *prim)
{for (nod *p=prim; p!=NULL; p=p->urm) cout<<p->info<<" "; cout<<endl;}

void main()
{nod *prim, *ultim; f>>n adauga_nod(prim,ultim);
IC

while (f>>n) adauga_ultim(ultim); f.close();


if (distincte(prim)) cout<<"Elementele sunt distincte"<<endl;
else cout<<"elementele nu sunt distincte"<<endl;
prelucrare(prim,ultim); afisare(prim);}
CT

Enunul problemei 2. Se citete dintr-un fiier text un numr cu maxim 20 de cifre. S se


verifice dac numrul este palindrom. Pentru testarea programului se vor folosi dou
numere: 1234321 i 12345.
DA

Se vor crea dou liste: una cu cifrele numrului citite din fiier, prin adugare dup ultimul
nod, iar a doua, cu cifrele memorate n nodurile primei liste prin adugare n faa primului nod
i se vor compara cele dou liste. Din fiier se va citi fiecare cifr a numrului ntr-o variabil
de tip char i se va obine cifra scznd din codul ASCII al caracterului citit codul ASCII al
DI

cifrei 0. Cele dou liste se identific prin adresa primului nod (prim1 i respectiv prim2) i prin
adresa ultimului nod (ultim1 i respectiv ultim2). Problema se descompune n urmtoarele
subprobleme, iar algoritmul de rezolvare a unei subprobleme este implementat cu ajutorul
RA

unui subprogram
P1 Se citete primul numr din fiier i se adaug primul nod la Lista 1 (nodul prim1)
subprogramul adauga nod().
P2 Ct timp mai exist caractere n fiier, execut: se citete un caracter din fiier, se
TU

convertete n cifr i se adaug un nod cu cifra respectiv dup ultimul nod din Lista
1 subprogramul adauga ultim().
P3 Se adaug primul nod la Lista 2 (nodul prim2) care va conine informaia din primul
nod al Listei 1 (prim1) subprogramul adauga nod().
I
ED
130 Implementarea structurilor de date

C
P4 Se parcurge Lista 1 de la succesorul primului nod pn la sfritul ei i se adaug un nod
cu cifra respectiv naintea primului nod din Lista 2 subprogramul adauga prim().
P5 Se parcurg simultan ambele liste de la primul nod pn la sfrit i se verific dac

I
sunt egale cifrele memorate n nodul curent din cele dou liste subprogramul

OG
palindrom().
#include<fstream.h>
struct nod {int info;
nod *urm;};

AG
fstream f("lista2.txt",ios::in);
int n;
void adauga nod(nod *&prim, nod *&ultim)
{prim=new nod; prim->info=n; prim->urm=NULL; ultim=prim;}
void adauga ultim(nod *&ultim)

ED
{nod *p=new nod; p->info=n; p->urm=NULL; ultim->urm=p; ultim=p;}
void adauga_prim(nod *&prim)
{nod *p=new nod; p->info=n; p->urm=prim; prim=p;}
int palindrom(nod *prim1, nod *prim2)

P
{nod *p,*q;
for (p=prim1,q=prim2; p->urm!=NULL; p=p->urm,q=q->urm)
if (p->info!=q->info) return 0;
I
return 1;}
void main()
{char c; nod *prim1,*ultim1,*prim2,*ultim2,*p;
f>>c; n=c-'0'; adauga_nod(prim1,ultim1);

while (f>>c) {n=c-'0'; adauga_ultim(ultim1);} f.close();


n=prim1->info; adauga_nod(prim2,ultim2);
IC

for (p=prim1->urm; p!=NULL; p=p->urm)


{n=p->info; adauga_prim(prim2);}
if (palindrom(prim1,prim2)) cout<<"Este palindrom";
CT

else cout<<"Nu este palindrom";}


Enunul problemei 3. Se citete dintr-un fiier text un ir de numere separate prin spaiu
cu care se creeaz o list simplu nlnuit n ordinea n care sunt citite numerele din fiier.
Se mai citete de la tastatur un numr x. S se caute i s se tearg din list nodul care
DA

conine acest numr. Pentru testarea programului se va folosi irul de numere: {2, 5, 10, 3,
8}, iar pentru x patru valori: 2, 5, 8 i 7.
Nodurile listei nu sunt ordonate conform unui criteriu. Numerele se vor citi din fiier i se vor
scrie n list prin adugare dup ultimul nod. Problema se descompune n urmtoarele
DI

subprobleme, iar algoritmii pentru rezolvarea subproblemelor sunt implementai cu ajutorul


subprogramelor:
P1 Se citete valoarea pentru x de la tastatur.
RA

P2 Se citete primul numr din fiier i se adaug primul nod la list (nodul prim)
subprogramul adauga nod().
P3.Ct timp mai exist numere n fiier execut: se citete un numr din fiier i se
adaug un nod cu numrul respectiv dup ultimul nod din list subprogramul
TU

adauga ultim().
P4 Dac primul nod din list conine numrul x, atunci se elimin primul nod (subprogra-
mul elimina prim()); altfel, se caut predecesorul nodului care conine numrul x
(subprogramul cauta()) i dac se gsete acest nod, atunci se terge nodul care
I

urmeaz dup el (subprogramul elimina urm()).


ED
Informatic 131

C
P5 Se parcurge lista de la primul nod pn la sfritul ei i se afieaz informaia din
fiecare nod subprogramul afiare().
#include<fstream.h>

I
struct nod {int info;

OG
nod *urm;};
fstream f("lista3.txt",ios::in);
int n,x;
void adauga nod(nod *&prim, nod *&ultim)
{prim=new nod; ultim=prim; prim->info=n; prim->urm=NULL;}

AG
void adauga_ultim(nod *&ultim)
{nod *p=new nod; p->info=n; p->urm=NULL; ultim->urm=p; ultim=p;}
nod * cauta(nod *p)
{while(p->urm!=NULL && p->urm->info!=x) p=p->urm;

ED
return p;}
void elimina_prim(nod *&prim)
{nod *q=prim; prim=prim->urm; delete q;}
void elimina_urm(nod *p)
{nod *q=p->urm; p->urm=p->urm->urm; delete q;}

P
void afisare(nod *prim)
{for (nod *p=prim;p!=NULL;p=p->urm) cout<<p->info<<" ";
cout<<endl;}
I
void main()
{nod *prim,*ultim,*p; cout<<"x= "; cin>>x;
f>>n; adauga_nod(prim,ultim);

while(f>>n) adauga_ultim(ultim); f.close();


if (prim->info==x) elimina_prim(prim);
IC

else {p=cauta(prim);
if (p->urm!=NULL) elimina_urm(p);}
afisare(prim);}
CT

Enunul problemei 4. Se citete dintr-un fiier text un ir de numere separate prin spaiu
cu care se creeaz o list simplu nlnuit n ordinea n care sunt citite numerele din fiier.
S se elimine din list valorile care se repet, n afar de prima lor apariie. Pentru testarea
programului se va folosi irul de numere: {2, 4, 9, 9, 9, 6, 2, 9, 9}.
DA

Nodurile listei nu sunt ordonate conform unui criteriu. Numerele se vor citi din fiier i se vor
scrie n list prin adugare dup ultimul nod. Problema se descompune n urmtoarele
subprobleme, iar algoritmii pentru rezolvarea subproblemelor sunt implementai cu ajutorul
subprogramelor:
DI

P1 Se citete primul numr din fiier i se adaug primul nod la list (nodul prim)
subprogramul adauga nod().
P2 Ct timp mai exist numere n fiier execut: se citete un numr din fiier i se
RA

adaug un nod cu numrul respectiv dup ultimul nod din list subprogramul
adauga ultim().
P3 Se elimin din list valorile care se repet, astfel (subprogramul prelucrare()):
Pentru un pointer p care indic fiecare nod din list, ncepnd cu primul nod pn la
TU

penultimul nod, execut:


Se iniializeaz pointerul q cu adresa nodul curent (indicat de pointerul p).
Ct timp pointerul q nu indic ultimul nod, execut: dac nodul indicat de
pointerul p conine acelai numr cu succesorul nodului indicat de pointerul q,
I
ED
132 Implementarea structurilor de date

C
atunci se elimin succesorul nodului q ( subprogramul elimina urm());
altfel, pointerul q indic succesorul nodului.
P4 Se parcurge lista de la primul nod pn la sfritul ei i se afieaz informaia din

I
fiecare nod (subprogramul afisare()).

OG
#include<fstream.h>
struct nod {int info;
nod *urm;};
fstream f("lista4.txt",ios::in);

AG
int n;
void adauga nod(nod *&prim, nod *&ultim)
{prim=new nod; prim->info=x; prim->urm=NULL; ultim=prim;}
void adauga ultim(nod *&ultim)
{nod *p=new nod; p->info=x; p->urm=NULL; ultim->urm=p; ultim=p;}

ED
void elimina_urm(nod *p)
{nod *q=p->urm; p->urm=p->urm->urm; delete q;}
void prelucrare(nod *prim)
{nod *p,*q;

P
for (p=prim;p->urm!=NULL;p=p->urm)
{n=p->info; q=p;
while (q!=NULL)
I
{if (q->urm!=NULL && q->urm->info==n) elimina_urm(q);
else q=q->urm;}}}
void afisare(nod *prim)
{for (nod *p=prim; p!=NULL;p=p->urm) cout<<p->info<<" ";

cout<<endl;}
void main() {nod *prim,*ultim; f>>n; adauga_nod(prim,ultim);
IC

while (f>>n) adauga_ultim(ultim); f.close();


prelucrare(prim); afisare(prim);}
Enunul problemei 5. Adunarea a dou polinoame. Se citesc dintr-un fiier text de pe
CT

prima linie un numr n1, care reprezint numrul de coeficieni nenuli ai unui polinom, apoi
de pe urmtoarele n1 linii coeficienii nenuli i gradul, de pe linia urmtoare un numr n2
care reprezint numrul de coeficieni nenuli ai celui de al doilea polinom i apoi de pe
urmtoarele linii coeficienii nenuli i gradul. S se creeze cu aceste informaii dou liste
DA

simplu nlnuite i s se adune cele dou polinoame. Coeficientul i gradul fiecrui termen
din polinomul sum se vor salva ntr-un fiier. Pentru testarea programului se vor folosi
4 2 3 2
polinoamele -10x +5x -3x i 3x +7x +x+2.
DI

Se vor crea dou liste n care se vor memora cele dou polinoame. Informaia util va fi
memorat ntr-o nregistrare cu dou cmpuri: un cmp pentru coeficient i un cmp pentru
grad. Ambele liste se creeaz prin citirea datelor din fiier i adugare dup ultimul nod. n a
treia list se va memora polinomul obinut prin adunarea celor dou polinoame. Cele trei liste
RA

se identific prin adresa primului nod (prim1, prim2 i respectiv prim3) i prin adresa
ultimului nod (ultim1, ultim2 i respectiv ultim3). Problema de creare a listei sum a
polinoamelor se descompune n urmtoarele subprobleme, iar algoritmii pentru rezolvarea
subproblemelor sunt implementai cu ajutorul subprogramelor:
TU

P1 Se citesc din fiier n1 i coeficientul i gradul primului termen din primul polinom. Se
adaug primul nod la lista L1 (nodul prim1) subprogramul adauga_nod().
P2 Pentru urmtoarele n1-1 perechi de numere din fiier, execut: se citesc din fiier
coeficientul i gradul unui termen al primului polinom i se adaug un nod cu
I
ED

informaia respectiv dup ultimul nod din lista L1 subprogramul adauga_ultim().


Informatic 133

C
P3 Se citesc din fiier n2 i coeficientul i gradul primului termen din al doilea polinom.
Se adaug primul nod la lista L2 (nodul prim2) subprogramul adauga_nod().
P4 Pentru urmtoarele n2-1 perechi de numere din fiier, execut: se citesc din fiier

I
coeficientul i gradul unui termen al celui de al doilea polinom i se adaug un nod cu

OG
informaia respectiv dup ultimul nod din lista L2 subprogramul adauga_ultim().
P5 Se adaug primul nod (prim3) la lista L3 cu urmtoarea informaie: dac gradul din
primul nod din lista L1 este egal cu gradul primului nod din lista L2, atunci gradul este
egal cu gradul nodului din Lista 1, iar coeficientul este egal cu suma coeficienilor din

AG
nodurile celor dou liste i n ambele liste se trece la nodul urmtor; altfel, dac gradul
din primul nod din lista L1 este mai mare dect gradul primului nod din lista L2, atunci
gradul este egal cu gradul nodului din Lista 1, iar coeficientul este egal cu coeficientul
nodului din Lista 1 i n Lista 1 se trece la urmtorul nod; altfel, gradul este egal cu
gradul nodului din Lista 2, iar coeficientul este egal cu coeficientul nodului din Lista 2 i

ED
n Lista 2 se trece la urmtorul nod subprogramul adauga nod().
P6 Ct timp nu s-a ajuns la sfritul Listei 1 i al Listei 2, execut: se adaug un nod la
lista L3 dup ultimul nod, cu urmtoarea informaie: dac gradul din nodul curent din
lista L1 este egal cu gradul nodului curent din lista L2, atunci gradul este egal cu

P
gradul nodului din Lista 1, iar coeficientul este egal cu suma coeficienilor din nodurile
celor dou liste i n ambele liste se trece la nodul urmtor; altfel, dac gradul din
I
nodul curent din lista L1 este mai mare dect gradul din nodul curent din lista L2,
atunci gradul este egal cu gradul nodului din Lista 1, iar coeficientul este egal cu coefi-
cientul nodului din Lista 1 i n Lista 1 se trece la urmtorul nod; altfel, gradul este egal
cu gradul nodului din Lista 2, iar coeficientul este egal cu coeficientul nodului din Lista 2

i n Lista 2 se trece la urmtorul nod subprogramul adauga_ultim().


IC

#include<fstream.h>
fstream f1("lista5.txt",ios::in),f2("polinom.txt",ios::out);
struct nod {int c,g;
nod *urm;};
CT

int c,g,n;
void adauga_nod(nod *&prim,nod *&ultim)
{prim=new nod; ultim=prim; prim->urm=NULL; prim->c=c; prim->g=g;}
void adauga_ultim(nod *&ultim)
DA

{nod *p=new nod; p->urm=NULL; ultim->urm=p; ultim=p; p->c=c; p->g=g;}


void creare(nod *&prim,nod *&ultim)
{f1>>c>>g; adauga_nod(prim,ultim);
for (int i=2;i<=n;i++) {f1>>c>>g; adauga_ultim(ultim);}}
DI

void adunare(nod *prim1, nod *prim2, nod *&prim3, nod *&ultim3)


{nod *p=prim1,*q=prim2;
if (p->g==q->g) {g=p->g; c=p->c+q->c; p=p->urm; q=q->urm;}
else if (p->g>q->g) {g=p->g; c=p->c; p=p->urm;}
RA

else {g=q->g; c=q->c; q=q->urm;}


adauga_nod(prim3,ultim3);
while(q!=NULL && p!=NULL)
{if (p->g==q->g) {g=p->g; c=p->c+q->c; p=p->urm; q=q->urm;}
else if (p->g>q->g) {g=p->g; c=p->c; p=p->urm;}
TU

else {g=q->g; c=q->c; q=q->urm;}


adauga_ultim(ultim3);}
if (p!=NULL)
while(p!=NULL) {g=p->g; c=p->c; adauga_ultim(ultim3);}
I

else
ED
134 Implementarea structurilor de date

C
while(q!=NULL) {g=q->g; c=q->c;adauga_ultim(ultim3);}}
void afisare(nod *prim)
{for (nod *p=prim;p!=NULL;p=p->urm) cout<<p->c<<" "<<p->g<<endl;

I
cout<<endl;}

OG
void salvare(nod *prim)
{for (nod *p=prim;p!=NULL;p=p->urm) f2<<p->c<<" "<<p->g<<endl;}
void main()
{nod *prim1,*ultim1,*prim2,*ultim2,*prim3,*ultim3;
int n1,n2;

AG
f1>>n1; n=n1; creare(prim1,ultim1); afisare(prim1);
f1>>n2; n=n2; creare(prim2,ultim2); afisare(prim2);
adunare(prim1,prim2,prim3,ultim3); afisare(prim3); salvare(prim3);
f1.close(); f2.close();}

ED
Enunul problemei 6. Reuniunea i intersecia a dou mulimi. Se citesc dintr-un fiier
text de pe prima linie un numr n1, care reprezint numrul de elemente ale primei mulimi,
apoi de pe urmtoarea linie elementele mulimii, de pe linia urmtoare un numr n2
numrul de elemente ale celei de a doua mulimi, apoi de pe urmtoarea linie elementele

P
mulimii. S se determine reuniunea i intersecia celor dou mulimi. Pentru testarea
programului se vor folosi dou seturi de date de intrare: mulimile A={1,2,3,4,5} i
B={4,5,6,7} i mulimile A={1,2,3} i B={4,5}.
I
Se vor crea dou liste n care se vor memora cele dou mulimi. Ambele liste se creeaz prin
citirea datelor din fiier i adugare dup ultimul nod. n a treia list se va memora reuniunea
celor dou mulimi, iar n a patra list intersecia. Cele patru liste se identific prin adresa

primului nod (prim1, prim2, prim3 i respectiv prim4) i prin adresa ultimului nod (ultim1,
ultim2, ultim3 i respectiv ultim4).
IC

Pentru determinarea reuniunii se vor executa urmtorii pai:


Pas1. Se adaug primul nod la Lista 3 (nodul prim3) care conine numrul din primul nod
al Listei 1 (prim1).
CT

Pas2. Se parcurge Lista 1 de la succesorul primului nod pn la sfritul ei i se adaug


un nod cu numrul respectiv dup ultimul nod din Lista 3.
Pas3. Pentru fiecare nod din Lista 2, execut: se parcurge Lista 1 i dac numrul din
nodul curent din Lista 2 nu se gsete n Lista 1, atunci se adaug un nod cu
DA

numrul respectiv dup ultimul nod din Lista 3.


Pentru determinarea interseciei se vor executa urmtorii pai:
Pas1. Se iniializeaz Lista 4 ca list vid (prim4=NULL i ultim4=NULL).
DI

Pas2. Pentru fiecare nod din Lista 1, execut: se parcurge Lista 2 i dac numrul din
nodul curent din Lista 2 se gsete n Lista 1, atunci se adaug un nod cu
numrul respectiv ca prim nod n Lista 4 (nodul prim4).
Pas3. Dac s-a adugat primul nod la Lista 4, atunci pentru un nod din Lista 1 de la
RA

succesorul nodului curent pn la ultimul nod, execut: se parcurge Lista 2 i


dac numrul din nodul curent din Lista 1 se gsete n Lista 2, atunci se adaug
n Lista 4, un nod cu numrul respectiv, dup ultimul nod.
#include<fstream.h>
TU

struct nod {int info;


nod *urm;};
fstream f("lista6.txt",ios::in);
int x;
I

void adauga_nod(nod *&prim,nod *&ultim)


ED
Informatic 135

C
{prim=new nod; prim->info=x; prim->urm=NULL; ultim=prim;}
void adauga_ultim(nod *&ultim)
{nod *p=new nod; p->info=x; p->urm=NULL; ultim->urm=p; ultim=p;}

I
void creare(nod *&prim,nod *&ultim)

OG
{int n; f>>n>>x; adauga_nod(prim,ultim);
for (int i=2;i<=n;i++) {f>>x; adauga_ultim(ultim);}}
void reuniune(nod *prim1, nod *prim2, nod *&prim3, nod *&ultim3)
{nod *p,*q; int gasit;
x=prim1->info; adauga_nod(prim3,ultim3);

AG
for(p=prim1->urm;p!=NULL;p=p->urm) {x=p->info; adauga_ultim(ultim3);}
for (p=prim2;p!=NULL;p=p->urm)
{for(q=prim1,gasit=0; q!=NULL && !gasit; q=q->urm)
if(p->info==q->info) gasit=1;
if(!gasit) {x=p->info; adauga_ultim(ultim3);}}}

ED
void intersectie(nod *prim1, nod *prim2, nod *&prim4, nod *&ultim4)
{nod *p,*q; int gasit; prim4=NULL; ultim4=NULL;
for(gasit=0,p=prim1;p!=NULL && !gasit; p=p->urm)
for (q=prim2; q!=NULL && !gasit; q=q->urm)

P
if (p->info==q->info) {gasit=1; x=p->info;}
if (gasit)
{adauga_nod(prim4,ultim4);
I
for(;p!=0;p=p->urm)
{for (gasit=0,q=prim2; q!=NULL && !gasit; q=q->urm)
if(p->info==q->info) gasit=1;
if(gasit) {x=p->info; adauga_ultim(ultim4);}}}}

void afisare(nod *prim)


{for (nod *p=prim; p!=NULL ;p=p->urm) cout<<p->info<<" ";
IC

cout<<endl;}
void main()
{nod *prim1,*ultim1,*prim2,*ultim2,*prim3,*ultim3,*prim4,*ultim4;
CT

creare(prim1,ultim1); creare(prim2,ultim2); f.close();


reuniune(prim1,prim2,prim3,ultim3); cout<<"Reuniunea= "; afisare(prim3);
intersectie(prim1,prim2,prim4,ultim4); cout<<"Intersectia= ";
if (prim4!=NULL) afisare(prim4);
DA

else cout<<"Multimea vida";}

Scriei cte un program care s rezolve cerinele fiecrei probleme. Fieca-


Tem re problem se va descompune n subprobleme i algoritmul pentru rezol-
DI

varea unei subprobleme se va implementa cu un subprogram. Datele se


transmit ntre subprograme cu ajutorul parametrilor de comunicaie i nu al variabilelor
globale. Dup executarea unei operaii de prelucrare a listei simplu nlnuite, se vor afia
numerele din nodurile listei pentru a se verifica dac operaia de prelucrare s-a executat
RA

corect. Se vor alege seturi de date de intrare astfel nct s se verifice algoritmul pe toate
traseele lui. Pentru urmtorii 18 itemi n nodurile listelor se memoreaz numere ntregi. irul de
numere se citete dintr-un fiier text n care sunt scrise pe acelai rnd, separate prin spaiu.
1. Se creeaz o list n care ordinea de acces este cea n care sunt citite numerele. Se
TU

mai citesc de la tastatur dou numere x i y. Se insereaz n list numrul y naintea


numrului x.
2. Se creeaz o list n care ordinea de acces este invers celei n care sunt citite nume-
rele. Se elimin din list cel mai mic numr i cel mai mare numr.
I
ED
136 Implementarea structurilor de date

C
3. Se creeaz o list i se afieaz n ordinea invers citirii din fiier numai numerele pare.
4. Se creeaz o list n care ordinea de acces este cea n care sunt citite numerele din
fiier. Se mai citete un numr n de la tastatur. Se afieaz elementul cu numrul de

I
ordine n din list. Dac nu exist, se afieaz un mesaj de informare.

OG
5. Se creeaz o list n care ordinea de acces este cea n care sunt citite numerele din
fiier. Se insereaz naintea fiecrui numr factorii si primi.
6. Se creeaz o list n care ordinea de acces este cea n care sunt citite numerele din
fiier. Se insereaz ntre fiecare pereche de noduri cel mai mare divizor comun al celor

AG
dou numere.
7. Se creeaz dou liste n care ordinea de acces este cea n care sunt citite numerele din
fiiere. Se creeaz a treia list prin concatenarea listei care are cele mai puine
elemente la lista care are cele mai multe elemente. Dac listele au acelai numr de

ED
elemente, se va aduga lista a doua la prima list.
8. Se creeaz dou liste n care ordinea de acces este cea n care sunt citite numerele din
fiiere. Se creeaz a treia list prin concatenarea celei de a doua liste la prima list. Se
elimin din a treia list numerele care se repet.

P
9. Se creeaz o list n care ordinea de acces este cea n care sunt citite numerele din fiier.
Se divizeaz lista n dou liste: una care conine numere care sunt palindrom i una care
conine numerele care nu sunt palindrom. Se salveaz lista cu numere palindrom ntr-un
I
alt fiier. Dac nu au existat numere palindrom, n fiier se va scrie un mesaj de informare.
n lista care nu conine numere palindrom se insereaz dup fiecare numr inversul su.
10. Se creeaz o list n care ordinea de acces este cea n care sunt citite numerele din

fiier. Se afieaz numerele care au ultimele trei cifre identice, se elimin din list
numerele care au ultimele trei cifre consecutive i se insereaz valoarea 10 naintea
IC

numerelor care au suma ultimelor trei cifre egal cu 10.


11. Se creeaz o list n care ordinea de acces este cea n care sunt citite numerele din
fiier. Se afieaz numerele care au mai mult de doi divizori primi, se insereaz divizorii
CT

proprii n faa numerelor care au mai mult de trei divizori proprii i se elimin din list
numerele care au cel puin dou cifre identice.
12. Se creeaz o list numai cu numerele prime din fiier. Se afieaz cel mai mare numr
prim i cel mai mic numr prim. Se verific dac lista conine numai numere distincte i
DA

se afieaz un mesaj de informare. Dac lista nu conine numai numere distincte, se


elimin numere din list astfel nct s conin numai numere distincte. Se salveaz lista
creat ntr-un alt fiier. Dac nu au existat numere prime n fiier, se va scrie un mesaj
de informare. (Indicaie. Se va crea o list ordonat cresctor i se vor afia numerele
DI

prime din primul nod i din ultimul nod).


13. Se creeaz dou liste cu numerele citite din fiiere. n primul fiier numerele sunt
ordonate cresctor, iar n al doilea fiier numerele sunt ordonate descresctor. Se
RA

creeaz a treia list prin interclasarea primelor dou.


14. Se creeaz o list n care ordinea de acces este cea n care sunt citite numerele din
fiier. S se inverseze ordinea de acces n list, astfel nct parcurgerea s se fac de
la ultimul numr ctre primul numr. (Indicaie. Se mut ultimul nod la nceputul listei i
TU

apoi, pn se ajunge la numrul memorat la adresa care a fost a primului nod se


insereaz nodul ultim dup ultimul nod inserat.)
15. Se creeaz o list n care ordinea de acces este cea n care sunt citite numerele din
fiier. S se afieze n ordine invers numerele din list. (Indicaie. Se implementeaz
I

un algoritm recursiv de parcurgere a listei.)


ED
Informatic 137

C
16. Se creeaz o list ordonat cu numerele din fiier i se divizeaz apoi lista n dou liste:
una cu numere pare i una cu numere impare.
17. n fiier sunt memorate foarte multe numere (maxim 10.000). Foarte multe dintre aceste

I
numere se repet (exist maxim 100 de numere distincte). Se creeaz o list ordonat

OG
cresctor numai cu numerele distincte i cu frecvena lor de apariie. Se afieaz cel mai
mare numr i cel mai mic numr. Se calculeaz media aritmetic a numerelor care au
valoarea cea mai mare sau au valoarea cea mai mic i se afieaz numai numerele
care sunt mai mari dect media aritmetic.

AG
18. Pentru dou mulimi de numere A i B s se determine diferenele A-B i B-A.
19. Se citete dintr-un fiier text un numr cu maxim 20 de cifre. Se creeaz o list cu cifrele
numrului, se elimin din list cifrele pare i se afieaz numrul astfel obinut.
20. Se calculeaz produsul a dou polinoame. Informaiile despre cele dou polinoame se

ED
citesc dintr-un fiier. (Indicaie. Pentru fiecare nod din prima list se parcurge a doua
list i, dac produsul coeficienilor nu este nul, se creeaz un nod n lista a treia care va
avea coeficientul egal cu produsul coeficienilor i gradul egal cu suma gradelor. Lista a
treia este o list ordonat descresctor dup grad.)

P
21. Se creeaz dou liste cu n noduri i respectiv m noduri care conin numere ntregi
generate aleatoriu n intervalul [a,b]. Valorile pentru numrul de noduri n, i respectiv m,
i pentru limitele intervalului, a i b, se citesc de la tastatur. S se afieze numai
I
numerele distincte din cele dou liste i numrul care are cea mai mare frecven de
apariie n cele dou liste.

2.6.4. Algoritmi pentru prelucrarea listelor circulare simplu


nlnuite
IC

Algoritmii de adugare a primului nod la lista vid i de adugare dup ultimul nod
sunt la fel ca i cei de la listele simplu nlnuite:
CT

Lista circular simplu nlnuit


prim ultim
info urm info urm info urm info urm
DA

2.6.4.1. Crearea listei


Deoarece n algoritmii de prelucrare trebuie s se cunoasc adresa primului nod, este impor-
DI

tant adugarea primului nod la lista vid. Paii algoritmului de creare a unei liste sunt:
PAS1. Se adaug primul nod la list (nodul prim).
PAS2. Ct timp mai exist informaie execut: se adaug un nod la list dup ultimul nod.
RA

PAS3. Se leag ultimul nod de primul nod.


Implementarea algoritmului. Se folosete funcia procedural creare() al crei parame-
tru este prim de tip nod: care se transmite prin referin deoarece este parametru de
intrare-ieire. Se folosete variabila global n pentru citirea informaiei din nod. Se conside-
TU

r c nu mai exist informaie atunci cnd valoarea citit pentru n are valoarea 0.
void creare(nod *&prim)
{nod *ultim; cin>>n; adauga_nod(prim,ultim);
while(n!=0) {cin>>n; adauga_ultim(ultim);}
I

ultim->urm=prim;}
ED
138 Implementarea structurilor de date

C
2.6.4.2. Parcurgerea listei
Deoarece lista circular nu conine un ultim nod care s fie considerat ca terminator al
listei, se va considera ca nod care termin lista nodul prim. Paii algoritmului de prelu-

I
crare a unei liste circulare sunt:

OG
PAS1. Se prelucreaz primul nod din list (nodul prim).
PAS2. Pentru fiecare nod din list ncepnd de la succesorul nodului prim pn la
primul nod, execut: se prelucreaz nodul curent.
Implementarea algoritmului. Se folosete funcia procedural parcurge() al crei para-

AG
metru prim de tip nod se transmite prin valoare deoarece este parametru de intrare.
void parcuge(nod *prim)
{//se prelucreaz prim->info;
for (nod *p=prim->urm; p!=prim; p=p->urm) //se prelucreaz p->info;}

ED
2.6.4.3. Eliminarea unui nod din list
Dac se elimin din list nodul care urmeaz dup nodul curent p trebuie s se verifice
dac acest nod nu este nodul prim, ca s nu se piard adresa primului element din list.

P
Paii algoritmului de eliminare a nodului urmtor nodului curent sunt:
PAS1. Se salveaz adresa succesorului nodului p n pointerul q.
PAS2. Se leag nodul p de succesorul succesorului lui.
I
PAS3. Dac succesorul nodului p era nodul prim, atunci succesorul nodului prim devine
nodul prim.
PAS4. Se cere eliberarea zonei de memorie de la adresa memorat n pointerul q.

Implementarea algoritmului. Se folosete funcia procedural elimina_urm() ai crei para-


metri de tip nod sunt: p (pentru adresa nodului precedent nodului ce se elimin), care se
IC

transmite prin valoare deoarece este parametru de intrare i prim, care se transmite prin
referin, deoarece este parametru de intrare-ieire.
void elimina_urm(nod *p,nod *&prim)
CT

{nod *q=p->urm; p->urm=p->urm->urm;


if(q==prim) prim=prim->urm;
delete q;}
DA

Scop: exemplificarea modului n care, pentru rezolvarea problemei, folosii algoritmii de prelu-
crare a listelor circulare simplu nlnuite i implementarea lor cu ajutorul subprogramelor.
DI

Enunul problemei. Se citete dintr-un fiier text un ir de numere separate prin spaiu cu
care se creeaz o list circular simplu nlnuit n ordinea n care sunt citite numerele din
fiier. S se tearg numerele pare din list i s se afieze numerele din list. Pentru
testarea programului se vor folosi dou seturi de numere: {2, 2, 3, 4, 4} i {2, 2, 2, 4, 4}.
RA

Problema se descompune n urmtoarele subprobleme, iar algoritmii pentru rezolvarea


subproblemelor sunt implementai cu ajutorul subprogramelor:
P1 Se creeaz lista circular simplu nlnuit subprogramul creare().
TU

P2 Se parcurge lista de la succesorul primului nod pn la primul nod i dac numrul


din succesorul nodului curent este par, atunci se elimin succesorul nodului curent
subprogramul elimin urm(); altfel se trece la succesorul nodului curent.
P3 Dac numrul din nodul prim este par, atunci se elimin nodul prim i lista este vid
I

subprogramul elimin prim().


ED
Informatic 139

C
P4 Dac lista nu este vid (subprogramul este vid()), atunci se afieaz numerele
din fiecare nod (subprogramul afisare()).
#include<fstream.h>

I
struct nod {int info;

OG
nod *urm;};
fstream f("lista7.txt",ios::in);
int x;
void adauga_nod(nod *&prim,nod *&ultim)
{prim=new nod; prim->info=x; prim->urm=NULL; ultim=prim;}

AG
void adauga_ultim(nod *&ultim)
{nod *p=new nod; p->info=x; p->urm=NULL; ultim->urm=p; ultim=p;}
void creare(nod *&prim)
{nod *ultim; f>>x; adauga_nod(prim,ultim);

ED
while (f>>x) adauga_ultim(ultim);
ultim->urm=prim;}
void elimina_urm(nod *p,nod *&prim)
{nod *q=p->urm; p->urm=p->urm->urm;
if(q==prim) prim=prim->urm;

P
delete q;}
void elimina_prim(nod *&prim)
{nod *q=prim; prim=NULL; delete q;}
I
int este vida(nod *prim) {return prim==NULL;}
void afisare(nod *prim)
{cout<<prim ->info<<" ";

for (nod *p=p->urm;p!=prim;p=p->urm) cout<<p->info<<" "; cout<<endl;}


void main()
IC

{nod *prim,*p; creare(prim); afisare(prim);


for(p=prim->urm;p!=prim;)
if (p->urm->info%2==0) elimina_urm(p,prim);
else p=p->urm;
CT

if(prim->info%2==0) elimina prim(prim);


if (!este_vida(prim)) afisare(prim);}
Scriei cte un program care s rezolve cerinele fiecrei probleme. Fiecare
DA

Tem problem se va descompune n subprobleme i algoritmul pentru rezolvarea


unei subprobleme se va implementa cu un subprogram. Datele se transmit
ntre subprograme cu ajutorul parametrilor de comunicaie i nu al variabilelor globale. Se
creeaz liste circulare simplu nlnuite n nodurile crora se memoreaz numere ntregi.
DI

irul de numere se citete dintr-un fiier text n care sunt memorate pe acelai rnd, separate
prin spaiu. Dup executarea unei operaii de prelucrare a listei, se vor afia numerele din noduri
pentru a verifica dac operaia s-a executat corect. Se vor alege seturi de date de intrare astfel
nct s se verifice algoritmul pe toate traseele lui. Pentru urmtorii 4 itemi listele se creeaz
RA

astfel nct ordinea de acces s fie cea n care sunt citite numerele din fiier.
1. S se insereze, dup fiecare numr divizibil cu cea mai mare cifr a sa, valoarea cifrei,
i s se elimine numerele care au ultimele dou cifre consecutive.
2. S se verifice dac numerele sunt n progresie geometric i s se afieze primul
TU

termen al progresiei geometrice. (Observaie. Dac numerele sunt n progresie geome-


tric, nu este obligatoriu ca irul de numere citit din fiier s nceap cu primul termen al
progresiei geometrice.)
3. S se insereze ntre dou numere pare din list media lor aritmetic pn cnd nu mai
I
ED

exist perechi de numere pare.


140 Implementarea structurilor de date

C
4. Din lista circular creat s se creeze alte dou liste circulare simplu nlnuite una cu
numerele divizibile cu cea mai mare cifr, iar alta cu numerele divizibile cu cea mai mic
cifr i s se verifice dac cele dou liste conin numere comune.

I
5. Se creeaz o list ordonat cresctor i se creeaz apoi din aceast list o list cu

OG
numerele care sunt ptrate perfecte.

2.6.5. Algoritmi pentru prelucrarea listelor dublu nlnuite


n cazul listelor dublu nlnuite informaia de legtur trebuie s conin i adresa

AG
succesorului nodului (pointerul *ant ctre tipul nod):
struct nod
{int info; //informaia propriu-zis
nod *ant ,*urm;}; //informaia pentru legtur

ED
nod *prim, *ultim, *p;
Algoritmii de la listele simplu nlnuite se modific prin adugarea instruciunilor care
ntrein i adresa de legtur cu predecesorul nodului. Algoritmul de adugare a unui
nod p n interiorul listei naintea unui nod q se simplific deoarece se cunoate adresa

P
att a succesorului, ct i a predecesorului.
Lista dublu nlnuit
I
prim NULL info urm ant info urm

IC

ultim ant info NULL ant info urm


CT

2.6.5.1. Adugarea primului nod la list


Implementarea algoritmului. Se folosete funcia procedural adauga_nod() ai crei para-
DA

metri prim i ultim de tip nod se transmit prin referin deoarece sunt parametri de ieire.
void adaug nod (nod *&prim, nod *&ultim)
{prim = new nod; prim->info=x; prim->ant=NULL; prim->urm=NULL;
ultim=prim;}
DI

2.6.5.2. Adugarea unui nod la list


Adugare n faa primului nod
Implementarea algoritmului. Se folosete funcia procedural adauga_prim() al crei para-
RA

metru prim de tip nod se transmite prin referin deoarece este parametru de intrare-iere.
void adauga prim(nod *&prim)
{nod *p=new nod; p->info=x; p->ant=NULL; p->urm=prim; prim=p;}
Adugare dup ultimul nod
TU

Implementarea algoritmului. Se folosete funcia procedural adauga_ultim() al crei para-


metru ultim de tip nod se transmite prin referin deoarece este parametru de intrare-ieire.
void adauga ultim(nod *&ultim)
I

{nod *p=new nod; p->info=x;


ED

p->ant=ultim; p->urm=NULL; ultim->urm=p; ultim=p;}


Informatic 141

C
Adugarea n interiorul listei

prim ... q>ant q q>urm ... ultim

I
OG
a) dup nodul cu adresa q
Nodul p care se adaug se insereaz ntre nodul q i nodul q->urm. Succesorul su este nodul
q->urm, iar predecesorul su nodul q. Nodul p va fi succesorul nodului q i predecesorul no-
dului q->urm.

AG
Implementarea algoritmului. Se folosete funcia procedural adauga_dupa() ai crei para-
metri sunt de tip nod: q (adresa nodului dup care se face adugarea), care se transmite prin
valoare deoarece este parametru de intrare i ultim (adresa ultimului nod), care se transmite
prin referin deoarece este parametru de intrare-ieire.

ED
void adauga dupa(nod *q, nod *&ultim)
{nod *p=new nod; p->info=x; p->urm=q->urm; p->ant=q;
if (q==ultim) ultim=p; else q->urm->ant=p; q->urm=p;}

P
b) nainte de nodul de adres q
Nodul p care se adaug se insereaz ntre nodul q->ant i nodul q. Succesorul su este nodul
q, iar predecesorul su nodul q->ant. Nodul p va fi succesorul nodului q->ant i predecesorul
I
nodului q.
Implementarea algoritmului. Se folosete funcia procedural adauga_in_fata() ai crei
parametri sunt de tip nod: q (adresa nodului naintea caruia se face adugarea), care se trans-

mite prin valoare deoarece este parametru de intrare.


void adauga in fata(nod *q)
IC

{nod *p=new nod; p->info=x;


p->urm=q; p->ant=q->ant; q->ant->urm=p; q->ant=p;}

2.6.5.3. Parcurgerea listei


CT

Vizitarea fiecrui nod al listei se poate face n dou moduri:


pornind de la primul nod, pn la ultimul nod, n ordinea de nlnuire a nodurilor
furnizat de adresa urm din nodul vizitat;
DA

pornind de la ultimul nod, pn la primul nod, n ordinea de nlnuire a nodurilor


furnizat de adresa ant din nodul vizitat
Implementarea algoritmului. Se folosete funcia procedural parcurge-inainte(),
respectiv parcurge-inapoi(), al crei parametru prim, respectiv ultim, de tip nod, se
DI

transmite prin valoare deoarece este parametru de intrare.


void parcuge_inainte(nod *prim)
{for (nod *p=prim; p!=NULL; p=p->urm) //se prelucreaz p->info}
void parcuge_inapoi(nod *ultim)
RA

{for (nod *p=ultim; p!=NULL; p=p->ant) //se prelucreaz p->info}

2.6.5.4. Eliminarea unui nod din list


Eliminarea primului nod
TU

Implementarea algoritmului. Se folosete funcia procedural elimina_prim() al crei para-


metru prim de tip nod se transmite prin referin deoarece este parametru de intrare-ieire.
void elimina prim(nod *&prim)
I

{nod *q=prim; prim->urm->ant=NULL; prim=prim->urm; delete q;}


ED
142 Implementarea structurilor de date

C
Eliminarea ultimului nod
Implementarea algoritmului. Se folosete funcia procedural elimina_ultim() al crei para-
metru ultim de tip nod se transmite prin referin deoarece este parametru de intrare-ieire.

I
void elimina ultim(nod *&ultim)

OG
{nod *q=ultim; ultim->ant->urm=NULL; ultim=ultim->ant; delete q;}
Eliminarea unui nod din interiorul listei
Pentru a elimina nodul p aflat n interiorul listei, trebuie s legm predecesorul nodului p
(p->ant) de succesorul lui (p->urm). Succesorul nodului p->ant va fi nodul p->urm, iar pre-

AG
decesorul nodului p->urm va fi nodul p->ant.
Implementarea algoritmului. Se folosete funcia procedural elimina() al crei parametru
este de tip nod: p (adresa nodului care se elimin), care se transmite prin valoare deoarece

ED
este parametru de intrare.
void elimina(nod *p)
{nod *q=p; p->ant->urm=p->urm; p->urm->ant=p->ant; delete q;}

P
Scop: exemplificarea modului n care, pentru rezolvarea problemei, folosii algoritmii de prelu-
crare a listelor dublu nlnuite i implementarea lor cu ajutorul subprogramelor.
I
Enunul problemei 1. Se citete dintr-un fiier text un ir de numere separate prin spaiu
cu care se creeaz o list dublu nlnuit n ordinea n care sunt citite numerele din fiier.
S se adauge valoarea 1 dup fiecare numr par i s se tearg apoi numerele pare din

list. S se afieze numerele din list dup fiecare operaie de prelucrare, n ambele moduri
(de la primul la ultimul, i de la ultimul la primul). Pentru testarea programului se va folosi
IC

irul de numere: {2, 2, 5, 3, 4, 4}.


n prelucrarea listelor dublu nlnuite trebuie ntreinute att adresa primului nod, ct i
adresa ultimului nod. Problema se descompune n urmtoarele subprobleme, iar algoritmii
CT

pentru rezolvarea subproblemelor sunt implementai cu ajutorul subprogramelor:


P1 Se creeaz lista dublu nlnuit subprogramul creare().
P2 Se adaug un nod cu valoarea 1 dup fiecare numr par, astfel (subprogramul
DA

prelucrare 1()):
Se parcurge lista de la primul nod pn la penultimul nod i, dac numrul din
nodul curent este par, se adaug dup el un nod cu valoarea 1 subprogramul
adauga dupa().
DI

Dac numrul din nodul ultim este par, atunci se adaug dup el un nod care con-
ine valoarea 1 i acest nod devine nodul ultim subprogramul adauga ultim().
P3 Se elimin nodurile cu numere pare, astfel (subprogramul prelucrare 2()):
Se parcurge lista de la succesorul primului nod pn la penultimul nod i, dac
RA

numrul din nodul curent este par, atunci se elimin din list (subprogramul
elimina urm()); altfel, se trece la succesorul nodului curent.
Dac numrul din nodul prim este par, atunci se elimin din list i succesorul su
devine nodul prim subprogramul elimina_prim().
TU

#include<fstream.h>
struct nod {int info;
nod *ant,*urm;};
fstream f("lista8.txt",ios::in);
I

int x;
ED
Informatic 143

C
void adauga_nod(nod *&prim,nod *&ultim)
{prim=new nod; prim->info=x;
prim->urm=NULL; prim->ant=NULL; ultim=prim;}

I
void adauga_ultim(nod *&ultim)

OG
{nod *p; p=new nod; p->info=x;
p->urm=NULL; p->ant=ultim; ultim->urm=p; ultim=p;}
void adauga_dupa(nod *p)
{nod *q=new nod; q->info=x;
q->urm=p->urm; q->ant=p; p->urm->ant=q; p->urm=q;}

AG
void elimina_prim(nod *&prim)
{nod *q=prim; prim->urm->ant=NULL; prim=prim->urm; delete q;}
void elimina(nod *&p)
{nod *q=p; p->ant->urm=p->urm; p->urm->ant=p->ant; p=p->urm;
delete q;}

ED
void creare(nod *&prim,nod *&ultim)
{f>>x; adauga_nod(prim,ultim);
while (f>>x) adauga_ultim(ultim);}
void prelucrare 1(nod *prim,nod *&ultim)

P
{for(nod *p=prim;p->urm!=NULL;p=p->urm)
if (p->info%2==0) adauga_dupa(p);
if(ultim->info%2==0) adauga_ultim(ultim);}
I
void prelucrare 2(nod *&prim)
{for(nod *p=prim->urm;p->urm!=NULL;)
if (p->info%2==0) elimina(p); else p=p->urm;
if (prim->info%2==0) elimina_prim(prim);}

void afisare_urm(nod *prim)


{for (nod *p=prim;p!=NULL;p=p->urm) cout<<p->info<<" ";cout<<endl;}
IC

void afisare_ant(nod *ultim)


{for (nod *p=ultim;p!=NULL;p=p->ant) cout<<p->info<<" "; cout<<endl;}
void main()
CT

{nod *prim,*ultim,*p;
creare(prim,ultim); afisare_urm(prim); afisare_ant(ultim);
x=1; prelucrare 1(prim,ultim); afisare_urm(prim); afisare_ant(ultim);
prelucrare 2(prim); afisare_urm(prim); afisare_ant(ultim);}
DA

Enunul problemei 2 Calcularea rezistenei echivalente. S se calculeze rezistena


echivalent ntre punctele A i B pentru circuitul electric din figur.
DI
RA

Pentru calcularea rezistenei echivalente se pornete de la ultimele rezistene Rn i Rn-1


care sunt legate n serie. Se calculeaz rezistena lor echivalent Re1, care va fi legat n
paralel cu rezistena Rn-2. Prin calcularea rezistenei echivalente a celor dou rezistene
legate n paralel, Re1 i Rn-2, se va obine o nou rezisten echivalent Re2 care este legat
TU

n serie cu rezistena Rn-3. Calcularea rezistenei echivalente a circuitului electric este un


proces repetitiv n care alterneaz calcularea unei rezistene echivalente a dou rezistene
legate n serie cu calcularea unei rezistene echivalente a dou rezistene legate n paralel.
Pentru a ti care dintre variantele de calcul se alege, se folosete variabila s care are
I
ED

valoarea 1 dac rezistenele sunt legate n serie, i valoarea 0 dac sunt legate n paralel.
144 Implementarea structurilor de date

C
Valorile pentru rezistene se citesc dintr-un fiier text n care sunt memorate pe acelai rnd,
separate prin spaiu. Se creeaz o list dublu nlnuit n care ordinea de acces este cea n
care sunt citite numerele din fiier. Lista se parcurge de la ultimul nod pn la primul nod.

I
#include<fstream.h>

OG
struct nod {float info;
nod *ant,*urm;};
fstream f("rezistente.txt",ios::in);
float x;
void adauga_nod(nod *&prim,nod *&ultim)

AG
{prim=new nod; prim->info=x; prim->urm=NULL; prim->ant=NULL; ultim=prim;}
void adauga (nod *&ultim)
{nod *p; p=new nod; p->info=x;
p->urm=NULL; p->ant=ultim; ultim->urm=p; ultim=p;}

ED
void creare(nod *&prim, nod *&ultim)
{f>>x; adauga_nod(prim,ultim);
while (f>>x) adauga(ultim);}
float R(nod *ultim)
{int s=1; float r=ultim->info; nod *p=ultim->ant;

P
while (p!=NULL)
if (s) {r+=p->info; p=p->ant; s=0;}
else {r=(r*p->info)/(r+p->info); p=p->ant; s=1;}
I
return r;}
void main(){nod *prim, *ultim; creare(prim,ultim); f.close();
cout<<"Rezistenta echivalenta= "<<R(ultim);}

Recomandare. Listele dublu nlnuite se folosesc n problemele n care, pentru


prelucrarea informaiilor:
IC

se execut frecevent operaii de inserare i de eliminare de noduri;


lista trebuie parcurs n ambele sensuri.
Exemplu. n problemele n care trebuie prelucrate numere foarte mari (pentru memorarea
CT

crora nu pot fi folosite tipurile de date implementate) se folosesc listele dublu nlnuite:
pentru operaiile aritmetice (adunare, scdere, nmulire) listele n care sunt memorate
cele dou numere vor fi parcurse de la ultimul nod, pn la primul nod;
pentru compararea a dou numere sau determinarea numrului de cifre ale numrului,
DA

listele n care sunt memorate numerele vor fi parcurse de la primul pn la ultimul nod.
Scriei cte un program care s rezolve cerinele fiecrei probleme. Fiecare
Tem problem se va descompune n subprobleme i algoritmul pentru
DI

rezolvarea unei subprobleme se va implementa cu un subprogram. Datele


se transmit ntre subprograme cu ajutorul parametrilor de comunicaie i nu al variabilelor
globale. Se creeaz liste dublu nlnuite n nodurile crora se memoreaz numere ntregi.
irul de numere se citete dintr-un fiier text n care sunt memorate pe acelai rnd, separate
RA

prin spaiu. Dup executarea unei operaii de prelucrare a listei, se vor afia numerele din
noduri pentru a verifica dac operaia s-a executat corect. Se vor alege seturi de date de
intrare astfel nct s se verifice algoritmul pe toate traseele lui. Listele se creeaz astfel
nct ordinea de acces s fie cea n care sunt citite numerele din fiier.
TU

1. S se elimine numerele prime i s se insereze ntre fiecare pereche de numere rmase


cel mai mare divizor comun al lor.
2. S se calculeze cifra de control a fiecrui numr i, dac numrul este divizibil cu cifra
de control, cifra este adugat dup numr; altfel, numrul este eliminat din list. Cifra
I
ED
Informatic 145

C
de control a unui numr este suma repetat a cifrelor numrului pn cnd se obine o
sum mai mic dect 10.
3. S se modifice adresele din nodurile listei astfel nct s se obin dou liste liniare

I
dublu nlnuite care s conin numerele din poziiile pare, respectiv din poziiile impare.

OG
4. Se citesc dintr-un fiier dou numere foarte mari. S se scrie urmtoarele subprograme
pentru prelucrarea numerelor:
a. calcularea sumei, a diferenei i produsului numerelor;
b. compararea a dou numere (subprogramul trebuie s verifice dac cele dou

AG
numere sunt egale, iar dac nu sunt egale, s precizeze care numr este mai mare);
c. verificarea numrului dac are un numr par sau un numr impar de cifre, fr s se
numere cifrele numrului;
d. determinarea numrului de cifre ale unui numr;
e. verificarea numrului dac este palindrom.

ED
2.6.6. Algoritmi pentru prelucrarea stivelor
Cele dou extremiti ale stivei se numesc vrf i baz. Accesul la nodurile stivei

P
(adugarea, extragerea sau consultarea unui nod) este permis numai printr-o singur
extremitate numit vrf i ultimul nod inserat este primul nod extras (se extrage cea mai
nou informaie adugat). La o operaie de adugare a unui nod, vrful stivei stivei urc,
I
iar la o operaie de extragere a unui nod, vrful stivei coboar.
Implementarea dinamic a stivei se face la fel ca a unei liste liniare, cu deosebirea c:
vrful stivei va fi indicat de pointerul varf ctre tipul nod;

pentru adugarea unui nod, se poate folosi numai algoritmul de adugare n faa
primului nod;
IC

pentru extragerea unui nod se poate folosi numai algoritmul pentru eliminarea primului
nod.
Altfel spus, prelucrarea unei stive se face de la vrf spre baz i se prelucreaz ntotdea-
CT

una nodul din vrful stivei. Accesul la informaia din acest nod se face cu varf->info.
Stiva vid este stiva care nu conine nici un nod i adresa nodului vrf are valoarea
NULL (varf = NULL;). n stiva vid nu se mai pot executa operaii de extragere de
DA

noduri. Stiva poate s ajung s fie vid n dou cazuri: la iniializare sau dup
extragerea ultimului nod. Pentru testarea unei stive dac este vid, se poate
implementa funcia operand este_vida() care va furniza valoarea 1 (adevrat), dac
stiva este vid, i valoarea 0 (fals) dac stiva nu este vid.
DI

int este vida(nod *varf)


{return varf==NULL;}
Pentru prelucrri cu ajutorul stivei putei folosi urmtorii algoritmi:
iniializarea stivei;
RA

adugarea unui nod la stiv;


extragerea unui nod din stiv;
consultarea nodului din vrful stivei.
TU

2.6.6.1. Iniializarea stivei


Prin acest algoritm se creeaz stiva vid. n acest caz, nodul vrf nu exist i pointerul
varf are valoarea NULL.
Implementarea algoritmului. Se folosete funcia procedural init() al crei parametru
I
ED

varf se transmite prin referin, deoarece este parametru de ieire.


146 Implementarea structurilor de date

C
void init(nod *&varf)
{varf = NULL;}
2.6.6.2. Adugarea unui nod la stiv

I
OG
Nodul se adaug la stiv ca predecesor al vrfului. Paii algoritmului sunt:
PAS1. Se cere alocarea de memorie pentru nodul p.
PAS2. Se scrie informaia n nodul p.
PAS3. Nodul p se leag de nodul varf.
PAS4. Nodul p adugat devine nodul varf.

AG
Implementarea algoritmului. Se folosete funcia procedural adauga() al crei parametru
varf se transmite prin referin, deoarece este parametru de intrare-ieire.
void adauga(nod *&varf)
{nod *p=new nod; p->info=x; p->urm=varf; varf=p;}

ED
2.6.6.3. Extragerea unui nod din stiv
Nodurile se extrag din stiv pentru a putea consulta informaia care exist n nodurile
urmtoare. Un nod se poate extrage numai n cazul n care stiva nu este vid. Se poate

P
extrage numai nodul din vrful stivei (se elibereaz spaiul care a fost ocupat de nod). n
vrful stivei va ajunge succesorul nodului extras. Paii algoritmului sunt:
PAS1. Se salveaz adresa nodului varf n pointerul p.
I
PAS2. Succesorul nodului varf devine nodul varf.
PAS3. Se cere eliberarea zonei de memorie de la adresa memorat n pointerul p.
Implementarea algoritmului. Se folosete funcia procedural extrage() al crei para-

metru varf se transmite prin referin, deoarece este parametru de intrare-ieire.


void extrage (nod *&varf)
IC

{nod *p =varf; varf=varf->urm; delete p;}


2.6.6.4. Prelucrarea stivei
CT

Prin acest algoritm se consult informaia din fiecare nod al stivei. Deoarece nu poate fi
consultat dect informaia din vrful stivei, pentru a ajunge la un nod trebuie s se
extrag toate nodurile pn la el.
DA

Implementarea algoritmului. Se folosete funcia procedural prelucrare() al crei parame-


tru varf de tip nod se transmite prin referin, deoarece este parametru de intrare-ieire.
void prelucrare(nod *&varf)
{while (varf!=NULL) {//se prelucreaz varf->info
extrage(varf);)}
DI

Scop: exemplificarea modului n care, pentru rezolvarea problemei, folosii algoritmii de prelu-
RA

crare a stivelor i implementarea lor cu ajutorul subprogramelor.


Enunul problemei. Se citete dintr-un fiier text un ir de numere separate prin spaiu
care se depun ntr-o stiv n ordinea n care sunt citite numerele din fiier. S se elimine
TU

numrul de la baza stivei i numerele rmase n stiv s se scrie ntr-un fiier text. Pentru
testarea programului se va folosi irul de numere: {1, 2, 5, 3, 4}.
n prelucrarea stivelor, pentru a putea ajunge la informaia care trebuie prelucrat, trebuie
extrase toate nodurile, pn la nodul care conine acea informaie, deoarece nu poate fi
I

prelucrat dect informaia din vrful stivei. Pentru a nu se pierde informaia din nodurile
ED
Informatic 147

C
extrase, ele vor fi descrcate ntr-o alt stiv (de rezerv), iar dup prelucrarea informaiei,
nodurile vor fi ncrcate din nou n stiv.
Consultarea nodului care conine numrul 3

I
OG
5 varf 5 varf
descarc consult ncarc
4 4
3 3 varf 3
2 4 varf_r 2 4 varf_r 2

AG
1 5 1 5 1 varf_r=NULL
stiva stiva de rezerv stiva stiva de rezerv stiva stiva de rezerv
Problema se descompune n urmtoarele subprobleme, iar algoritmul de rezolvare a unei
subprobleme este implementat cu ajutorul unui subprogram:

ED
P1 Se creeaz stiva cu numerele citite din fiier (nodul varf) subprogramul creare()).
P2 Se descarc stiva ntr-o alt stiv (nodul varf r) pn la penultimul nod (subpro-
gramul descarca()).

P
P3 Se extrage ultimul nod din stiv subprogramul extrage().
P4 Se ncarc n stiv (nodul varf) nodurile din stiva de rezerv (nodul varf r) sub-
programul incarca().
I
P5 Se scriu numerele din stiv (nodul varf) n fiierul text subprogramul salveaza().
#include<fstream.h>
struct nod {int info;
nod *urm;};

fstream f1("stiva1.txt",ios::in),f2("stiva2.txt",ios::out);
int x;
IC

void init(nod *&varf) {varf=NULL;}


void adauga(nod *&varf) {nod *p=new nod; p->info=x; p->urm=varf; varf=p;}
int este vida(nod *varf) {return varf==NULL;}
CT

void extrage(nod *&varf) {nod *p=varf; varf=varf->urm; delete p;}


void creare(nod *&varf)
{init(varf); while (f1>>x) adauga(varf);}
void descarca(nod *&varf,nod *&varf r)
DA

{init(varf r);
while (varf->urm!=NULL) {x=varf->info; extrage(varf); adauga(varf r);}}
void incarca(nod *&varf,nod *&varf r)
{while (!este vida(varf_r))
DI

{x=varf r->info; extrage(varf_r); adauga(varf);}}


void salveaza(nod *&varf)
{while (!este vida(varf)) {f2<<varf->info<<" "; extrage(varf);}}
void main() {nod *varf, *varf_r; creare(varf); f1.close();
RA

descarca (varf,varf r); extrage(varf);


incarca(varf,varf_r); salveaza(varf); f2.close();}
Fiecare problem se va descompune n subprobleme i algoritmul pentru
Tem rezolvarea unei subprobleme se va implementa cu un subprogram. Datele
TU

se transmit ntre subprograme cu ajutorul parametrilor de comunicaie i nu


al variabilelor globale. Se creeaz stive n nodurile crora se memoreaz informaia (numere
sau caractere). Informaia se citete dintr-un fiier text n care, numerele sau caracterele, sunt
memorate pe acelai rnd, separate prin spaiu. Se vor alege seturi de date de intrare astfel
I

nct s se verifice algoritmul pe toate traseele lui.


ED
148 Implementarea structurilor de date

C
1. ntr-o stiv sunt memorate numere din intervalul [1,10], ordonate cresctor, iar ntr-o alt
stiv, numere din intervalul [20,30], ordonate cresctor. S se concateneze cele dou
iruri de numere, pstrnd ordonarea cresctoare. (Indicaie. Se rstoarn a doua stiv

I
ntr-o a treia stiv, se rstoarn i prima stiv n a treia, peste numerele din prima stiv, i

OG
se extrag numerele din a treia stiv.)
2. Se compar dou stive fr a pierde coninutul lor n urma extragerii de noduri.
3. Se elimin din stiv numerele pare.
4. Se memoreaz ntr-o stiv un ir de litere mici. Se citete de la tastatur o liter mic a alfa-

AG
betului lit. S se creeze dou stive: una va conine literele din stiva iniial care preced n
alfabet litera lit i alta va conine literele din stiva iniial care succed n alfabet litera lit
5. S se afieze n ordine invers numerele dintr-o list liniar simplu nlnuit. (Indicaie.
Se ncarc numerele din list ntr-o stiv, n ordinea de parcurgere a listei, i apoi se

ED
extrag i se afieaz numerele din stiv.)
6. Se ordoneaz cresctor un ir de numere, cu ajutorul a dou stive. Determinai com-
plexitatea algoritmului. (Indicaie. Se folosesc dou stive. Se scrie un numr n Stiva 1.
Se citete un numr. Dac numrul din vrful Stivei 1 este mai mare dect numrul citit,

P
atunci noul numr se adaug la Stiva 1; altfel, se descarc din Stiva 1 n Stiva 2 numere
pn cnd n vrful Stivei 1 ajunge un numr mai mare dect numrul citit, se adaug la
Stiva 1 numrul citit, i se ncarc n Stiva 1 numerele din Stiva 2.)
I
7. S se verifice dac o expresie aritmetic ce conine paranteze este balansat, adic dac
fiecare parantez deschis este nchis corect. De exemplu, expresia (a+b+{c/[d-e]})+
(d/s) este balansat, iar expresia (a+b+{c/[d-e}])+(d/s) nu este balansat. (Indicaie. Se

codific parantezele 1(; 2 [; 3{; 4); 5]; 6}). Dac stiva nu este vid i dac diferena
dintre codul dintre paranteza citit i codul parantezei din vrful stivei este 3, atunci se
IC

elimin nodul din vrful stivei; altfel, se adaug la stiv codul parantezei citite. Dac stiva
este vid la terminarea evalurii expresiei, nseamn c expresia este balansat.)
CT

2.6.7. Algoritmi pentru prelucrarea cozilor


Cele dou extremiti ale cozii se numesc cap i baz. Adugarea de noduri la coad se
face prin nodul baz, iar extragerea i consultarea unui nod este permis numai prin
extremitatea cap (se extrage cea mai veche informaie adugat).
DA

Implementarea dinamic a cozii se face la fel ca a unei liste liniare, cu deosebirea c:


primul nod al cozii va fi indicat de pointerul cap ctre tipul nod, iar ultimul nod al cozii va
fi indicat de pointerul baza ctre tipul nod;
DI

pentru adugarea unui nod, se poate folosi numai algoritmul de adugare dup
ultimul nod;
pentru extragerea unui nod se poate folosi numai algoritmul pentru eliminarea
primului nod.
RA

Altfel spus, prelucrarea unei cozi se face de la cap spre baz i se prelucreaz ntotdeauna
nodul din capul cozii. Accesul la informaia din acest nod se face cu cap->info.
Coada vid este coada care nu conine nici un nod i adresa nodului cap are valoarea
TU

NULL (cap = NULL;). n coada vid nu se mai pot executa operaii de extragere de
noduri. Coada poate s ajung s fie vid n dou cazuri: la iniializare sau dup
extragerea ultimului nod. Pentru testarea unei cozi dac este vid se poate implementa
funcia operand este_vida() care va furniza valoarea 1 (adevrat), dac este vid, i
I

valoarea 0 (fals) dac nu este vid.


ED
Informatic 149

C
int este vida(nod *cap)
{return cap==NULL;}
Pentru prelucrri cu ajutorul cozii putei folosi urmtorii algoritmi:

I
iniializarea cozii;

OG
adugarea unui nod la coad;
extragerea unui nod din coad;
consultarea nodului din capul cozii.
2.6.7.1. Iniializarea cozii

AG
Prin acest algoritm se creeaz coada care conine un nod. n acest caz, nodurile cap i
baz vor avea aceeai adres.
Implementarea algoritmului. Se folosete funcia procedural init() ai crei parametri
cap i baza se transmit prin referin, deoarece sunt parametri de ieire.

ED
void init(nod *&cap, nod *&baza)
{cap=new nod; cap->info=x; cap->urm=NULL; baza=cap;}
2.6.7.2. Adugarea unui nod la coad

P
Nodul se adaug la coad ca succesor al bazei. Paii algoritmului sunt:
PAS1. Se cere alocarea de memorie pentru nodul p.
PAS2. Se scrie informaia n nodul p.
I
PAS3. Nodul p se leag de nodul baza.
PAS4. Nodul p adugat devine nodul baza.
Implementarea algoritmului. Se folosete funcia procedural adauga() al crei parametru

baza se transmite prin referin deoarece este parametru de intrare-ieire.


void adauga(nod *&baza)
IC

{nod *p=new nod; p->info=x; p->urm=NULL; baza->urm=p; baza=p;}


2.6.7.3. Extragerea unui nod din coad
CT

Nodurile se extrag din coad pentru a putea consulta informaia care exist n nodurile
urmtoare. Un nod se poate extrage numai n cazul n care coada nu este vid. Se poate
extrage numai nodul din capul cozii (se elibereaz spaiul care a fost ocupat de nod). n
capul cozii va ajunge succesorul nodului extras. Paii algoritmului sunt:
DA

PAS1. Se salveaz adresa nodului cap n pointerul p.


PAS2. Succesorul nodului cap devine nodul cap.
PAS3. Se cere eliberarea zonei de memorie de la adresa memorat n pointerul p.
Implementarea algoritmului. Se folosete funcia procedural extrage() al crei para-
DI

metru cap se transmite prin referin, deoarece este parametru de intrare-ieire.


void extrage(nod *&cap)
{nod *p =cap; cap=cap->urm; delete p;}
RA

2.6.7.4. Prelucrarea cozii


Prin acest algoritm se consult informaia din fiecare nod al cozii. Deoarece nu poate fi
consultat dect informaia din capul cozii, pentru a ajunge la un nod trebuie se
extrag toate nodurile pn la el.
TU

Implementarea algoritmului. Se folosete funcia procedural prelucrare() al crei parame-


tru cap de tip nod se transmite prin referin, deoarece este parametru de intrare-ieire.
void prelucrare(nod *&cap)
I

{while (cap!=NULL) {//se prelucreaz cap->info


ED

extrage(cap);)}
150 Implementarea structurilor de date

C
Scop: exemplificarea modului n care, pentru rezolvarea problemei, folosii algoritmii de prelu-

I
crare a cozilor i implementarea lor cu ajutorul subprogramelor.

OG
Enunul problemei. Se citete dintr-un fiier text un ir de numere separate prin spaiu
care se depun ntr-o coad n ordinea n care sunt citite din fiier. S se elimine numrul din
mijlocul cozii, dac numrul de noduri este impar, i cele dou numere din mijloc, dac
numrul de noduri este par, iar numerele rmase n coad s se scrie ntr-un fiier text.

AG
Pentru testarea programului se vor folosi dou seturi de numere: {1, 2, 5, 3, 4} i {1, 2, 5, 4}.
n prelucrarea cozilor, pentru a putea ajunge la informaia care trebuie prelucrat, trebuie
extrase toate nodurile pn la nodul care conine acea informaie, deoarece nu poate fi pre-
lucrat dect informaia din capul cozii. Pentru a nu se pierde informaia din nodurile extrase,

ED
ele vor fi descrcate ntr-o alt coad (de rezerv), iar dup prelucrarea informaiei, nodurile
vor fi descrcate n continuare n coada de rezerv, pn cnd coada iniial devine vid.
Consultarea nodului care conine numrul 3

P
coada coada coada
1 2 3 4 5 consult 3 4 5 cap=NULL
cap baz cap baz
I
descarc
descarc
coada de rezerv coada de rezerv
1 2 1 2 3 4 5

cap_r baza_r cap_r baza_r


IC

Problema se descompune n urmtoarele subprobleme, iar algoritmul de rezolvare a unei


subprobleme este implementat cu ajutorul unui subprogram:
P1 Se creeaz coada cu numerele citite din fiier (nodurile cap i baza) subprogramul
CT

creare().
P2 Se descarc coada ntr-o alt coad (nodurile cap r i baza r) pn la nodurile care
trebuie eliminate subprogramul descarca 1().
P3 Se extrage nodul sau se extrag nodurile din mijlocul cozii subprogramul extrage().
DA

P4 Se descarc restul nodurilor din coad (nodul cap) n coada de rezerv (nodul
baza_r) subprogramul descarca_2().
P5 Se scriu numerele din coada de rezerv (nodul cap r) n fiierul text subprogramul
salveaza().
DI

#include<fstream.h>
struct nod {int info;
nod *urm;};
fstream f1("coada1.txt",ios::in),f2("coada2.txt",ios::out);
RA

int x,n,i,j;
void init(nod *&cap,nod *&baza)
{cap=new nod; cap->info=x; cap->urm=NULL; baza=cap;}
int este vida(nod *cap) {return cap==NULL;}
TU

void adauga(nod *&baza)


{nod *p=new nod; p->info=x; p->urm=NULL; baza->urm=p; baza=p;}
void extrage(nod *&cap) {nod *p=cap; cap=cap->urm; delete p;}
void creare(nod *&cap, nod *&baza)
I

{f1>>x; init(cap,baza); n++;


ED
Informatic 151

C
while (f1>>x) {adauga(baza); n++;}}
void descarca 1(nod *&cap,nod *&cap r, nod *&baza_r)
{x=cap->info; extrage(cap); init(cap r,baza r);i++;

I
while (i<j) {x=cap->info; extrage(cap); adauga(baza_r);i++;}}

OG
void descarca 2(nod *&cap,nod *&baza r)
{while (!este_vida(cap))
{x=cap->info; extrage(cap); adauga(baza_r);}}
void salveaza(nod *&cap)
{while (!este_vida(cap)) {f2<<cap->info<<" "; extrage(cap);}}

AG
void main()
{nod *cap,*baza,*cap r,*baza r; creare(cap,baza); f1.close();
if (n%2==0) j=n/2-1; else j=n/2;
descarca_1(cap,cap r,baza r); extrage(cap);
if (n%2==0) extrage(cap);

ED
descarca 2(cap,baza r); salveaza(cap r); f2.close();}
Fiecare problem se va descompune n subprobleme i algoritmul
Tem pentru rezolvarea unei subprobleme se va implementa cu un subpro-

P
gram. Datele se transmit ntre subprograme cu ajutorul parametrilor de
comunicaie i nu al variabilelor globale. Se creeaz cozi n nodurile crora se memo-
reaz numere ntregi. irul de numere se citete dintr-un fiier text n care sunt memorate
I
pe acelai rnd, separate prin spaiu. Se vor alege seturi de date de intrare astfel nct s
se verifice algoritmul pe toate traseele lui.
1. Se elimin din coad numerele pare.
2. Se verific dac numerele dintr-o coad sunt ordonate (cresctor sau descresctor).

3. Se concateneaz dou cozi, adugnd a doua coad la sfritul primei cozi.


IC

4. Se formeaz din dou cozi o a treia coad care conine mai nti numerele pare din pozi-
iile impare din prima coad i apoi numerele impare din poziiile pare din a doua coad.
5. Se inverseaz ordinea numerelor dintr-o coad cu ajutorul unei stive.
CT

2.6.8. Aplicaii practice


1. Analiza lexical a unui text. S se afieze, n ordine alfabetic, cuvintele dintr-un text
i frecvena lor de apariie n text.
DA

2. Exist dou automate care elibereaz bonuri de ordine pentru o coad de ateptare. Pe
fiecare bon de ordine este trecut numrul bonului i momentul la care a fost eliberat
(exprimat n or, minut i secund). Bonurile au numere unice. Deservirea persoanelor
se face n ordinea momentului de eliberare a bonurilor. S se organizeze o coad de
DI

ateptare pe baza bonurilor emise de cele dou automate.


3. Jocul lui Josephus. ntr-un grup de n copii, acetia sunt aranjai n cerc i sunt numrai
ncepnd cu primul copil pn la numrul k. Copilul care are numrul k iese din joc, iar
RA

numrtoarea ncepe din nou de la 1 cu urmtorul copil. S se afieze ordinea de ieire


din joc a copiilor. Se vor implementa dou soluii, folosind o structur de date de tip:
a) coad; b) list circular simplu nlnuit.
4. S se simuleze, cu ajutorul unei stive, o main de adunat i multiplicat. Numerele se
TU

introduc ntr-o stiv i operaia se ncheie atunci cnd se citete de la tastatur


operatorul + (pentru adunarea numerelor) sau operatorul * (pentru nmulirea
numerelor). Se mai folosesc: caracterul A, pentru a anula ultimul numr introdus, i
caracterul C, pentru a anula toate numerele introduse.
I
ED
152 Implementarea structurilor de date

C
5. Un automobil trebuie s parcurg un traseu care formeaz un poligon, cu ntoarcere la staia
de pornire. Pe traseu exist n staii de alimentare cu carburant care formeaz vrfurile poli-
gonului. Fiecare staie de alimentare i este caracterizat de coordonatele (xi,yi). Automobilul

I
consum 1 litru de carburant la fiecare 20 km i nu exist restricie pentru capacitatea rezer-

OG
vorului. Se citesc dintr-un fiier text urmtoarele informaii: de pe primul rnd numrul de sta-
ii n, de pe urmtorul rnd un ir de n numere ci care reprezint cantitatea de combustibil cu
care este alimentat la staia i, iar de pe urmtorul rnd n perechi de numere xi i yi care re-
prezint coordonatele staiei i. Din ce punct trebuie s plece automobilul astfel nct s par-

AG
curg traseul cu ntoarcere n punctul de pornire i s nu rmn fr combustibil.

Pentru exerciiile urmtoare, dac nu se specific semnificaia variabilelor de memorie, se

ED
folosesc urmtoarele date:
struct nod {int info;
nod *urm;};
nod *prim,*ultim,*p,*q,*r,*u,*vf,*cap,*baza;

P
int x,k;
Rspundei:
I
1. Analizai din punct de vedere al complexitii algoritmii pentru prelucrarea listelor. Se
va folosi n determinarea complexitii timpul maxim de execuie. Pentru compararea
algoritmilor completai urmtorul tabel:

Lista simplu nlnuit Lista dublu nlnuit


Neordonat Ordonat Neordonat Ordonat
IC

Caut (L,k)
Adaug (L,x)
Elimin (L,x)
CT

Succesorul (L,x)
Predecesorul (L,x)
Minim (L)
Maxim (L)
DA

2. O list simplu nlnuit conine, n ordine, urmtoarele noduri: 2 4 6 8 10


12 14 16 18 20. Ce se va afia n urma execuiei urmtoarei secvene
de program?
DI

for(p=prim,k=1;k<5;k++,p=p->urm); cout<< p->info;


3. O list simplu nlnuit conine, n ordine, urmtoarele noduri: 1 2 3 4 5
6 7 8. Ce se va afia n urma execuiei urmtoarei secvene de program?
for(k=0,p=prim;p->urm!=NULL; p=p->urm) if (p->info%2) k+= p->info;
RA

cout<<k;
4. Ce se va afia n urma execuiei urmtoarei secvene de program, dac lista simplu
nlnuit conine, n ordine, urmtoarele noduri: 1 2 3 4 5? Dar dac
nodurile ei sunt, n ordine: 1 0 3 0 5?
TU

for(p=prim; p->info!=0;p=p->urm); cout<<p->info;


5. Ce se va afia n urma execuiei urmtoarei secvene de program, dac lista simplu
nlnuit conine, n ordine, urmtoarele noduri: 1 2 3 7 8 9? Dar dac
nodurile ei sunt, n ordine: 1 2 4 5 7 8?
I
ED

for(k=0,p=prim;p->info!=0;p=p->urm)
Informatic 153

C
if (p->urm->info-p->info==1) k++;
cout<<k;

Adevrat sau Fals:

I
OG
1. Dac p este primul nod al listei, pentru a afia informaia din al doilea nod se execut
secvena de instruciuni: p=p->urm; cout<<p->info;
2. Dac p este primul nod al listei, pentru a afia informaia din al doilea nod se execut
instruciunea: cout<<p->urm->info;

AG
3. Dac p este primul nod al listei, pentru a afia informaia din al treilea nod se execut
instruciunea: cout<<p->urm->urm->info;

Alegei:

ED
1. Dac p este primul nod al listei, iar q al doilea nod al listei, prin ce instruciune se
leag nodul p de nodul q?
a. p=q; b. q=p->urm; c. p=q->urm; d. p->urm=q;
2. Care dintre urmtoarele variante realizeaz corect legturile n cazul inserrii unui

P
nod nou ntr-o list simplu nlnuit, dac nodul nou are adresa p, iar nodul dup
care se insereaz are adresa q?
a. p->urm=q; q->urm=p->urm; b. p->urm=q->urm; q->urm=p;
I
c. q->urm=p->urm; d. p->urm=q->urm; p->urm=q;
3. Dac p este primul nod al listei, ce instruciune trebuie executat pentru a afia
informaia memorat n al treilea nod?
a. cout<<p->urm->urm->info->info; b. cout<<p->urm->info->urm->info;

c. cout<<p->urm->urm->info; d. cout<< p->urm->urm->urm->info;


4. Dac p, q i r sunt trei noduri consecutive ale listei, pentru a interschimba nodul q cu
IC

nodul r, care dintre secvenele de instruciuni este corect?


a. r->urm=q; q->urm=r->urm; p->urm=r;
b. p->urm=r; r->urm=q; q->urm=r->urm;
CT

c. q->urm=r->urm; r->urm=q; p->urm=r;


d. r->urm=q; p->urm=r; q->urm=r->urm;
5. Dac p este un nod al listei i q un pointer ctre tipul nod, care dintre secvenele de
instruciuni urmtoare realizeaz corect legturile astfel nct s se elimine din list
DA

cele dou noduri care urmeaz dup nodul p?


a. p->urm=p->urm->urm->urm->urm; b. p->urm=p->urm->urm;
c. p->urm->urm=p->urm->urm->urm; d. q=p->urm; p->urm=q->urm->urm;
6. Dac L1 este o list organizat ca stiv, stabilii care este adresa corect de
DI

extragere din stiv:


a. delete p; p=p->urm; b. r=p->urm; p=r; delete p;
c. r=p; p=p->urm; delete p; d. r=p->urm; p=r; delete r;
7. Care dintre urmtoarele secvene de program calculeaz, n variabila k, suma ele-
RA

mentelor din lista simplu nlnuit:


a. for(k=0,p=prim;p!=NULL;p= p->urm) k+= p->info;
b. for(k=0,p=prim; p->urm!=NULL;p= p->urm) k+=p->info;
c . k=0; p=prim; while (p!=NULL) {k+= p->info; p= p->urm;}
TU

d. p=prim; k= p->info;
do {p= p->urm; k+= p->info;} while (p->urm!=NULL);
n urmtorii 7 itemi, variabilele p i q memoreaz adresele de nceput ale listelor
liniare simplu nlnuite nevide L1 i respectiv L2. Elementele listelor sunt de tipul nod.
I
ED

(Bacalaureat Sesiunea iunie-iulie 2003)


154 Implementarea structurilor de date

C
8. Trebuie mutat primul element al listei L1 imediat dup primul element al listei L2, n
rest listele rmnnd neschimbate. Care dintre urmtoarele atribuiri sunt necesare i
n ce ordine se efectueaz? 1) r=q->urm; 2) r=p->urm; 3) q->urm=p; 4) p=r;

I
5) p->urm=r; 6) p->urm =q->urm;

OG
a. 1 6 3 4 b. 1 3 5 c. 2 6 3 4 d. 2 3 6 4
9. Trebuie mutat primul element al listei L1 imediat dup primul element al listei L2, n
rest listele rmnnd neschimbate. Care dintre urmtoarele atribuiri sunt necesare i
n ce ordine se efectueaz? 1) r=q->urm; 2) r=p->urm; 3) q->urm=p; 4) p=r;

AG
5) p->urm=r; 6) p->urm =q->urm;
a. 1 6 3 4 b. 1 3 5 c. 2 6 3 4 d. 2 3 6 4
10. Dac la sfritul executrii secvenei alturate valoarea r=p->urm;
variabilei r este nul, atunci lista L1: while (r!=p && r)

ED
a. are cel puin dou elemente b. este vid r=r->urm;
c. este incorect constituit d. nu este circular
11. Funcia egale(ad1,ad2) returneaz valoarea 1 dac i numai dac informaiile utile
memorate la adresele ad1 i ad2 coincid, altfel returneaz valoarea 0. Secvena

P
alturat calculeaz n variabila ntreag n numrul de elemente din lista L1:
a. distincte consecutive aflate la nceputul listei n=0; r=p;
b. egale consecutive aflate la nceputul listei while (egale(r,p) && r)
I
c. care sunt egale cu primul element {r=r->urm; n++;}
d. care sunt egale dou cte dou
12. Dac L1 este o coad, cu p adresa primului element i u adresa ultimului element, iar
r este adresa unui element ce urmeaz a fi adugat n coad, stabilii care dintre

urmtoarele este o operaie corect de adugare:


a. r=u->urm; u=r; b. r->urm=p; p=r;
IC

c. u->urm=r; u=r; d. r->urm=u; u=r;


13. Pentru a uni listele L1 i L2 plasnd lista L1 n continuarea listei L2, se efectueaz
operaiile:
CT

a. r=q; while (r->urm) {r=r->urm; r->urm=p;}


b. r=p; while (r) r=r->urm; r=q;
c. r=q; while (r->urm) r=r->urm; r->urm=p;
d. r=p; while (r->urm) r=r->urm; r->urm=q;
DA

14. Pentru a determina numrul de elemente ale listei L1 se utilizeaz o variabil


ntreag n astfel:
a. n=0; r=p; while (r->urm) {r=r->urm; n++;}
b. n=0; r=p; while (r) r=r->urm; n++;
DI

c. n=0; r=p; while (r) {r=r->urm; n++;}


d. n=0; r=p; do {n++;} while (r)
n urmtorii 6 itemi, variabilele p i u memoreaz adresa primului, respectiv a ultimului
RA

element al listei liniare simplu nlnuite nevide L. Elementele listelor sunt de tipul nod.
(Bacalaureat Sesiunea august 2003)
15. tiind c L este format din 4 elemente, atunci adresa penultimului element este:
a. p->urm->urm-> b. p->urm->urm c. p->urm d. p->urm->urm->urm
TU

16. Elementele din lista L aflate la adresele q i r sunt vecine (consecutive) n list dac
i numai dac:
a. q->urm == r->urm b. r->urm == q && q->urm == r
c. q->urm == r || r->urm == q d. q == r
I
ED
Informatic 155

C
17. tiind c este definit o funcie cnt astfel nct cnt(a1,a2) returneaz numrul de
elemente situate n list ntre elementele de la adresa a1 i a2 (fr a numra
elementele de la adresele respective), care dintre urmtoarele expresii arat al

I
ctelea este elementul memorat la adresa q n lista L?

OG
a. cnt(p,q)+2 b. cnt(q,u)+2 c. cnt(q,u)+1 d. cnt(p,q)+1
18. Este definit o funcie min astfel nct min(a1,a2) returneaz valoarea 1 dac i
numai dac cel puin unul dintre elementele memorate la adresele a1 i a2 se afl n
lista L i returneaz valoarea 0 n caz contrar. Care dintre urmtoarele expresii are

AG
valoarea 1 dac i numai dac elementul de la adresa q se afl n lista L?
a. min(p,q) b. min(q,u) c. min(p,u) d. min(q,q)
r=p;
19. Un element aflat la adresa q face parte din lista L dac la while (r!=q && r)
sfritul executrii secvenei alturate variabila r are valoarea: r=r->urm;

ED
a. 1 b. p c. q d. NULL / 0
20. Lista L are exact dou elemente dac:
a. p->urm==u b. u->urm==NULL / !u->urm
c. p=u d. p->urm==NULL / !p->urm

P
21. Dac n variabila p este memorat iniial adresa primului nod al unei liste simplu
nlnuite cu cel puin 10 elemente, pentru a obine n variabila p adresa penultimului
nod al listei se execut secvena:
I
a. while (!p) p->urm; b. while (!p->urm) p->urm;
c. while (p->urm->urm) p->urm; d. while (p->urm) p->urm;
(Bacalaureat Sesiunea special 2003)

22. tiind c ntr-o list circular simplu nlnuit cu cel puin dou elemente, adresele p i
q reprezint adresele a dou elemente distincte din list, atunci elementul memorat la
IC

adresa p este succesorul elementului memorat la adresa q n list dac i numai dac:
a. p->urm == q; b. q->urm == p
c. p->urm == q->urm; d. q->urm->urm == p
CT

(Bacalaureat Sesiunea special 2004)


23. Dac ntr-o list circular simplu nlnuit, cu cel puin 4 elemente, se cunoate
adresa p a unui element din list, atunci este accesibil adresa elementului din list
precedent celui aflat la adresa p?
DA

a. Nu.
b. Da, n orice situaie.
c. Da, numai dac p este adresa primului element al listei.
d. Da, numai dac p este adresa ultimului element al listei.
DI

(Bacalaureat Sesiunea iunie-iulie 2004)


24. ntr-o list liniar simplu nlnuit nevid, pentru eliminarea elementului ce urmeaz
dup elementul aflat la adresa p (elementul de la adresa p nu este nici primul, nici
ultimul) un elev utilizeaz trei instruciuni simple (nestructurate). Care dintre instruc-
RA

iunile urmtoare poate fi una dintre cele trei?


a. p->urm->urm = p; b. dispose(p)
c. p->urm = p->urm->urm; d. p->urm = p
(Bacalaureat Sesiunea iunie-iulie 2004)
TU

25. Nodurile unei liste dublu nlnuite rein n cmpurile info, adp i adu o informaie
numeric, adresa nodului precedent i respectiv adresa nodului urmtor. tiind c lista
este corect construit i c dou noduri p i q ale acesteia se nvecineaz, atunci:
a. p->adp==q->adu b. p->adu==q->adu c. p->adu==q d. p->adp==q->adp
I

(Bacalaureat Simulare 2006)


ED
156 Implementarea structurilor de date

C
26. Dac ntr-o list liniar simplu nlnuit adresa de nceput a listei este p, iar adresa de
sfrit este u, atunci transformarea listei n list circular se realizeaz prin instruciunea:
a. p->urm=u b. p=u->urm c. u->urm=p d. u=p->urm

I
(Bacalaureat Sesiunea iunie-iulie 2004)

OG
27. Se consider o list simplu nlnuit ale crei noduri rein n cmpul urm adresa nodului
urmtor al listei sau NULL dac nu exist un nod urmtor. Pentru inserarea unui nod aflat
la adresa p imediat dup un nod al listei aflat la adresa q, se utilizeaz unele dintre urm-
toarele atribuiri: 1) p->urm=q; 2) q->urm=p; 3) p=q->urm; 4) q=p->urm;

AG
5) p->urm =q->urm; 6) q->urm=p->urm;. Stabilii care dintre acestea se utilizeaz
i n ce ordine:
a. 3 6 b. 2 4 c. 5 2 d. 2 3
(Bacalaureat Simulare 2006)

ED
28. Variabila vf memoreaz adresa elementului din vrful stivei. Fiecare element al stivei
memoreaz ntr-un cmp adr adresa urmtorului element din stiv. Variabila q poate
memora adresa oricrui element al stivei. S se realizeze eliminarea elementului din
vrful stivei:
a. q->adr=vf;vf->adr=q;delete q; b. q=vf->adr;vf=q->adr;delete q;

P
c. q=vf;vf=vf->adr; delete vf; d. q=vf;vf=q->adr; delete q;
(Bacalaureat Simulare 2003)
I
29. O list liniar simplu nlnuit cu adresa de nceput memorat n variabila p este
vid dac:
a. *p==NULL / !*p b. p==NULL / !p
c. p!=NULL / p d. *p!=NULL / *p

(Bacalaureat Sesiunea special 2003)


30. ntr-o list dublu nlnuit cu cel puin 4 elemente, fiecare ele-
IC

q=p->adu->adp;
ment reine n cmpul adp i adu adresa elementului prece-
p=q->adu;
dent i respectiv urmtor din list. Dac p reprezint adresa p->adp=NULL;
primului element din list, iar q este de acelai tip cu p, atunci delete q;
CT

secvena alturat realizeaz:


a. interschimbarea primelor dou componente b. eliminarea primului element
c. eliminarea celui de-al doilea element d. eliminarea ultimului element
(Bacalaureat Sesiunea special 2005)
DA

31. ntr-o list dublu nlnuit cu cel puin 4 elemente, fiecare element reine n cmpul
adp i adu adresa elementului precedent i respectiv urmtor din list. Dac p
reprezint adresa primului element din list, atunci p->adu->adu->adp este
a. adresa primului element b. adresa celui de-al doilea element
DI

c. adresa celui de-al treilea element d. adresa celui de-al patrulea element
(Bacalaureat Simulare 2005)
32. ntr-o list circular simplu nlnuit fiecare element reine n cmpul next adresa
RA

elementului urmtor. tiind c, pentru variabila p ce memoreaz adresa unui element


oarecare din list, este adevrat relaia p->next=p, atunci lista este format din:
a. zero componente b. o component c. 2 componente d. minim 3 componente
(Bacalaureat Sesiunea august-septembrie 2005)
TU

33. Dac vf indic ultimul nod al stivei, care dintre urmtoarele expresii trebuie s fie
adevrate, pentru ca stiva s fie vid?
a. vf==NULL b. vf->urm==0
c. vf->urm==NULL d. vf==0
I
ED
Informatic 157

C
34. Dac vf indic ultimul nod al stivei, iar q un pointer ctre tipul nod, care dintre
urmtoarele secvene de instruciuni extrage nodul din vrful stivei?
a. q=vf->urm;vf=q->urm;delete q; b. q=vf;vf=vf->urm;delete q;

I
c. q=vf;vf=q->urm;delete q; d. q=vf;vf=q->urm;delete q;

OG
35. Dac variabila cap memoreaz adresa primului nod din coad i variabila baza
memoreaz adresa ultimului nod din coad, care dintre urmtoarele expresii trebuie
s fie adevrate, pentru a avea o coad vid?
a. baza==NULL b. cap->urm==baza c. cap==baza d. cap==NULL

AG
Miniproiecte:
Observaie: Pentru realizarea urmtoarelor miniproiecte se va lucra n echip. Profe-
sorul va numi conductorii de proiect, le va distribui proiectele i le va aloca un buget pentru

ED
realizarea lor (pentru simplificare, bugetul va fi folosit numai pentru plata membrilor echipei
care vor realiza proiectul). Conductorii de proiect vor negocia cu profesorul termenul de
predare a aplicaiei, echipa cu care o vor realiza, i, dac este cazul, bugetul care li s-a
alocat iniial. Pe timpul realizrii aplicaiilor, membrii echipelor pot migra de la o echip la

P
alta, cu condiia s rmn ncadrai ntr-una dintre echipe, iar migraia s se fac numai cu
acceptul conductorilor echipelor ntre care migreaz. Fiecare echip va fi format din:
Conductorul proiectului i va forma echipa i va distribui sarcinile pentru fiecare
I
membru, negociind iniial suma repartizat din bugetul alocat pentru realizarea sarcinii. Va
fixa termene de execuie pentru fiecare membru al echipei i va urmri modul n care sunt
respectate aceste termene. n cazul n care unul dintre membrii echipei nu i realizeaz
corect i la timp sarcinile, va redistribui o parte dintre sarcini ntre ceilali membri ai echipei,

renegociind suma din buget alocat fiecruia dintre ei. La sfrit, va da calificative fiecrui
membru al echipei, n funcie de modul n care i-au respectat termenele, de modul n
IC

care au cooperat cu ceilali membrii ai echipei i de calitatea lucrrilor executate.


Analistul va analiza cerinele informaionale ale aplicaiei, va determina funciile apli-
CT

caiei i va elabora modul de rezolvare (datele i structurile de date folosite, procesele


n care este descompus aplicaia care vor fi implementate cu subprograme i
meniul care asigur interfaa cu utilizatorul). n realizarea acestor sarcini va fi ajutat i
ndrumat de conductorul proiectului.
DA

Grupul de programatori (numrul lor trebuie s fie stabilit n funcie de dimensiunea


proiectului) va implementa n limbajul de programare soluia gsit de analistul echipei.
Conductorul proiectului le va repartiza subprogramele pe care le vor realiza i specifica-
iile fiecrui subprogram: datele de intrare, datele de ieire i funcia subprogramului.
DI

Testorul va testa aplicaia. El va trebui s aleag seturi de date de intrare astfel nct
s gseasc erorile de logic i de execuie ale aplicaiei.
Documentaristul va ntocmi documentaiile aplicaiei: documentaia pentru beneficiar
i documentaia pentru proiectantul aplicaiei.
RA

La terminarea proiectului membrii echipelor vor primi note pentru evaluarea activitii lor.
Sistemul de evaluare trebuie s in cont de veniturile realizate pentru munca depus, de
calificativul obinut de la conductorul de proiect i de calitatea muncii evaluat de profesor.
TU

1. Pentru biblioteca colii sunt aduse cri de la mai multe edituri. Crile trebuie organizate
n ordinea alfabetic a autorilor, i pe fiecare autor n ordinea alfabetic a titlurilor. Este
posibil ca pentru acelai autor i acelai titlu s se primeasc mai multe exemplare. Se
va folosi cte o stiv pentru fiecare autor, n care se va simula teancul de titluri primite,
I

pentru fiecare titlu memorndu-se i numrul de exemplare. Numele autorilor i adresa


ED
158 Implementarea structurilor de date

C
vrfului stivei de cri asociate se vor memora ntr-o list ale crei elemente conin n
informaia util dou cmpuri: un cmp de tip ir de caractere pentru numele autorului i
un cmp de tip pointer cte tipul nod al stivei pentru vrful stivei. Scriei o aplicaie care

I
s asigure urmtoarele operaii prin intermediul unui meniu:

OG
a. Distribuirea pe autori i titluri a unui teanc de cri sosit de la o editur.
b. Afiarea titlurilor i a numrului de exemplare ale unui autor al crui nume se citete
de la tastatur.
c. Afiarea n ordine alfabetic a autorilor i a numrului de titluri i de exemplare

AG
pentru fiecare autor.
d. Numele autorilor cu cele mai multe, respectiv cu cele mai puine titluri.
e. Numele autorilor cu cele mai multe, respectiv cu cele mai puine exemplare.
2. La un concurs particip mai muli candidai identificai dup nume i prenume. Fiecare

ED
candidat primete la nscriere un numr de identificare. Concursul const n trei probe,
notele putnd lua valori de la 1 la 10. Rezultatul concursului se stabilete pe baza medi-
ei aritmetice a notelor primite. Trebuie prevzute dou variante de admitere a candida-
ilor: sunt admii toi candidaii care au o medie mai mare dect m i sunt admii, n

P
ordinea mediilor, primii k candidai (valorile pentru m i k se citesc de la tastatur).
Scriei o aplicaie care s asigure urmtoarele operaii prin intermediul unui meniu:
a. nscrierea unui nou candidat la concurs.
I
b. Retragerea unui candidat din concurs.
c. Completarea notelor i calcularea mediei pentru fiecare candidat.
d. Modificarea informaiilor despre un candidat.
e. Afiarea candidailor admii n fiecare dintre cele dou variante n ordinea descres-

ctoare a mediilor.
IC

f. Afiarea candidailor admii n fiecare dintre cele dou variante n ordinea alfabetic
a numelui i prenumelui.
3. ntr-un depou exist o linie pe care se gsesc mai multe locomotive, aranjate n ordinea
CT

n care au intrat n depou, i o linie pe care se


gsesc mai multe vagoane, aranjate n ordinea n
care au intrat n depou. Fiecare locomotiv i ieire
fiecare vagon are un numr de identificare. n plus,
DA

pentru fiecare vagon este precizat i clasa (clasa


1 i clasa 2). Pentru linia care conine locomotivele
exist un triaj cu k linii de manevr. Valoarea
pentru k se citete de la tastatur. n triajul vagoa-
DI

nelor exist o linie de intrare i o linie de ieire pe care depla-


sarea se poate face numai n sensul sgeilor i o linie de
ma-nevr pe care deplasarea se poate face n ambele ieire
sensuri. Scriei o aplicaie care s asigure urmtoarele
RA

operaii prin inter-mediul unui meniu:


a. Intrarea unei locomotive n depou.
b. Afiarea locomotivelor din depou.

c. Intrarea unui vagon n depou.
TU

d. Afiarea vagoanelor din depou, precizndu-se cte


vagoane sunt de clasa 1 i cte sunt de clasa 2.
e. Formarea unei garnituri. Garnitura este format dintr-o
locomotiv cu numrul de iden-tificare p i n vagoane, dintre care m vagoane sunt de
I
ED

clasa 1 (valorile pentru p, n i m se citesc de la tastatur).


Informatic 159

C
2.7. Graful

I
2.7.1. Definiia matematic a grafului

OG
Se numete graf (G) o pereche ordonat de mulimi (X,U), unde X este o mulime finit i
nevid, iar U o mulime de perechi formate cu elemente distincte din mulimea X (familie
de submulimi cu dou elemente din mulimea X).

AG
Terminologie:
Elementele mulimii X se numesc vrfuri sau noduri. Mulimea X se mai numete i
mulimea vrfurilor sau mulimea nodurilor grafului G. Ea este de forma:

ED
X = {x1, x2, x3, ..., xi, ..., xn}
unde xi reprezint nodul i al grafului G care are n noduri.
Ordinul grafului reprezint numrul de noduri ale grafului, n:

P
ordinul grafului = card(X) = n
Elementele mulimii U sunt perechi de noduri, adic submulimi cu dou elemente din
I
mulimea X i se noteaz cu uk. Elementul uk este definit de perechea de forma {xi, xj},
unde xi, xj X i xixj (elemente distincte din mulimea X). Elementul uk leag nodurile xi
i xj i se noteaz astfel: [xi, xj]. Mulimea U este de forma:

U={u1, u2, u3, ..., uk, ..., um}


Clasificarea grafurilor:
IC

Criteriul de clasificare folosit este proprietatea de simetrie a mulimii U.


Mulimea U are proprietatea de simetrie dac i numai dac,
CT

pentru orice pereche de noduri (xi, xj), dac {xi, xj}U, atunci i {xj, xi}U
n funcie de proprietatea de simetrie, grafurile se clasific n:
Grafuri neorientate. Un graf G=(X,U) este un graf neorientat dac mulimea U are
DA

proprietatea de simetrie. Mulimea U este format din perechi neordonate {xj, xi}.
Grafuri orientate. Un graf G=(X,U) este un graf orientat dac mulimea U nu are
proprietatea de simetrie. Mulimea U este format din perechi ordonate {xj, xi}.
Pentru a identifica tipul de graf pe care l vei folosi pentru a reprezenta datele, definii rela-
DI

ia dintre nodurile grafului i verificai dac relaia are proprietatea de simetrie, astfel:
Dac nodul x n relaie cu nodul y implic i c nodul y este n relaie cu nodul x, atunci
graful este neorientat.
RA

Dac nodul x n relaie cu nodul y nu implic i c nodul y este n relaie cu nodul x,


atunci graful este orientat.
TU

Scop: identificarea tipului de graf pe care l folosii pentru a rezolva problema.


Enunul problemei 1. Pe harta unui jude exist mai multe localiti care sunt legate prin
osele pe care se circul n ambele sensuri. S se identifice traseele pe care se poate
I

ajunge de la localitatea A la localitatea B.


ED
160 Implementarea structurilor de date

C
Nodurile grafului sunt localitile. Relaia care se stabilete ntre nodurile grafului este:
nodul x este n relaie cu nodul y, dac exist o osea care leag direct localitatea asociat
nodului x cu localitatea asociat nodului y. Relaia are proprietatea de simetrie, deoarece

I
oseaua care leag direct localitatea asociat nodului x cu localitatea asociat nodului y

OG
leag direct i localitatea asociat nodului y cu localitatea asociat nodului x. Pentru
reprezentarea cilor de comunicaie dintre localiti se va folosi un graf neorientat.
Enunul problemei 2. Pe harta unui cartier exist mai multe intersecii care sunt legate
de strzi. Pe unele strzi se poate circula n ambele sensuri, pe alte strzi numai ntr-un

AG
anumit sens. S se identifice traseele prin care se poate ajunge de la intersecia A la
intersecia B.
Nodurile grafului sunt interseciile. Relaia care se stabilete ntre nodurile grafului este: nodul
x este n relaie cu nodul y, dac exist trafic care leag direct intersecia asociat nodului x

ED
cu intersecia asociat nodului y (se poate circula de la nodul x la nodul y). Relaia nu are
proprietatea de simetrie deoarece, dac exist o strad care leag direct intersecia asociat
nodului x cu intersecia asociat nodului y i pe aceast strad exist trafic de la nodul x la
nodul y, nu este obligatoriu ca pe acea strad s existe trafic i de la nodul y la nodul x.

P
Pentru reprezentarea traficului auto dintre intersecii se va folosi un graf orientat.
Enunul problemei 3. La nivelul unui grup de persoane se face un studiu social. ntre
persoane se stabilesc relaii de prietenie, dar i relaii de simpatie. S se descrie cu
I
ajutorul grafului relaiile dintre persoane.
Nodurile grafului sunt membrii grupului de persoane. ntre persoane se pot stabili relaiile:
Relaia de prietenie este o relaie definit astfel: persoana x este n relaie cu persoana

y, dac este prieten cu ea. Relaia este simetric deoarece, dac persoana x este
prieten cu persoana y, atunci i persoana y este prieten cu persoana x (relaia de
IC

prietenie presupune reciprocitate). Pentru reprezentarea relaiilor de prietenie dintre


membrii grupului se va folosi un graf neorientat.
Relaia de simpatie este o relaie definit astfel: persoana x este n relaie cu persoana
CT

y, dac o simpatizeaz. Relaia nu este simetric deoarece, dac persoana x


simpatizeaz persoana y, nu este obligatoriu ca persoana y s simpatizeze persoana x
(relaia de simpatie nu presupune reciprocitate). Pentru reprezentarea relaiilor de
DA

simpatie dintre membrii grupului se va folosi un graf orientat.


1. Prin ce tip de graf va fi reprezentat un grup de persoane ntre care
Tem s-au stabilit relaii de vecintate?
2. Prin ce tip de graf va fi reprezentat un grup de persoane ntre
DI

care s-au stabilit relaii de cunotin?

2.7.2. Graful neorientat


RA

2.7.2.1. Terminologie
Elementele mulimii U (perechile de noduri) se numesc muchii. Mulimea U se mai
numete i mulimea muchiilor grafului G. O muchie, fiind un element din mulimea U,
TU

este determinat de o submulime cu dou elemente din mulimea X: muchia k a


grafului (uk), care unete nodurile xi i xj, este determinat de submulimea {xi, xj} i se
noteaz cu [xi, xj]. [xi, xj] i [xj, xi] reprezint aceeai muchie a grafului. Graful G are
m muchii:
I
ED

numrul de muchii = card(U) = m


Informatic 161

C
Numim noduri adiacente orice pereche de noduri care formeaz o muchie {xi,xj}U.
Fiecare dintre cele dou noduri (xi i xj) este nod incident cu muchia uk = [xi,xj].
Nodurile vecine unui nod xi sunt toate nodurile xj care sunt adiacente cu el.

I
Se numete nod extrem al unei muchii oricare dintre cele dou noduri care se gsesc

OG
la captul muchiei. Nodurile xi i xj sunt extremitile muchiei [xi, xj].
Se numesc muchii incidente dou muchii ui i uj care au o extremitate comun
nodul xk.
Un graf neorientat G este definit de o pereche de mulimi:

AG
mulimea nodurilor sale X i mulimea muchiilor sale U. El poate fi considerat ca
o mulime de noduri din care unele pot fi unite dou cte dou printr-o muchie.
Graful se reprezint n plan prin intermediul unor elemente geometrice: nodurile se
reprezint prin cercuri, iar muchiile prin linii drepte care unesc anumite cercuri.

ED
Nodul xi al grafului G

Muchia uk=[xi,xj] a grafului G

Nodul xj al grafului G
P
I
Elementele mulimii X (nodurile) se identific cu ajutorul unor etichete, care pot fi numere
sau litere. Pentru simplificare, vom folosi ca etichete un ir de numere consecutive,
ncepnd cu numrul 1. De exemplu, pentru un graf cu n noduri, vom folosi etichetele: 1, 2,
3, , n-1, n. O muchie se va nota cu [i,j], unde i i j sunt etichetele nodurilor incidente cu

muchia. De exemplu, muchia [2,3] este muchia care unete nodurile cu etichetele 2 i 3.
IC

Exemplul 1:
n graful G1=(X1,U1) din figura 1: G
G
G111
Ordinul grafului este 8.
CT

Graful are 8 noduri (n=8) i mulimea nodurilor este


X1={1,2,3,4,5,6,7,8}.
Graful are 9 muchii (m=9) i mulimea muchiilor este Fig. 1
DA

U1={[1,2], [1,3], [1,4], [2,3], [2,5], [3,4], [3,5], [6,7], [6,8] }.


Nodul 1 este nod adiacent cu nodurile 2, 3 i 4, iar nodul 6 este adiacent cu nodurile 7
i 8. Nodurile 3 i 4 sunt adiacente deoarece perechea de noduri [3,4]U1. Nodurile 5 i
6 nu sunt adiacente deoarece perechea de noduri [5,6]U1.
DI

Nodul 5 este nod incident cu muchiile [2,5] i [3,5], dar nu este incident cu muchia [1,2].
Nodul 3 este nod extrem muchiilor [1,3], [2,3], [3,4] i [3,5].
Muchiile [1,2] i [2,3] sunt muchii incidente deoarece au un nod comun (nodul 2).
Muchiile [1,4] i [2,3] nu sunt muchii incidente deoarece nu au un nod comun.
RA

Teorema 1
Dac graful neorientat G are n noduri (x1, x2, ..., xn), atunci numrul total de grafuri
neorientate care se pot forma cu aceste noduri este g:
TU

2
Cn
g2
Demonstraie. Notm cu X mulimea nodurilor grafului, cu U mulimea muchiilor, cu A mulimea
tuturor submulimilor de dou elemente din X i cu B mulimea {0,1}. Mulimea A are urmtoarele
I

elemente (submulimi):
ED
162 Implementarea structurilor de date

C
[1,2],
[1,3], [1,4], , [1,n] n-1 submulimi
[2,3], [2,4], , [2,n] n-2 submulimi

I
[n-1,n] 1 submulime

OG
n (n 1)
Numrul total de submulimi este: (n 1) (n 2) ... 1 C n2
2
Notm cu a card(A) i cu b card(B). Fiecrui graf i putem asocia o 1, dac [x,y] U
funcie f:AB definit alturat. Invers, unei funcii f:AB i putem f(x,y) =

AG
ataa un graf, astfel: f(x,y)=1 dac i numai dac [x,y]U. Rezult 0, dac [x,y] U
c numrul total de grafuri care se pot forma cu n noduri este egal cu
a
numrul de funcii f. Dar, numrul de funcii f:AB este egal cu b , unde b=2 i a= C n2

ED
1. n graful G1 cu ce noduri este adiacent nodul 1?
Tem 2. n graful G1 cu ce muchii este incident nodul 1?
3. Dai exemple de dou noduri adiacente i de dou noduri care nu
sunt adiacente n graful G1.

P
4. Dai exemplu de dou muchii incidente i de dou muchii care nu sunt incidente n
graful G1.
G
G
G222 5. Desenai graful G2=(X2, U2) definit astfel:
I
X2={1,2,3,4,5,6,7,8}
U2={[1,2], [1,3], [1,5], [2,3], [2,5], [3,4], [4,5], [4,6], [4,7] }.
6. Desenai graful traseelor rutiere care fac legtura ntre localitile Braov, Bucureti,
Buzu, Ploieti i Constana. Dac exist mai multe trasee rutiere ntre dou localiti

(de exemplu, Bucureti i Braov), adugai la graf noduri pentru localitile care
IC

identific unic aceste trasee (de exemplu, Vlenii de Munte, Trgovite i Piteti).
7. Desenai graful judeelor din Romnia (ntre dou judee exist o muchie dac cele
dou judee sunt nvecinate).
CT

8. Cte grafuri se pot construi cu 3 muchii? Desenai toate grafurile care


se pot construi cu 3 muchii.
G
G
G333 9. Pentru graful G3 din figura 2, precizai ordinul, numrul de noduri,
numrul de muchii i mulimile X3 i U3.
DA

10. Structura unei molecule de substan chimic poate fi reprezentat Fig. 2


printr-un graf neorientat, n care nodurile sunt atomii i gruprile din
care este compus molecula, iar muchiile sunt legturile dintre ele.
n figura 3 este prezentat graful moleculei de ap H2O. Repre-
DI

zentai grafurile moleculelor de H2SO4, NH3, CH4 i C2H4.

2.4.2.2. Gradul unui nod al grafului neorientat Fig. 3


RA

Nodul unui graf este caracterizat prin grad.


Gradul unui nod xk al grafului G este egal cu numrul muchiilor incidente
cu nodul i se noteaz cu d(xk).
TU

Terminologie:
Se numete nod terminal un nod care are gradul egal cu 1 d(xk) = 1 (este incident
cu o singur muchie).
Se numete nod izolat un nod care are gradul egal cu 0 d(xk) = 0 (nu este adiacent
I

cu nici un alt nod al grafului, adic nu se gsete n extremitatea nici unei muchii).
ED
Informatic 163

C
Exemplul 1:
G
G
G444
Graful G4=(X4,U4) din figura 4 este definit astfel:
X4={1,2,3,4,5,6,7,8,9,10,11}

I
U4={[1,2], [1,4], [2,3], [2,5], [3,4], [3,5], [5,6], [5,7], [5,8],

OG
[7,9] }. Fig. 4
n graful G4:
Gradul nodului 5 este 5, deoarece are 5 muchii incidente: [2,5], [3,5], [5,6], [5,7] i [5,8].
Nodul 9 este nod terminal, deoarece are gradul 1 (o singur muchie incident: [7,9]).

AG
Nodul 10 este nod izolat, deoarece are gradul 0 (nicio muchie incident).
Exemplul 2:
Fie graful G5=(X5,U5), unde X5={1,2,3,4,5,6,7,8} i U5={[1,2], [1,5], [2,3], [2,5], [3,4], [3,5], [4,5], G
G
G555

ED
[4,6], [4,7]}. Din lista muchiilor unui graf neorientat, putei preciza urmtoarele informaii:
Determinai gradul unui nod numrnd de cte ori apare eticheta nodului n lista de mu-
chii. Nodul 5 are gradul 3 (n mulimea muchiilor, eticheta 5 apare de 3 ori: [1,5], [2,5], [3,5]).
Determinai dac un nod este terminal verificnd dac eticheta lui apare o singur

P
dat. Nodul 7 este nod terminal (eticheta lui apare numai ntr-o singur muchie: [4,7]).
Determinai dac un nod este izolat verificnd dac eticheta lui nu apare n lista de
muchii. Nodul 8 este nod izolat (eticheta lui nu apare n lista muchiilor).
I
Determinai numrul de noduri izolate (n1) astfel: numrai etichetele distincte care
apar n lista muchiilor (n2) i n1=n-n2. n graful G5, n lista de muchii exist 7 etichete
distincte. Numrul de noduri izolate este 1 (8-7).

Observaie: ntr-un graf cu n noduri, oricare ar fi nodul xk, gradul su este mai mare sau
egal cu 0 i mai mic sau egal cu n-1 (0d(xk)n-1).
IC

1. n graful G4: precizai gradul nodului 3 i identificai nodul cu gradul cel


Tem mai mare, nodurile izolate i nodurile terminale.
CT

2. n graful G3: identificai nodurile care au gradul 2, precizai cte noduri


au gradul impar i care este nodul cu gradul cel mai mare.
3. n graful G5: precizai gradul nodului 3, identificai nodurile izolate i nodurile terminale,
precizai cte noduri au gradul 2 i cte noduri au gradul impar.
DA

Teorema 2
Dac graful G are m muchii (u1, u2, ..., um) i n noduri (x1, x2, ..., xn), atunci ntre gradul
nodurilor i numrul de muchii exist urmtoarea relaie: suma gradelor tuturor nodurilor
DI

grafului este egal cu dublul numrului de muchii:


n
d(x i ) 2 m
i 1
RA

Demonstraie. Fiecare muchie uk = [xi, xj] corespunde unei uniti din gradul nodului xi i unei uniti
din gradul nodului xj. Rezult c fiecare muchie contribuie cu 2 uniti la suma gradelor.
Exemplu. n graful G4: d(1) + d(2) + d(3) + d(4) + d(5) + d(6) + d(7) + d(8) + d(9) + d(10) +
d(11) = 2+2+3+2+4+1+2+1+1+0+0 = 18 = 29 = 2m
TU

Propoziia 1. Pentru orice graf G, numrul nodurilor de grad impar este par.
Demonstraie. Suma gradelor nodurilor fiind un numr par, aceast sum trebuie s conin un
numr par de termeni care sunt numere impare.
I

Exemplu. n graful G3 exist 4 noduri cu grad impar (3, 6, 8 i 9).


ED
164 Implementarea structurilor de date

C
Propoziia 2. Numrul minim de muchii, mmin, pe care trebuie s le aib un graf neorientat,
cu n noduri, ca s nu existe noduri izolate, este:
n 1
m min

I

2

OG
Demonstraie. Pentru ca un nod xi s nu fie izolat, trebuie ca d(xi)1. Pentru ca toate nodurile s nu
fie izolate, trebuie ca suma gradelor s fie mai mare sau egal cu n. Dar, suma gradelor este dublul
numrului de muchii m. nseamn c, pentru n par mmin=n/2, iar pentru n impar mmin=(n+1)/2.
Teorema 3

AG
Dac graful G are n noduri (n2), atunci cel puin dou noduri au acelai grad.
Demonstraie prin reducere la absurd. Presupunem c nu este adevrat. Cum, oricare ar fi nodul
xk, 0d(xk)n-1, nseamn c singurul ir de n numere, diferite ntre ele dou cte dou, care pot

ED
reprezenta gradele unghiurilor este 0, 1, 2, , n-1. Deoarece un nod este izolat, cel mai mare grad al
unui nod nu poate fi dect n-2 (nodul nu se poate lega de el nsui i de nodul izolat). Rezult c irul
de numere definit mai sus (singurul ir care se poate defini) nu poate reprezenta irul gradelor n graf.
1. n graful G1 verificai c este ndeplinit relaia dintre gradul nodurilor

P
Tem i numrul de muchii ale grafului. Identificai nodurile cu grad impar i
verificai c numrul lor este par.
2. Dac un graf are 8 noduri, care este numrul minim de muchii pe care trebuie s le
I
aib, ca s nu fie noduri izolate. Desenai un graf care, avnd numrul minim de muchii
stabilit, nu conine noduri izolate. Dac un graf are 9 noduri, care este numrul minim de
muchii pe care trebuie s le aib, ca s nu fie noduri izolate. Desenai un graf care

avnd numrul minim de muchii stabilit nu conine noduri izolate.


IC

2.7.2.3. irul grafic


Se numete ir grafic un ir s de n numere ntregi pozitive (d1, d2, ..., dn) care pot
CT

reprezenta gradele unui graf neorientat, cu n noduri.


Propoziia 3
Condiiile necesare ca un ir de n numere ntregi pozitive (d1, d2, ..., dn)
DA

s fie un ir grafic sunt:


(1) di n-1, pentru orice i=1,n;
(2) suma d1 + d2 + ... + dn trebuie s fie un numr par.
Demonstraie. Necesitatea condiiei (1) rezult din faptul c gradul maxim al unui nod dintr-un graf cu
DI

n noduri poate fi n-1. Necesitatea condiiei (2) rezult din Teorema 2 suma gradelor fiind egal cu
dublul numrului de muchii, este un numr par.
Aceste condiii nu sunt ntotdeauna i suficiente. Pentru a verifica dac irul de
RA

numere este ir grafic, se face analiza irului de numere.


Exemple:
(a) s=(1,1,2,3,3,4,5,5,7,8)
Acest ir nu ndeplinete una dintre condiiile necesare (2) suma numerelor este 39.
TU

(b) s=(1,1,1,2,2,3,5,6,8,9)
Acest ir ndeplinete condiiile necesare (suma numerelor este 38 i fiecare numr este
mai mic sau egal cu 9: 9=10-1). Aceste condiii nu sunt ns suficiente. Din analiza irului
rezult c nodul 10, avnd gradul 9, este legat de toate celelalte 9 noduri. Nodurile 1, 2 i
I

3 sunt noduri terminale. Ele nu pot fi legate dect de nodul 10. Rezult c gradul maxim
ED
Informatic 165

C
pe care l poate avea oricare dintre celelalte ase noduri este 6 (ele nu se pot lega de ele
nsele i de nodurile 1, 2 i 3). Dar nodul 9 are gradul 8, ceea ce este imposibil.
(c) s=(1,1,1,2,3,4,5,6,6,9)

I
i acest ir ndeplinete condiiile necesare (suma numerelor este 38 i fiecare numr

OG
este mai mic sau egal cu 9). n plus, fa de irul (b), avnd aceleai grade pentru
nodurile 1, 2, 3 i 10, ndeplinete i condiia ca celelalte noduri s aib gradul mai mic
sau egal cu gradul maxim posibil (6). Dar, exist dou noduri cu gradul 6. Ele trebuie s
se lege amndou de nodul 4, la care este legat i nodul 10. Nodul 4 trebuie s aib cel

AG
puin gradul 3. Dar nodul 4 are gradul 2, ceea ce este imposibil.
(d) s=(1,1,1,3,3,4,4,5,5,9)
Acest ir ndeplinete condiiile necesare (suma numerelor este 38 i fiecare numr este
mai mic sau egal cu 9) i este un ir grafic cruia i se poate asocia graful G6=(X6,U6), cu G G
G666
18 muchii, definit astfel:

ED
X6={1,2,3,4,5,6,7,8,9,10}
U6={[1,10], [2,10], [3,10], [4,8], [4,9], [4,10], [5,8], [5,9], [5,10], [6,7], [6,8], [6,9], [6,10],
[7,8], [7,9], [7,10], [8,10], [9,10]}.

P
Precizai dac irurile s1=(1,1,2,2,4) i s2=(0,1,1,1,4) pot fi iruri grafice.
Tem Pentru irul care este ir grafic, gsii un graf care i se poate asocia.
I
2.7.3. Graful orientat
Spre deosebire de graful neorientat, n graful orientat perechile de noduri sunt ordonate.

Graful orientat se mai numete i digraf.


IC

2.7.3.1. Terminologie
Elementele mulimii U (perechile de noduri) se numesc arce. Mulimea U se mai nume-
te i mulimea arcelor grafului G. Un arc, fiind un element din mulimea U, este
CT

determinat de o submulime ordonat, cu dou elemente, din mulimea X: arcul k al


grafului (uk), ce unete nodurile xi i xj, este determinat de submulimea {xi,xj} i se
noteaz cu [xi, xj]. [xi, xj] i [xj, xi] nu reprezint acelai arc al grafului. Graful G are
DA

m arce:
numrul de arce = card(U) = m
Se numesc noduri adiacente n graful G oricare din perechile de noduri care formeaz
un arc (xi,xj)U sau (xj,xi)U. Fiecare dintre cele dou noduri (xi i xj) este nod
DI

incident cu arcul uk = [xi, xj] sau cu arcul uk = [xj, xi].


Nodurile xi i xj sunt extremitile arcului [xi, xj]. Nodul xi este extremitatea iniial a
arcului, iar nodul xj este extremitatea final a arcului.
RA

Se numesc arce incidente dou arce ui i uj care au o extremitate comun nodul xk.
Se numete succesor al nodului xi orice nod la care ajunge un arc care iese din nodul
xi. Mulimea succesorilor nodului xi este format din mulimea nodurilor la care ajung
arcele care ies din nodul xi. Se noteaz cu S(xi) i se definete ca mulimea:
TU

S(x) = {xj X(xi, xj)U}.


Se numete predecesor al nodului xi orice nod de la care intr un arc n nodul xi.
Mulimea predecesorilor nodului xi este format din mulimea nodurilor de la care
ajung arcele care intr n nodul xi. Se noteaz cu P(xi) i se definete ca mulimea:
I

P(x) = {xj X(xj, xi)U}.


ED
166 Implementarea structurilor de date

C
Mulimea arcelor care ies din nodul xi se noteaz cu U+(xi) i se definete ca mulimea
U+(xi) = {u=(xi, xj)uU}.
Mulimea arcelor care intr n nodul xi se noteaz cu U-(xi) i se definete ca muli-

I
mea U-(xi) = {u=(xj, xi)uU}.

OG
Nodul surs al grafului este nodul care are mulimea succesorilor format din toate
celelalte noduri, mai puin el, iar mulimea predecesorilor si este mulimea vid.
Nodul destinaie al grafului este nodul care are mulimea predecesorilor format din
toate celelalte noduri, mai puin el, iar mulimea succesorilor si este mulimea vid.

AG
Observaii
1. card(S(x))=card(U+(x)) i card(P(x))=card(U-(x)).
2. Pentru nodul surs al grafului card(S(x))=card(X)-1 i card(P(x))=0.

ED
3. Pentru nodul destinaie al grafului card(P(x))=card(X)-1 i card(S(x))=0.
4. Dac un graf are un nod surs, atunci nu poate avea un nod destinaie, i invers.
Un graf orientat G este definit de o pereche de mulimi: mulimea nodurilor sale X
i mulimea arcelor sale U. El poate fi considerat ca o mulime de noduri din care

P
unele pot fi unite dou cte dou, prin unul sau dou arce.
Graful orientat se reprezint n plan prin intermediul unor elemente geometrice: nodurile
I
se reprezint prin cercuri, iar arcele prin linii drepte care unesc anumite cercuri i care au o
sgeat la captul care corespunde extremitii finale a arcului.
Nodul xi al grafului G

Arcul uk=[xi,xj] al grafului G


IC

Nodul xj al grafului G
CT

Exemplu:
G
G
G777 n graful G7=(X7,U7) din figura 5:
Ordinul grafului este 5.
Graful are 5 noduri (n=5) i mulimea nodurilor este X7={1,2,3,4,5}.
DA

Graful are 7 arce (m=7) i mulimea arcelor este U7={[1,2], [1,4],


Fig. 5
[2,3], [4,1], [4,3], [5,2], [5,3] }.
Nodul 1 este nod adiacent cu nodurile 2 i 4, iar nodul 3 este adiacent cu nodurile 2, 4
i 5. Nodurile 3 i 4 sunt adiacente deoarece perechea de noduri [4,3]U7. Nodurile 5 i
DI

4 nu sunt adiacente, deoarece nici una dintre perechile de noduri [4,5] i [5,4] U7.
Nodul 4 este nod incident cu arcele [1,4], [4,1] i [4,3], dar nu este incident cu arcul [1,2].
Nodul 2 este extremitatea iniial a arcului [2,3] i extremitatea final a arcului [1,2] i
[5,2].
RA

Arcele [1,2] i [5,2] sunt arce incidente deoarece au un nod comun (nodul 2). Arcele
[1,4] i [2,3] nu sunt arce incidente, deoarece nu au un nod comun.
Mulimea succesorilor nodului 1 este format din nodurile 2 i 4. Nodul 2 este nod
TU

succesor al nodului 1, dar i al nodului 5. Nodul 1 este nod succesor al nodului 4, dar i
nodul 4 este nod succesor al nodului 1. Nodul 3 nu are succesori.
Mulimea predecesorilor nodului 3 este format din nodurile 2, 4 i 5. Nodul 2 este
nod predecesor al nodului 3. Nodul 1 este nod predecesor al nodului 4, dar i nodul 4
I

este nod predecesor al nodului 1. Nodul 5 nu are predecesori.


ED
Informatic 167

C
Teorema 4
Dac graful orientat G are n noduri (x1, x2, ..., xn), atunci numrul total de grafuri
orientate care se pot forma cu aceste noduri este g:

I
OG
n ( n 1 )
g4 2

3, dac [x,y] U i [y,x] U


Demonstraie. Se demonstreaz la fel ca Teorema 1,
2, dac [x,y] U
cu deosebirea c mulimea B este {0,1,2,3}

AG
f(x,y) =
card(B)=4, iar funcia f este definit alturat.
1, dac [y,x] U
0, dac [x,y] U i [y,x] U

Tem 1. n graful G7 cu ce noduri este adiacent nodul 2?

ED
2. n graful G7 cu ce arce este incident nodul 2?
3. Dai exemplu de dou noduri adiacente n graful G7.
4. Dai exemplu de dou noduri care nu sunt adiacente n graful G7.
5. Dai exemplu de dou arce incidente n graful G7.

P
6. Dai exemplu de dou arce care nu sunt incidente n graful G7.
7. n graful G7 precizai ce fel de extremitate este nodul 4 pentru fiecare arc cu care este
I
incident. Precizai mulimea succesorilor i mulimea predecesorilor nodului 4.
8. Desenai graful G8=(X8,U8), definit astfel. G
G
G888
X8={1,2,3,4,5,6,7}
U8={[1,2], [1,5], [2,1], [2,4], [3,4], [4,3], [5,3], [6,5], [6,7], [7,5] }.

9. Cte grafuri orientate se pot construi cu 3 arce?


Desenai 10 dintre aceste grafuri.
IC

10. Pentru graful G9 din figura 6, precizai ordinul, numrul de G


GG999
noduri, numrul de arce i mulimile X9 i U9.
CT

2.7.3.2. Gradele unui nod al grafului orientat Fig. 6

Nodul unui graf orientat este caracterizat prin gradul intern i gradul extern.
DA

Gradul intern al unui nod xi al grafului G este egal cu numrul arcelor care intr n nodul
-
xi (arce de forma [xj, xi]) i se noteaz cu d (x).
Gradul extern al unui nod xi al grafului G este egal cu numrul arcelor care ies din nodul
xi (arce de forma [xi, xj]) i se noteaz cu d+(x).
DI

Terminologie:
Se numete nod terminal un nod care are suma gradelor egal cu 1 (gradul intern sau
gradul extern egal cu 1 i gradul extern, respectiv gradul intern, egal cu 0 d+(xk) = 1 i
- -
d (xk) = 0 sau d (xk) = 1 i d+(xk) = 0). Nodul terminal este incident cu un singur arc.
RA

Se numete nod izolat un nod care are suma gradelor egal cu 0 (gradul intern i
-
gradul extern egale cu 0 d+(xk) = d (xk) = 0). Nodul izolat nu este adiacent cu nici un
alt nod al grafului, adic nu se gsete la extremitatea niciunui arc.
TU

Observaii:
-
1. d+(x)=card(S(x)) i d (x)=card(P(x)).
-
2. Dac graful are n noduri, pentru un nod surs al grafului d+(x)=n-1 i d (x)=0, iar
- +
pentru un nod destinaie al grafului d (x)=n-1 i d (x)=0.
I
ED
168 Implementarea structurilor de date

C
Exemplul 1:
G
G
G111000 Graful G10=(X10,U10) din figura 7 este definit astfel:
X10={1,2,3,4,5,6,7,8,9,10}

I
U10={[1,2], [1,4], [2,1], [2,3], [2,5], [2,6], [2,7], [4,1],

OG
[7,2], [8,9], [9,8] }.
n graful G10: Fig. 7
Gradul intern al nodului 2 este 2, deoarece are 2 arce
care intr: [1,2] i [7,2]. Gradul extern al nodului 2 este 4, deoarece are 4 arce care ies:

AG
[2,1], [2,3], [2,5] i [2,7].
Nodul 5 este nod terminal deoarece are suma gradelor egal cu 1 (gradul intern este 1
i gradul extern este 0) i un singur arc incident: [2,5]).
Nodul 10 este nod izolat, deoarece are gradul 0 (niciun arc incident).

ED
Exemplul 2:
G
G
G111111 Fie graful G11=(X11,U11), unde X11={1,2,3,4,5,6,7,8} i U11={[1,2], [1,5], [2,1], [2,3], [2,5],
[3,4], [3,5], [4,3], [4,5], [4,6], [4,7], [5,4]}. Din lista arcelor unui graf orientat, putei preciza

P
urmtoarele informaii:
Gradul extern al unui nod numrnd de cte ori apare eticheta nodului n lista de
arce, ca prim element din pereche. Nodul 3 are gradul extern 2 (n mulimea arcelor,
I
eticheta 3 apare de 2 ori ca prim element: [3,4] i [3,5]).
Gradul intern al unui nod numrnd de cte ori apare eticheta nodului n lista de
arce, ca al doilea element din pereche. Nodul 5 are gradul 4 (n mulimea arcelor,
eticheta 5 apare de 4 ori ca al doilea element: [1,5], [2,5], [3,5] i [4,5]).

Mulimea succesorilor unui nod este format din nodurile a cror etichet apare ca al
doilea element n perechile n care primul element este nodul precizat. Mulimea
IC

succesorilor nodului 4 este {3, 5, 6, 7} arcele: [4,3], [4,5], [4,6] i [4,7].


Mulimea predecesorilor unui nod este format din nodurile a cror etichet apare ca
CT

prim element n perechile n care al doilea element este nodul precizat. Mulimea
predecesorilor nodului 3 este {2, 4} arcele: [2,3] i [4,3].
Exemplul 3
G
G
G111222 Fie grafurile G12=(X12,U12), unde X12={1,2,3,4} i U12={[1,2], [1,3], [1,4] [2,3], [3,4], [4,3]}, i
DA

G13=(X13,U13), unde X13={1,2,3,4} i U13={[2,1], [2,3], [3,1], [3,4], [4,1], [4,3]}. Din lista
G
G
G111333 muchiilor unui graf, putei preciza urmtoarele informaii:
Nodul surs al unui graf apare pe primul loc din pereche de n-1 ori i niciodat pe
locul al doilea. n graful G12, nodul 1 este nod surs. Desenai graful G12 pentru a
DI

verifica aceast afirmaie.


Nodul destinaie al unui graf apare pe al doilea loc din pereche de n-1 ori i niciodat
pe primul loc. n graful G13, nodul 1 este nod destinaie. Desenai graful G13 pentru a
RA

verifica aceast afirmaie.


Observaie: ntr-un graf cu n noduri, oricare ar fi nodul xk, oricare dintre gradele sale este
-
mai mare sau egal cu 0 i mai mic sau egal cu n-1 (0d+(xk) n-1 i 0d (xk) n-1).
TU

1. n graful G9 precizai gradul intern i gradul extern ale nodului 5,


Tem identificai nodul cu gradul extern cel mai mare i nodurile cu gradul
intern cel mai mic.
2. n graful G10 identificai nodurile care au gradul intern 1, precizai cte noduri au gradul
I

intern egal cu gradul extern, care sunt nodurile terminale i care sunt nodurile izolate.
ED
Informatic 169

C
3. n graful G11 precizai gradul intern i gradul extern ale nodului 4, identificai nodurile
izolate i nodurile terminale, identificai nodurile care au gradul extern maxim i nodurile
care au gradul intern egal cu gradul extern.

I
OG
Teorema 5
Dac graful orientat G are m arce (u1, u2, ..., um) i n noduri (x1, x2, ..., xn), atunci ntre
gradele nodurilor i numrul de muchii exist urmtoarea relaie: suma gradelor interne
ale tuturor nodurilor este egal cu suma gradelor externe ale tuturor nodurilor i cu

AG
numrul de arce:
n n
d (xi ) d (xi ) m
i 1 i 1

Demonstraie. Fiecare arc uk = [xi, xj] corespunde unei uniti din gradul extern al nodului xi i unei

ED
uniti din gradul intern al nodului xj. Rezult c fiecare arc contribuie cu o unitate la suma gradelor
interne i cu o unitate la suma gradelor externe.
Exemplu. n graful G9: d+(1) + d+(2) + d+(3) + d+(4) + d+(5) + d+(6) = 1+3+1+2+2+1 = 10 i
- - - - - -
d (1) + d (2) + d (3) + d (4) + d (5) + d (6) = 1+2+2+2+2+1 = 10, m fiind egal cu 10.

Tem i numrul de arce ale grafului.


P
n graful G11 verificai c este ndeplinit relaia dintre gradurile nodurilor
I
2.7.4. Reprezentarea i implementarea grafului

Exist mai multe moduri de reprezentare la nivel logic a unui graf, care pot fi implementate n
memoria unui calculator, folosind diverse tipuri de structuri de date. Aceste reprezentri pot fi
IC

folosite n algoritmii care prelucreaz grafuri i, implicit, n programele prin care vor fi imple-
mentai n calculator aceti algoritmi. Printre modurile de reprezentare a unui graf se numr:
reprezentarea prin matricea de adiacen;
CT

reprezentarea prin matricea de inciden;


reprezentarea prin lista muchiilor (arcelor);
reprezentarea prin lista de adiacen (listele vecinilor);
DA

reprezentarea prin matricea costurilor.


Fiecare reprezentare prezint avantaje n ceea ce privete utilizarea eficient a memoriei
interne, n funcie de tipul grafului (cu noduri puine, dar cu muchii multe sau cu noduri
multe, dar cu muchii puine) i din punct de vedere al eficienei algoritmilor de prelucrare
DI

(n funcie de aplicaie). n urmtoarele reprezentri se consider c graful G=(X,U) are n


noduri i m muchii.

2.7.4.1. Reprezentarea prin matricea de adiacen


RA

Matricea de adiacen a unui graf este o matrice ptrat binar de ordinul n (An,n),
ale crei elemente ai,j sunt definite astfel:
1, dac [i, j] U
TU

a i, j 0, dac [i, j] U

Implementarea grafului prin matricea de adiacen se face printr-un tablou bidimensional
(o matrice ptrat cu dimensiunea n), astfel:
I
ED

int a[<n>][<n>];
170 Implementarea structurilor de date

C
Exemple:
Graful neorientat G1
1 2 3 4 5 6 7 8 Graful orientat G9

I
1 0 1 1 1 0 0 0 0 1 2 3 4 5 6

OG
2 1 0 1 0 1 0 0 0 1 0 1 0 0 0 0
3 1 1 0 1 1 0 0 0 2 1 0 1 1 0 0
4 1 0 1 0 0 0 0 0 3 0 0 0 0 1 0
4 0 1 0 0 1 0

AG
5 0 1 1 0 0 0 0 0
6 0 0 0 0 0 0 1 1 5 0 0 1 0 0 1
7 0 0 0 0 0 1 0 0 6 0 0 0 0 1 0
8 0 0 0 0 0 1 0 0

ED
Proprietile matricei de adiacen:
1. Elementele de pe diagonala principal au valoarea 0 din definiia grafului rezult c
orice muchie (arc) [i, j] trebuie s respecte condiia ij.

P
2. n cazul unui graf neorientat, matricea de adiacen este o matrice simetric fa de
diagonala principal, deoarece, dac exist muchia [i, j], atunci exist i muchia [j, i].
I
Aceast reprezentare este recomandat pentru problemele n care se testeaz pre-
zena unei muchii sau a unui arc ntre dou noduri, se calculeaz gradul unui nod
etc. deoarece permite un acces rapid la nodurile i muchiile (arcele) unui graf.

Algoritmi pentru reprezentarea grafurilor folosind matricea de adiacen


Din matricea de adiacen putei obine urmtoarele informaii:
IC

Graf neorientat Graf orientat


Suma elementelor matricei de adiacen este Suma elementelor matricei de adiacen este
CT

egal cu 2m (dublul numrului de muchii). egal cu m (numrul de arce).


Gradul unui nod i este egal cu suma Gradul extern al nodului i este egal cu suma
elementelor de pe linia i (sau cu suma elementelor de pe linia i.
elementelor din coloana i). Gradul intern al nodului i este egal cu suma
DA

elementelor din coloana i.


Nodurile adiacente nodului i sunt nodurile j Succesorii nodului i sunt nodurile j (j=1,n)
(j=1,n) pentru care elementele din linia i sunt pentru care elementele din linia i sunt egale cu
egale cu 1 (a[i][j]=1). Mai pot fi definite ca 1 (a[i][j]=1).
DI

nodurile j (j=1,n) pentru care elementele din Predecesorii nodului i sunt nodurile j (j=1,n)
coloana i sunt egale cu 1 (a[j][i]=1). pentru care elementele din coloana i sunt
egale cu 1 (a[j][i]=1).
Nodurile adiacente nodului i sunt nodurile j
RA

(j=1,n) pentru care elementele din linia i sau


din coloana i sunt egale cu 1 (a[i][j]=1 sau
a[j][i]=1) reuniunea dintre mulimea
succesorilor i mulimea predecesorilor nodului.
Numrul de vecini ai nodului i este egal cu Numrul de vecini ai nodului i este egal cu
TU

gradul nodului. cardinalul mulimii de noduri adiacente nodului i.


Muchia [i,j] a grafului reprezint un element al Arcul [i,j] al grafului reprezint un element al
matricei de adiacen care ndeplinete condiia: matricei de adiacen care ndeplinete condiia:
a[i][j] = 1 (sau a[j][i] = 1). a[i][j] = 1
I
ED
Informatic 171

C
Exemplu
Se consider graful din figura alturat. Identificai matricea de adiacen a
grafului.

I
OG
a) 0 1 1 1 b) 0 1 1 1 c) 0 1 1 1 d) 0 1 0 1
1 0 1 0 1 1 1 0 1 0 1 0 1 0 1 0
1 1 0 1 1 1 0 1 1 1 0 0 0 1 0 1
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0

AG
(Bacalaureat Sesiunea special 2003)
Rspunsul corect este matricea a). Pentru a identifica matricea de adiacen a grafului din
figur, se vor elimina pe rnd variantele incorecte, prin verificarea urmtoarelor condiii:
1. Matricea trebuie s fie binar toate matricele ndeplinesc aceast condiie;

ED
2. Elementele de pe diagonala principal trebuie s aib valoarea 0 matricea b) nu
ndeplinete aceast condiie.
3. Deoarece graful este neorientat, matricea trebuie s fie simetric matricea c) nu
ndeplinete aceast condiie.

P
4. Din analiza grafului se observ c dou noduri au gradul 2 i dou noduri au gradul
3; n matricea de adiacen trebuie s existe dou linii care s conin dou ele-
mente cu valoarea 1 i dou linii care s conin trei elemente cu valoarea 1
I
matricea d) nu ndeplinete aceast condiie.
1. Scriei matricea de adiacen a grafului G4. Folosind informaiile din
Tem matricea de adiacen, determinai: gradul nodului 5, nodurile izolate

i nodurile terminale.
2. Scriei matricea de adiacen a grafului neorientat G14=(X14,U14), unde X14={1,2,3,4} i
IC

U14={[1,2], [2,3], [3,4], [4,1]}. Ce proprietate are acest graf? G


G
G111444
3. Scriei matricea de adiacen a grafului G8. Folosind informaiile din matricea de adia-
CT

cen, determinai: gradul intern al nodului 5, gradul extern al nodului 4, succesorii i


predecesorii nodului 2 i predecesorii nodului 3.
4. Scriei matricea de adiacen a grafului G11. Folosind informaiile din matricea de
adiacen, determinai: gradul intern al nodului 5, gradul extern al nodului 2, nodurile
DA

adiacente nodului 5, succesorii i predecesorii nodului 4,


nodurile terminale i nodurile izolate.
5. Scriei matricea de adiacen a grafului orientat G15 din
figura 8.
G
G
DI

6. Scriei matricea de adiacen a grafului G12. Cum iden- G111555


tificai n matricea de adiacen nodul surs al grafului?
7. Scriei matricea de adiacen a grafului G13. Cum Fig. 8
identificai n matricea de adiacen nodul destinaie al grafului?
RA

Implementarea algoritmilor pentru reprezentarea grafurilor cu matricea de adiacen


1. Crearea matricei de adiacen prin introducerea datelor de la tastatur. Deter-
minarea gradului unui nod. Salvarea matricei de adiacen ntr-un fiier text.
TU

Se citesc de la tastatur muchiile (arcele) unui graf orientat (neorientat), se creeaz matri-
cea de adiacen a grafului, se afieaz nodurile izolate i terminale i se salveaz matri-
cea de adiacen n fiierul text graf1.txt, pentru graful neorientat, i graf2.txt, pentru graful
orientat. n fiierul text se scriu, pe primul rnd, ordinul grafului, i pe urmtoarele rnduri,
I
ED

liniile matricei de adiacen. Funcia scrie() se folosete pentru a scrie matricea de


172 Implementarea structurilor de date

C
adiacen n fiier. Deoarece matricea de adiacen a fost declarat ca variabil global,
elementele ei sunt iniializate cu valoarea 0. Pentru testarea programelor se folosesc
graful neorientat G1 i graful orientat G9.

I
Graful neorientat. Funcia grad() se folosete pentru a determina gradul unui nod.

OG
#include<fstream.h>
int a[10][10],n,m;
fstream f("graf1.txt",ios::out);
void scrie()

AG
{int i,j; f<<n<<endl;
for(i=1;i<=n;i++)
{for (j=1;j<=n;j++) f<<a[i][j]<<" "; f<<endl;}
f.close();}
int grad(int i)

ED
{int j,g=0;
for (j=1;j<=n;j++) g+=a[i][j]; return g;}
void main()
{int i,j,k;

P
cout<<"numar de noduri "; cin>>n; cout<<"numar de muchii "; cin>>m;
for(k=1;k<=m;k++)
{cout<<"primul nod al muchiei "<<k<<": "; cin>>i;
I
cout<<"al doilea nod al muchiei "<<k<<": "; cin>>j;
a[i][j]=1; a[j][i]=1;}
cout<<"Nodurile izolate sunt: ";
for(i=1;i<=n;i++) if (grad(i)==0) cout<<i<<" ";

cout<<endl<<"Nodurile terminale sunt: ";


for(i=1;i<=n;i++) if (grad(i)==1) cout<<i<<" ";
IC

scrie();}
Graful orientat. Funcia grad int()se folosete pentru a determina gradul intern al unui
nod, iar funcia grad_ext()se folosete pentru a determina gradul extern al unui nod.
CT

#include<fstream.h>
int a[10][10],n,m;
fstream f("graf2.txt",ios::out);
void scrie() {//este identic cu cea de la graful neorientat}
DA

int grad ext(int i)


{int j,g=0;
for (j=1;j<=n;j++) g+=a[i][j]; return g;}
int grad int(int i)
DI

{int j,g=0;
for (j=1;j<=n;j++) g+=a[j][i]; return g;}
void main()
{int i,j,k;
RA

cout<<"numar de noduri "; cin>>n; cout<<"numar de arce "; cin>>m;


for(k=1;k<=m;k++)
{cout<<"nodul initial al arcului "<<k<<": "; cin>>i;
cout<<"nodul final al arcului "<<k<<": "; cin>>j; a[i][j]=1;}
TU

cout<<"Nodurile izolate sunt: ";


for(i=1;i<=n;i++) if (grad int(i)+grad ext(i)==0) cout<<i<<" ";
cout<<endl<<"Nodurile terminale sunt: ";
for(i=1;i<=n;i++) if (grad int(i)+grad ext(i)==1) cout<<i<<" ";
scrie();}
I
ED
Informatic 173

C
2. Crearea matricei de adiacen prin citirea datelor din fiier. Determinarea num-
rului de vecini ai unui nod. Afiarea muchiilor (arcelor) grafului.
Se citesc din fiierele text create anterior matricele de adiacen ale celor dou grafuri

I
graf1.txt, respectiv graf2.txt. Se afieaz nodurile care au cei mai muli vecini (cele mai multe

OG
noduri adiacente). Se determin numrul de muchii (arce) ale grafului i se afieaz muchiile
(arcele). Funcia citeste() se folosete pentru a citi matricea de adiacen din fiier.
Graful neorientat. Funcia nr m() se folosete pentru a determina numrul de muchii ale
grafului. La afiarea muchiilor, pentru a nu se afia de dou ori aceeai muchie, se

AG
parcurge matricea de adiacen numai deasupra diagonalei principale.
#include<fstream.h>
int a[10][10],n;
fstream f("graf1.txt",ios::in);

ED
void citeste()
{int i,j; f>>n;
for(i=1;i<=n;i++)
for (j=1;j<=n;j++) f>>a[i][j]; f.close();}

P
int nr m()
{int i,j,m=0;
for(i=1;i<=n;i++)
I
for (j=1;j<=n;j++) m+=a[i][j]; return m/2;}
int grad(int i) {// este identic cu cea de la exemplul anterior}
void main()
{int i,j,max; citeste(); max=grad(1);

for(i=2;i<=n;i++) if (grad(i)>max) max=grad(i);


cout<<"Nodurile cu cei mai multi vecini sunt: ";
IC

for(i=1;i<=n;i++) if (grad(i)==max) cout<<i<<" ";


cout<<endl<<"Graful are "<<nr m()<<" muchii "<<endl;
cout<<"Muchiile grafului sunt: ";
CT

for(i=1;i<=n;i++)
for (j=i+1;j<=n;j++) if (a[i][j]==1) cout<<i<<"-"<<j<<" "; }
Graful orientat. Funcia nr_a() se folosete pentru a determina numrul de arce ale
grafului. Funcia vecini() se folosete pentru a determina numrul de vecini ai unui nod.
DA

La afiarea arcelor, se parcurge toat matricea de adiacen.


#include<fstream.h>
int a[10][10],n;
fstream f("graf2.txt",ios::in);
DI

void citeste(){//este identic cu cea de la graful neorientat}


int nr a()
{int i,j,m=0;
for(i=1;i<=n;i++)
RA

for (j=1;j<=n;j++) m+=a[i][j]; return m;}


int vecini(int i)
{int j,v=0;
for (j=1;j<=n;j++) if (a[i][j]==1 || a[j][i]==1) v++; return v;}
void main()
TU

{int i,j,max; citeste(); max=vecini(1);


for(i=2;i<=n;i++) if (vecini(i)>max) max=vecini(i);
cout<<"Nodurile cu cei mai multi vecini sunt: ";
for(i=1;i<=n;i++) if (vecini(i)==max) cout<<i<<" ";
I

cout<<endl<<"Graful are "<<nr a()<<" arce "<<endl;


ED
174 Implementarea structurilor de date

C
cout<<"Arcele grafului sunt: ";
for(i=1;i<=n;i++)
for (j=1;j<=n;j++) if (a[i][j]==1) cout<<i<<"-"<<j<<" ";}

I
3. Crearea matricei de adiacen prin citirea muchiilor (arcelor) din fiier. Determi-

OG
narea vecinilor unui nod.
Datele se citesc din fiierul text graf3.txt, pentru graful neorientat, i graf4.txt, pentru graful
orientat. n fiier sunt scrise, pe primul rnd, desprite prin spaii, numrul de noduri i nu-
mrul de muchii (arce) ale grafului, i apoi pe cte un rnd, separate prin spaiu, cele dou

AG
noduri terminale ale fiecrei muchii (arc). Se afieaz vecinii fiecrui nod. Funcia
citeste() se folosete pentru a citi datele din fiier, iar funcia vecini() pentru a deter-
mina vecinii unui nod. Fiierele text se creeaz cu ajutorul unui editor de texte. Pentru
testarea programelor se folosesc graful neorientat G1 i graful orientat G9.

ED
Graful neorientat.
#include<fstream.h>
int a[10][10],n,m;
fstream f("graf3.txt",ios::in);

P
void citeste()
{int k,i,j; f>>n>>m;
for(k=1;k<=m;k++) {f>>i>>j; a[i][j]=1; a[j][i]=1;} f.close();}
I
void vecini(int i)
{for(int j=1;j<=n;j++) if(a[i][j]==1) cout<<j<<" ";}
void main()
{int i; citeste(); cout<<"Vecinii fiecarui nod sunt: "<<endl;

for (i=1;i<=n;i++) {cout<<"Nodul "<<i<<": "; vecini(i); cout<<endl;}}


IC

Graful orientat.
#include<fstream.h>
int a[10][10],n,m;
CT

fstream f("graf4.txt",ios::in);
void citeste()
{int k,i,j; f>>n>>m;
for(k=1;k<=m;k++) {f>>i>>j; a[i][j]=1;} f.close();}
DA

void vecini(int i)
{for(int j=1;j<=n;j++) if(a[i][j]==1 || a[j][i]==1) cout<<j<<" ";}
void main()
{int i; citeste(); cout<<"Vecinii fiecarui nod sunt: "<<endl;
for (i=1;i<=n;i++){cout<<"Nodul "<<i<<": "; vecini(i); cout<<endl;}}
DI

4. Generarea matricei de adiacen.


Pentru a testa programele care prelucreaz grafuri implementate cu matricea de adiacen,
putei s generai aleatoriu matricea de adiacen. Funcia generare() genereaz matri-
RA

cea de adiacen a unui graf neorientat, cu n noduri i m muchii.


#include<iostream.h>
#include<stdlib.h>
int a[10][10],n,m;
TU

void generare()
{int k=0,i,j; randomize();
while(k<m)
{i=rand()%n+1; j=rand()%n+1;
I

if(i!=j && a[i][j]==0) {a[i][j]=1; a[j][i]=1; k++;}}}


ED
Informatic 175

C
void main() {cout<<"n= "; cin>>n; cout<<"m= "; cin>>m;
while (m>n*(n-1)/2) {cout<<"m= "; cin>>m;}
generare(); ... }

I
1. ntr-un fiier este scris o matrice ptrat, astfel: pe primul rnd, un

OG
Tem numr care reprezint dimensiunea matricei, i pe urmtoarele rnduri,
valori numerice desprite prin spaiu care reprezint elementele de
pe cte o linie a matricei. S se verifice dac aceast matrice poate fi matricea de adia-
cen a unui graf. n caz afirmativ, s se precizeze dac graful este orientat sau neorientat

AG
2. Scriei un program care s genereze aleatoriu matricea de adiacen a unui graf orientat.
3. Scriei un program care citete dintr-un fiier matricea de adiacen a unui graf neorien-
tat i care determin numrul minim de muchii care trebuie adugate pentru ca graful s
nu conin noduri izolate.

ED
4. Scriei un program care citete, din dou fiiere text, g1.txt i g2.txt, matricele de
adiacen a dou grafuri, Ga=(X,Ua) i Gb=(X,Ub), i care determin matricea de
adiacen a grafului reuniune Gr=(X,Ur), unde Ur= Ua Ub, care se salveaz n fiierul
g3.txt i matricea de adiacen a grafului intersecie Gi=(X,Ui), unde Ui= Ua Ub, care

P
se salveaz n fiierul g4.txt.
5. Scriei un program care citete din fiierul text graf2.txt informaii despre un graf
orientat (de pe prima linie numrul de noduri, apoi matricea de adiacen) i de la
I
tastatur o mulime A de numere care reprezint etichetele unor noduri din graf i
care afieaz mulimea arcelor ce au o extremitate ntr-un nod din mulimea A i o
extremitate n muimea X-A (X fiind mulimea nodurilor grafului). Pentru testarea
programului, se vor folosi graful G9 i mulimea A={1,3,4,6}.

2.7.4.2. Reprezentarea prin matricea de inciden


IC

Matricea de inciden a unui graf neorientat este o matrice binar cu n linii i m


coloane (An,m), ale crei elemente ai,j sunt definite astfel:
CT

1, dac [i, j] U
a i, j 0, dac [i, j] U

Implementarea grafului neorientat prin matricea de inciden se face printr-un tablou
DA

bidimensional (o matrice cu dimensiunea nm), astfel:


int a[<n>][<m>];
Graful neorientat G1
DI

1 2 3 4 5 6 7 8 9
1 1 1 1 0 0 0 0 0 0
2 1 0 0 1 1 0 0 0 0
RA

3 0 1 0 1 0 1 1 0 0
Graful G1 4 0 0 1 0 0 1 0 0 0
Fig. 9 5 0 0 0 0 1 0 1 0 0
6 0 0 0 0 0 0 0 1 1
TU

Proprietile matricei de inciden a


7 0 0 0 0 0 0 0 1 0
grafului neorientat:
8 0 0 0 0 0 0 0 0 1
1. Pe fiecare coloan exist dou ele-
mente cu valoarea 1 (pe liniile i i j care corespund nodurilor incidente cu muchia), iar
I

restul elementelor au valoarea 0.


ED
176 Implementarea structurilor de date

C
2. Matricea de inciden are 2m elemente egale cu 1, deoarece fiecare muchie este
incident cu dou noduri.

I
Matricea de inciden a unui graf orientat este o matrice cu n linii i m coloane

OG
(An,m), ale crei elemente ai,j sunt definite astfel:

1, dac nodul i este extremitat ea final a arcului j



a i, j 1, dac nodul i este extremitat ea ininii a arcului j
0, dac nodul i nu este extremitat e a arcului j

AG
Implementarea grafului neorientat prin matricea de inciden se face printr-un tablou
bidimensional (o matrice cu dimensiunea nm), astfel:
int a[<n>][<m>];

ED
Graful orientat G9
1 2 3 4 5 6 7 8 9 10
1 1 -1 0 0 0 0 0 0 0 0

P
2 -1 1 -1 -1 1 0 0 0 0 0
3 0 0 1 0 0 1 -1 0 0 0
4 0 0 0 1 -1 0 0 -1 0 0
I
Graful G9 5 0 0 0 0 0 -1 1 1 1 -1
Fig. 10 6 0 0 0 0 0 0 0 0 -1 1

Proprietile matricei de inciden a grafului orientat:


1. Pe fiecare coloan exist un element cu valoarea 1 (pe linia i care corespunde extremitii
IC

finale a arcului) i un element cu valoarea -1 (pe linia j care care corespunde extremitii
iniiale a arcului), iar restul elementelor au valoarea 0.
2. Matricea de inciden are m elemente egale cu 1 i m elemente egale cu -1, deoarece fie-
CT

care arc are o extremitate final i o extremitate iniial. Suma elementelor matricei este 0.
Aceast reprezentare este recomandat pentru grafurile care au un numr mare de
noduri i un numr mic de muchii.
DA

Algoritmi pentru reprezentarea grafurilor folosind matricea de inciden


Din matricea de inciden putei obine urmtoarele informaii:
Graf neorientat Graf orientat
DI

Gradul unui nod i este egal cu suma Gradul intern al unui nod i este egal cu
elementelor de pe linia i. numrul de elemente cu valoarea 1 de pe
linia i. Gradul extern al unui nod i este egal
cu numrul de elemente cu valoarea -1 de pe
RA

linia i.
Nodurile adiacente nodului i sunt nodurile j Succesorii nodului i sunt nodurile j (j=1,n) pen-
(j=1,n) pentru care elementele din linia j sunt tru care elementele din linia j sunt egale cu 1
egale cu 1 n coloana k (k=1,m) n care i n coloana k (k=1,m) n care elementele de pe
TU

elementele de pe linia i au valoarea 1: linia i au valoarea -1: a[i][k] = -1 i a[j][k] = 1.


a[i][k] = 1 i a[j][k] = 1. Predecesorii nodului i sunt nodurile j (j=1,n)
penru care elementele din linia j sunt egale cu
-1 n coloana k (k=1,m) n care elementele de pe
I

linia i au valoarea 1: a[i][k] = 1 i a[j][k] = -1.


ED
Informatic 177

C
Graf neorientat Graf orientat
Nodurile adiacente nodului i sunt date de
reuniunea dintre mulimea succesorilor i

I
mulimea predecesorilor nodului.

OG
Numrul de vecini ai nodului i este egal cu Numrul de vecini ai nodului i este egal cu
gradul nodului. cardinalul mulimii de noduri adiacente nodului i.
Muchia k = [i,j] a grafului este determinat de Arcul k = [i,j] al grafului este determinat de
dou elemente ale matriceii a[i]kj] i a[j]kj], care dou elemente ale matricei, a[i]kj] i a[j]kj], care
ndeplinesc condiia a[i][k] = 1 i a[j][k] = 1, i ndeplinesc condiia a[i][k] = -1 i a[j][k] = 1, i

AG
semnific faptul c muchia k este incident cu semnific faptul c arcul k iese din nodul i i
nodurile i i j. intr n nodul j

1. Scriei matricea de inciden a grafului neorientat G4. Folosind infor-


Tem

ED
maiile din matricea de inciden, determinai: gradul nodului 5, nodurile
izolate i nodurile terminale.
2. Scriei matricea de inciden a grafului neorientat G14. Ce proprietate are acest graf?
3. Scriei matricea de inciden a grafului G8. Folosind informaiile din matricea de inci-

P
den, determinai: gradul intern al nodului 5, gradul extern al nodului 4, succesorii i
predecesorii nodului 2 i predecesorii nodului 3.
G
G
G111666
4. Scriei matricea de inciden a grafului orientat G16 din figura 11.
I
5. Scriei matricea de inciden a grafului G11. Folosind informa-
iile din matricea de inciden determinai: gradul intern al
nodului 5, gradul extern al nodului 2, nodurile adiacente
nodului 5, succesorii i predecesorii nodului 4, nodurile termi- Fig. 11

nale i nodurile izolate.


6. Scriei matricea de inciden a grafului G13. Cum identificai, n matricea de inciden,
IC

nodul surs al unui graf?


7. Scriei matricea de inciden a grafului G14. Cum identificai, n matricea de inciden,
CT

nodul destinaie al unui graf?


Implementarea algoritmilor pentru reprezentarea grafurilor cu matricea de inciden
1. Crearea matricei de inciden prin introducerea datelor de la tastatur. Deter-
DA

minarea gradului unui nod. Salvarea matricei de inciden ntr-un fiier text.
Se citesc de la tastatur muchiile (arcele) unui graf orientat (neorientat). Se creeaz
matricea de inciden a grafului. Se afieaz gradul nodului p a crui etichet se introduce
de la tastatur. Se salveaz matricea de inciden n fiierul text graf5.txt, pentru graful
DI

neorientat, i graf6.txt, pentru graful orientat. n fiierul text se scriu pe primul rnd ordinul
grafului i numrul de muchii, iar pe urmtoarele rnduri, liniile matricei de inciden.
Funcia scrie() se folosete pentru a scrie matricea de inciden n fiier. Pentru testarea
programelor se folosesc graful neorientat G1 i graful orientat G9.
RA

Graful neorientat. Funcia grad() se folosete pentru a determina gradul unui nod.
#include<fstream.h>
int a[10][10],n,m;
TU

fstream f("graf5.txt",ios::out);
void scrie()
{int i,j; f<<n<<" "<<m<<endl;
for(i=1;i<=n;i++)
{for(k=1;k<=m;k++) f<<a[i][k]<<" "; f<<endl;}
I
ED

f.close();}
178 Implementarea structurilor de date

C
int grad(int i)
{int g=0,k;
for(k=1;k<=m;k++) g+=a[i][k]; return g;}

I
void main()

OG
{int i,j,p,k;
cout<<"numar de noduri "; cin>>n; cout<<"numar de muchii "; cin>>m;
for(k=1;k<=m;k++)
{cout<<"primul nod al muchiei "<<k<<": "; cin>>i;
cout<<"al doilea nod al muchiei "<<k<<": "; cin>>j;

AG
a[i][k]=1; a[j][k]=1;}
cout<<"nodul= "; cin>>p;
cout<<"Gradul nodului "<<p<<" este "<<grad(p)<<endl;
scrie();}

ED
Graful orientat. Funcia grad_int() se folosete pentru a determina gradul intern al unui
nod, iar funcia grad_ext()se folosete pentru a determina gradul extern al unui nod.
#include<fstream.h>
int a[10][10],n,m;

P
fstream f("graf6.txt",ios::out);
int scrie() {//este identic cu cea de la graful neorientat }
int grad int(int i)
I
{int g=0,k;
for(k=1;k<=m;k++) if (a[i][k]==1) g++; return g;}
int grad ext(int i)
{int g=0,k;

for(k=1;k<=m;k++) if (a[i][k]==-1) g++; return g;}


void main()
IC

{int i,j,p,k;
cout<<"numar de noduri "; cin>>n; cout<<"numar de muchii "; cin>>m;
for(k=1;k<=m;k++)
CT

{cout<<"nodul initial al arcului "<<k<<": "; cin>>i;


cout<<"nodul final al arcului "<<k<<": "; cin>>j;
a[i][k]=-1; a[j][k]=1;}
cout<<"nodul= "; cin>>p;
DA

cout<<"Gradul intern al nodului "<<p<<" este "<<grad int(p)<<endl;


cout<<"Gradul extern al nodului "<<p<<" este "<<grad ext(p)<<endl;
scrie();}
2. Crearea matricei de inciden prin citirea datelor din fiier. Afiarea vecinilor
DI

unui nod.
Se citesc din fiierele create anterior (graf5.txt, respectiv graf6.txt) matricele de inciden
ale celor dou grafuri i se afieaz vecinii unui nod x a crui etichet se introduce de la
RA

tastatur. Funcia citeste() se folosete pentru a citi matricea de inciden din fiier.
Graful neorientat. Funcia vecini() se folosete pentru a determina vecinii unui nod.
#include<fstream.h>
int a[10][10],n;
TU

fstream f("graf5.txt",ios::in);
void citeste()
{int i,k; f>>n>>m;
for(i=1;i<=n;i++)
I

for (k=1;k<=m;k++) f>>a[i][k]; f.close();}


ED
Informatic 179

C
void vecini(int i)
{int k,j;
for(k=1;k<=m;k++)

I
if(a[i][k]==1) for(j=1;j<=n;j++)

OG
if(j!=i && a[j][k]==1) cout<<j<<" ";}
void main()
{int p; cout<<"nodul= "; cin>>x; citeste();
cout<<"Vecinii nodului "<<x<<" sunt nodurile "; vecini(x);}
Graful orientat. Vectorii binari s i p se folosesc pentru a memora succesorii, respectiv prede-

AG
cesorii nodului x. Elementul i are valoarea 1 dac nodul i este succesor, respectiv predecesor
al nodului x; altfel, are valoarea 0. Funciile succ() i pred() se folosesc pentru a determina
n vectorii s i p succesorii, respectiv predecesorii unui nod. Funcia vecini() se folosete
pentru a determina vecinii unui nod, prin reuniunea mulimii predecesorilor i a succesorilor.

ED
#include<fstream.h>
int a[10][10],n,m,s[10],p[10];
fstream f("graf6.txt",ios::in);
void citeste() {//este identic cu cea de la graful neorientat }

P
void succ(int i)
{for(int k=1;k<=m;k++)
if(a[i][k]==-1) for(int j=1;j<=n;j++)
I
if(j!=i && a[j][k]==1) s[j]=1;}
void pred(int i)
{for(int k=1;k<=m;k++)
if(a[i][k]==1) for(int j=1;j<=n;j++)

if(j!=i && a[j][k]==-1) p[j]=1;}


void vecini(int i)
IC

{int j; succ(i); pred(i);


for(j=1;j<=n;j++) if (j!=i && (s[j]==1 || p[j]==1)) cout<<j<<" ";}
void main()
CT

{int x; cout<<"nodul= "; cin>>x; citeste();


cout<<"Vecinii nodului "<<x<<" sunt nodurile "; vecini(x);}
3. Crearea matricei de inciden prin citirea muchiilor (arcelor) din fiier. Prelucrarea
informaiilor asociate muchiilor.
DA

Datele se citesc din fiierul text graf7.txt, pentru graful neorientat, i graf8.txt, pentru graful
orienatat. n fiier sunt scrise, pe primul rnd, desprite prin spaii, numrul de noduri i
numrul de muchii (arce) ale grafului, i apoi, pe cte un rnd, separate prin spaiu, cele dou
DI

noduri terminale ale fiecrei muchii (arc) i lungimea muchiei (arcului). Se afieaz muchiile
(arcele) care au lungimea mai mare dect lungimea medie a muchiilor (arcelor) din graf. Se
folosete vectorul d pentru a memora lungimea fiecrei muchii (arc). Funcia citeste() se
folosete pentru citi datele din fiier, funcia medie() pentru a determina lungimea medie a
RA

muchiilor (arceor) din graf iar funcia afisare() pentru a afia muchiile (arcele) care au
lungimea mai mare dect media. Fiierele text se creeaz cu ajutorul unui editor de texte.
Pentru testarea programelor se folosesc graful neorientat G1 i graful orientat G9. n aceste
grafuri se asociaz fiecrei muchii (arc) o valoare pentru lungime.
TU

Graful neorientat
#include<fstream.h>
int a[10][10],d[10],n,m;
I

fstream f("graf7.txt",ios::in);
ED
180 Implementarea structurilor de date

C
void citeste()
{int k,i,j,l; f>>n>>m;
for(k=1;k<=m;k++) {f>>i>>j>>l; a[i][k]=1; a[j][k]=1; d[k]=l;}

I
f.close();}

OG
float media()
{int i,s=0;
for(i=1;i<=m;i++) s+=d[i]; return (float)s/m;}
void afiseaza()
{int i,k; float dm=media();

AG
for(k=1;k<=m;k++)
if (d[k]>dm)
{for (i=1;i<=n;i++) if (a[i][k]==1) cout<<i<<" ";
cout<<" cu lungimea "<<d[k]<<endl;}}
void main()

ED
{citeste(); cout<<"Media lungimii este: "<<media()<<endl;
cout<<"Muchiile sunt: "<<endl; afiseaza();}
Graful orientat

P
#include<fstream.h>
int a[10][15],d[15],n,m;
fstream f("graf8.txt",ios::in);
I
void citeste()
{int k,i,j,l; f>>n>>m;
for(k=1;k<=m;k++) {f>>i>>j>>l; a[i][k]=-1; a[j][k]=1; d[k]=l;}
f.close(); }

float media() {//este identic cu cea de la graful neorientat }


void afiseaza()
IC

{int i,k,x,y; float dm=media();


for(k=1;k<=m;k++)
if (d[k]>dm)
CT

{for (i=1;i<=n;i++) {if (a[i][k]==-1) x=i;


if (a[i][k]==1) y=i;}
cout<<x<<"-"<<y<<" cu lungimea "<<d[k]<<endl;}}
void main()
{citeste(); cout<<"Media lungimii este: "<<media()<<endl;
DA

cout<<"Arcele sunt: "<<endl; afiseaza();}


4. Crearea matricei de inciden prin citirea datelor din matricea de adiacen.
Afiarea muchiilor i a nodurilor izolate.
DI

Matricele de adiacen se citesc din fiierele text create anterior: graf1.txt, pentru graful
neorientat, i graf2.txt, pentru graful orientat. Se creeaz matricele de inciden ale celor dou
grafuri, se afieaz muchiile (arcele) i nodurile izolate. Se salveaz n fiierul text graf9.txt,
respectiv graf10.txt, informaiile despre muchii, astfel: pe primul rnd, desprite prin spaii,
RA

numrul de noduri i numrul de muchii (arce) ale grafului, i apoi, pe cte un rnd, separate
prin spaiu, cele dou noduri terminale ale fiecrei muchii (arc). Se folosesc matricele a pentru
matricea de adiacen i b pentru matricea de inciden i funciile citeste() pentru a citi
matricea de adiacena din fiier, salveaza() pentru a salva n fiierul text informaiile despre
TU

muchiile (arcele) grafului, transforma() pentru a obine matricea de inciden din matricea
de adiacen, afiseaza_noduri_izolate() pentru a afia nodurile izolate, i
afiseaza_muchii() pentru a afia muchiile (arcele). Pentru testarea programelor se
folosesc graful neorientat G1 i graful orientat G9.
I
ED
Informatic 181

C
Graful neorientat
#include<fstream.h>
int a[10][10],b[10][20],n,m;

I
fstream f1("graf1.txt",ios::in),f2("graf9.txt",ios::out);

OG
void citeste()
{int i,j; f1>>n;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) {f1>>a[i][j]; if(a[i][j]==1) m++;}
m=m/2; f1.close();}

AG
void transforma()
{int i,j,k=1;
for (i=1;i<=n;i++)
for (j=1;j<i;j++) if (a[i][j]==1) {b[i][k]=1; b[j][k]=1; k++;}}

ED
void afiseaza muchii()
{for (int k=1; k<=m; k++)
{cout<<"Muchia "<<k<<": ";
for (int i=1;i<=n;i++) if (b[i][k]==1) cout<<i<<" "; cout<<endl;}}
void afiseaza noduri izolate()

P
{int i,k,x;
for (i=1;i<=n;i++)
{for (k=1,x=0;k<=m && x==0;k++) if (b[i][k]==1) x=1;
I
if (!x) cout<<i<<" ";}}
void salveaza()
{f2<<n<<" "<<m<<endl;

for (int k=1;k<=m;k++)


{for (int i=1;i<=n;i++) if (b[i][k]==1) f2<<i<<" "; f2<<endl;}
f2.close();}
IC

void main()
{citeste(); transforma(); afiseaza_muchii();
cout<<"Nodurile izolate sunt: "; afiseaza_noduri_izolate();
CT

salveaza();}
Graful orientat
#include<fstream.h>
DA

int a[10][10],b[10][20],n,m;
fstream f1("graf1.txt",ios::in),f2("graf9.txt",ios::out);
void citeste()
{int i,j; f1>>n;
DI

for(i=1;i<=n;i++)
for(j=1;j<=n;j++) {f1>>a[i][j]; if(a[i][j]==1) m++;} f1.close();}
void transforma()
{int i,j,k=1;
RA

for (i=1;i<=n;i++)
for (j=1;j<=n;j++) if (a[i][j]==1) {b[i][k]=-1; b[j][k]=1; k++;}}
void afiseaza arce()
{int i,k,x,y;
for (k=1; k<=m; k++)
TU

{cout<<"Arcul "<<k<<": ";


for (i=1;i<=n;i++) {if (b[i][k]==-1) x=i; if (b[i][k]==1) y=i;}
cout<<x<<"-"<<y<<endl;}}
void afiseaza noduri izolate()
I

{int i,k,x;
ED
182 Implementarea structurilor de date

C
for (i=1;i<=n;i++)
{for (k=1,x=0;k<=m && x==0;k++) if (b[i][k]==1 || b[i][k]==-1) x=1;
if (!x) cout<<i<<" ";}}

I
void salveaza()

OG
{int i,k;
f2<<n<<" "<<m<<endl;
for (k=1;k<=m;k++)
{for (i=1;i<=n;i++) {if (b[i][k]==-1) x=i; if (b[i][k]==1) y=i;}
f2<<x<<" "<<y<<endl;}

AG
f2.close();}
void main()
{citeste(); transforma(); afiseaza arce();
cout<<"Nodurile izolate sunt: "; afiseaza noduri izolate();
salveaza();}

ED
1. ntr-un fiier text este scris o matrice, astfel: pe primul rnd dou
Tem numere separate prin spaiu, care reprezint numrul de linii i
numrul de coloane ale matricei, i, pe urmtoarele rnduri valori

P
numerice desprite prin spaiu, care reprezint elementele de pe cte o linie a matricei.
a. Scriei un program care s verifice dac aceast matrice poate fi matricea de
inciden a unui graf neorientat. n caz afirmativ, s se afieze cte noduri izolate are
I
graful (Indicaie. Se verific urmtoarele condiii: a) s fie o matrice binar; b) suma
elementelor de pe fiecare coloan s fie egal cu 2; c) s nu existe dou coloane
identice. Un nod este izolat dac suma elementelor de pe linia sa este egal cu 0).

b. Scriei un program care s verifice dac aceast matrice poate fi matricea de


inciden a unui graf orientat. n caz afirmativ, s se determine cte noduri care au
IC

gradul intern egal cu gradul extern exist (Indicaie. Se verific urmtoarele condiii:
a) pe fiecare coloan s nu existe dect o valoare egal cu 1, una egal cu -1 i
restul egale cu 0; b) s nu existe dou coloane identice. Un nod are gradul intern
CT

egal cu gradul extern dac suma elementelor de pe linia sa este egal cu 0).
2. Scriei un program care citete din fiierul text graf6.txt matricea de inciden a grafului
orientat i care:
a. afieaz numrul de vecini ai unui nod p a crui etichet se citete de la tastatur;
DA

b. genereaz matricea de adiacen a grafului din matricea de inciden i o salveaz


n fiierul graf6a.txt.

2.7.4.3. Reprezentarea prin lista muchiilor


DI

Lista muchiilor unui graf este format din m elemente care conin, fiecare,
cte o pereche de dou noduri, xi i xj, care formeaz o muchie,
adic pentru care [xi, xj]U.
RA

Implementarea acestui tip de reprezentare se poate face folosind una dintre urmtoarele
structuri de date:
Matricea muchiilor u cu dimensiune m2, n care fiecare linie corespunde unei
TU

muchii (arc) i n fiecare linie se nregistreaz n cele dou coloane etichetele nodu-
rilor care se gsesc la extremitile muchiei (arcului).
int u [<m>][2];
Referirea la nodurile adiacente muchiei (arcului) i se face prin u[i][0] extremitatea
I
ED

iniial a muchiei (arcului), respectiv u[i][1] extremitatea final a muchiei (arcului).


Informatic 183

C
Vectorul muchiilor u cu dimensiunea m ale crui elemente sunt nregistrri, fiecare
nregistrare fiind format din dou cmpuri x i y ce conin etichetele nodurilor care
se gsesc la extremitile muchiei (arcului). Pentru elementele vectorului se define-

I
te tipul de dat muchie, de tip nregistrare.

OG
struct muchie {int x,y;};
muchie u[<m>];
Referirea la o muchie (arc) i se face prin u[i], iar la unul dintre nodurile adiacente
muchiei (arcului) se face prin u[i].x extremitatea iniial a muchie (arcului),

AG
respectiv u[i].y extremitatea final a muchiei (arcului).

Implementarea cu matrice
0 1

ED
1 1 2
2 1 3
3 1 4
Graful neorientat G1
4 2 3

P
5 2 4
Implementarea cu vector de nregistrri
6 3 4
I
Muchiile
7 3 5
8 6 7 1 2 3 4 5 6 7 8 9
9 6 8 1 2 1 3 2 4 2 3 2 4 3 4 3 5 6 7 6 8

Implementarea cu matrice
IC

0 1
1 1 2
CT

2 2 1
3 2 4
Graful orientat G9
4 3 2
DA

5 3 5
Implementarea cu vector de nregistrri
6 4 2
Arcele
7 4 5
8 5 3 1 2 3 4 5 6 7 8 9 10
DI

9 5 6 1 2 2 1 2 4 3 2 3 5 4 2 4 5 5 3 5 6 6 5
10 6 5
RA

Exemple:
Dac implementarea se face folosind matricea, atunci pentru orice muchie (arc) i, u[i][0]
u[i][1]. Dac implementarea se face folosind vectorul de nregistrri, atunci pentru
orice muchie (arc) i, u[i].x u[i].y .
TU

Aceast reprezentare este recomandat pentru problemele n care se face


prelucrarea succesiv a muchiilor (arcelor). Are avantajul c permite adugarea la
tipul de dat muchie i a altor cmpuri (lungime, cost, timp etc.), corespunztor
unor mrimi care pot fi asociate muchiilor (arcelor).
I
ED
184 Implementarea structurilor de date

C
Algoritmi pentru reprezentarea grafurilor folosind lista muchiilor
Din lista muchiilor putei obine urmtoarele informaii:

I
Graf neorientat Graf orientat

OG
Gradul unui nod i este egal, n funcie de Gradul extern al nodului i este egal, n funcie
implementare, cu numrul de apariii ale de implementare, cu numrul de apariii ale eti-
etichetei nodului n matrice, respectiv n chetei nodului n coloana 0 a matricei, respec-
cmpurile vectorului de nregistrri. tiv n primul cmp, n vectorul de nregistrri.
Gradul intern al nodului i este egal, n funcie

AG
de implementare, cu numrul de apariii ale eti-
chetei nodului n coloana 1 a matricei, respec-
tiv n al doilea cmp, n vectorul de nregistrri.
Nodurile adiacente nodului i sunt, n funcie Succesorii nodului i sunt, n funcie de

ED
de implementare, etichetele j din coloana 1, implementare, etichetele j din coloana 1 pentru
pentru care u[k][0]=i, sau din coloana 0, pentru care u[k][0]=i, respectiv etichetele j din cmpul
care u[k][1]=i, respectiv etichetele j din cmpul u[k].y pentru care u[k].x=i (k=1,m).
u[k].y, pentru care u[k].x=i, sau din cmpul Predecesorii nodului i sunt, n funcie de
u[k].x, pentru care u[k].y=i (k=1,m). implementare, etichetele j din coloana 0 pentru

P
care u[k][1]=i, respectiv etichetele j din cmpul
u[k].x pentru care u[k].y=i (k=1,m).
Nodurile adiacente nodului i sunt date de
I
reuniunea dintre mulimea succesorilor i
mulimea predecesorilor nodului.
Numrul de vecini ai nodului i este egal cu Numrul de vecini ai nodului i este egal cu
gradul nodului. cardinalul mulimii de noduri adiacente nodului i.

1. Scriei lista muchiilor a grafului G4. Folosind informaiile din lista mu-
IC

Tem chiilor, determinai: gradul nodului 5, nodurile izolate i nodurile termi-


nale.
2. Scriei lista muchiilor a grafului neorientat G14. Ce proprietate are acest graf?
CT

3. Scriei lista muchiilor a grafului G8. Folosind informaiile din lista muchiilor, determinai:
gradul intern al nodului 5, gradul extern al nodului 4, succesorii i predecesorii nodului 2
i predecesorii nodului 3.
DA

4. Scriei lista muchiilor a grafului G11. Folosind informaiile din lista muchiilor, determinai:
gradul intern al nodului 5, gradul extern al nodului 2, nodurile adiacente nodului 5,
succesorii i predecesorii nodului 4, nodurile terminale i nodurile izolate.
G
G
G111777 5. Scriei lista muchiilor a grafului orientat G17 din figura 12. Folo-
DI

sind informaiile din lista muchiilor, identificai nodurile izolate.


6. Scriei lista muchiilor a grafului G13. Cum identificai, n lista
muchiilor, nodul surs?
7. Scriei lista muchiilor a grafului G14. Cum identificai, n lista
RA

muchiilor, nodul destinaie? Fig. 12

Implementarea algoritmilor pentru reprezentarea grafurilor cu lista muchiilor


1. Crearea matricei cu lista muchiilor prin introducerea datelor de la tastatur. Deter-
TU

minarea gradului unui nod. Salvarea informaiilor despre muchii ntr-un fiier text.
Se citesc de la tastatur muchiile (arcele) unui graf orientat (neorientat). Se creeaz matri-
cea cu muchiile grafului. Se afieaz nodurile izolate i terminale. Se salveaz matricea cu
muchiile grafului n fiierul text graf11.txt, pentru graful neorientat, i graf12.txt, pentru graful
I

orientat. n fiierul text se vor scrie, pe primul rnd, ordinul grafului i numrul de muchii, iar
ED
Informatic 185

C
pe urmtoarele rnduri, nodurile de la extremitile unei muchii (arc). Funcia scrie() se
folosete pentru a scrie informaiile din matricea muchiilor n fiier. Pentru testarea progra-
melor se folosesc graful neorientat G1 i graful orientat G9.

I
Graful neorientat. Funcia grad() se folosete pentru a determina gradul unui nod.

OG
#include<fstream.h>
int a[10][2],n,m;
fstream f("graf11.txt",ios::out);
int grad(int i)

AG
{int k,g=0;
for (k=1;k<=m;k++) if (a[k][0]==i || a[k][1]==i) g++; return g;}
void scrie()
{int k; f<<n<<" "<<m<<endl;
for(k=1;k<=m;k++) f<<a[k][0]<<" "<<a[k][1]<<endl; f.close();}

ED
void main()
{int i,j,k;
cout<<"numar de noduri "; cin>>n; cout<<"numar de muchii "; cin>>m;
for(k=1;k<=m;k++)

P
{cout<<"primul nod al muchiei "<<k<<": "; cin>>i;
cout<<"al doilea nod al muchiei "<<k<<": "; cin>>j;
a[k][0]=i; a[k][1]=j;}
I
cout<<"Nodurile izolate sunt: ";
for(i=1;i<=n;i++) if (grad(i)==0) cout<<i<<" ";
cout<<endl<<"Nodurile terminale sunt: ";
for(i=1;i<=n;i++) if (grad(i)==1) cout<<i<<" ";

scrie();}
IC

Graful orientat. Funcia grad_int()se folosete pentru a determina gradul intern al unui
nod, iar funcia grad_ext()se folosete pentru a determina gradul extern al unui nod.
#include<fstream.h>
CT

int a[10][2],n,m;
fstream f("graf12.txt",ios::out);
int grad int(int i)
{int g=0,k;
DA

for(k=1;k<=m;k++) if (a[k][1]==i) g++; return g;}


int grad ext(int i)
{int g=0,k;
for(k=1;k<=m;k++) if (a[k][0]==i) g++; return g;}
void scrie() {//este identic cu cea de la graful neorientat }
DI

void main()
{int i,j,k;
cout<<"numar de noduri "; cin>>n; cout<<"numar de arce "; cin>>m;
for(k=1;k<=m;k++)
RA

{cout<<"nodul initial al arcului "<<k<<": "; cin>>i;


cout<<"nodul final al arcului "<<k<<": "; cin>>j;
a[k][0]=i; a[k][1]=j;}
cout<<"Nodurile izolate sunt: ";
TU

for(i=1;i<=n;i++) if (grad int(i)+grad ext(i)==0) cout<<i<<" ";


cout<<endl<<"Nodurile terminale sunt: ";
for(i=1;i<=n;i++) if (grad int(i)+grad ext(i)==1) cout<<i<<" ";
scrie();}
I
ED
186 Implementarea structurilor de date

C
2. Crearea vectorului de muchii prin citirea muchiilor (arcelor) din fiier. Prelucrarea
informaiilor asociate muchiilor.
Datele se citesc din fiierele text create anterior: graf7.txt, pentru graful neorientat, i

I
graf8.txt, pentru graful orientat. Pentru un nod p a crui etichet se citete de la tastatur,

OG
se afieaz cel mai apropiat vecin (sau cei mai apropiai vecini, dac exist mai muli) la
care se poate ajunge din nodul p. n cazul grafului neorientat, cel mai apropiat vecin este
nodul adiacent nodului p care formeaz cu acesta muchia care are lungimea cea mai mic
fa de muchiile incidente cu ceilali vecini. n cazul grafului orientat, cel mai apropiat vecin

AG
la care se poate ajunge din nodul p este nodul succesor nodului p care formeaz cu acesta
arcul care are lungimea cea mai mic fa de arcele incidente cu ceilali succesori. Funcia
citeste() se folosete pentru a citi datele din fiier. Pentru testarea programelor se
folosesc graful neorientat G1 i graful orientat G9.

ED
Graful neorientat. Funcia izolat() determin dac nodul este izolat.
#include<fstream.h>
struct muchie {int x,y,d;};
muchie u[20]; int n,m;

P
fstream f("graf7.txt",ios::in);
void citeste()
{int k; f>>n>>m;
I
for(k=1;k<=m;k++) f>>u[k].x>>u[k].y>>u[k].d; f.close();}
int izolat(int i)
{int k,g=0;
for (k=1;k<=m;k++) if (u[k].x==i || u[k].y==i) g++; return g==0;}

void main()
{int k,p,min;
IC

citeste(); cout<<"Nodul: "; cin>>p;


if (izolat(p)) cout<<"Nodul "<<p<<" nu are vecini";
else
CT

{k=1;
while (u[k].x!=p && u[k].y!=p) k++;
min=u[k].d;
for (k++;k<=m;k++)
DA

if (u[k].x==p || u[k].y==p)
if (u[k].d<min) min=u[k].d;
cout<<"Distanta minima este "<<min<<endl;
cout<<"Nodurile aflate la distanta minima sunt: ";
for (k=1;k<=m;k++)
DI

{if (u[k].x==p && u[k].d==min) cout<<u[k].y<<" ";


if (u[k].y==p && u[k].d==min) cout<<u[k].x<<" ";}}}
Graful orientat. Funcia succ()determin dac nodul are succesori.
RA

#include<fstream.h>
struct arc {int x,y,d;};
arc u[20];
int n,m;
TU

fstream f("graf8.txt",ios::in);
void citeste() {//este identic cu cea de la graful neorientat }
int succ(int i)
{int k,g=0;
I

for (k=1;k<=m;k++) if (u[k].x==i) g++; return g!=0;}


ED
Informatic 187

C
void main()
{int k,p,min; citeste(); cout<<"Nodul: "; cin>>p;
if (!succ(p))

I
cout<<"Nodul "<<p<<" nu are vecini la care sa se poata ajunge";

OG
else
{k=1;
while (u[k].x!=p) k++;
min=u[k].d;
for (k++;k<=m;k++) if (u[k].x==p && u[k].d<min) min=u[k].d;

AG
cout<<"Distanta minima este "<<min<<endl;
cout<<"Nodurile aflate la distanta minima sunt: ";
for (k=1;k<=m;k++)
if (u[k].x==p && u[k].d==min) cout<<u[k].y<<" ";}}

ED
1. Scriei un program care realizeaz urmtoarele:
Tem a. reface matricea cu muchiile grafului orientat din fiierul text graf12.txt;
b. determin cte noduri izolate are graful i afieaz aceste noduri;
c. genereaz matricea de adiacen din matricea muchiilor i o salveaz n fiierul text

P
graf12a.txt.
(Indicaie. Se numr nodurile distincte care apar n lista muchiilor n1, iar numrul de
noduri izolate va fi dat de diferena n-n1.)
I
2. Scriei un program care construiete vectorul de muchii din matricea de adiacen a
grafului orientat care se citete din fiierul text graf2.txt i care determin vecinii unui
nod p a crui etichet se citete de la tastatur.

3. Scriei un program care s genereze aleatoriu, ntr-un fiier, lista muchiilor unui graf
neorientat (orientat). Numrul de noduri i numrul de muchii se citesc de la tastatur.
IC

4. Scriei un program care s genereze aleatoriu, ntr-un fiier, lista muchiilor unui graf
neorientat (orientat) n care muchiile au asociate o mrime numit cost. Se citesc de la
tastatur: numrul de noduri, numrul de muchii i limitele intervalului n care mrimea
CT

cost poate lua valori.

2.7.4.4. Reprezentarea prin lista de adiacen


DA

Lista de adiacen este format din listele Li (1in) care conin toi vecini
unui nod xi la care se poate ajunge direct din nodul xi,
adic toate nodurile xj pentru care [xi,xj]U.
Observaie. n cazul grafului neorientat, lista Li a vecinilor unui nod xi al grafului este
DI

format din nodurile xj adiacente nodului xi. n cazul grafului orientat, lista Li a vecinilor
unui nod xi al grafului este format din nodurile xj care sunt succesorii nodului xi.
Implementarea acestui tip de reprezentare se poate face: Graful neorientat G1
RA

static, folosind una dintre urmtoarele structuri de date: Nod Lista de adiacen
A. Matricea listei de adiacen 1 2, 3, 4
B. Vectorii listei de adiacen 2 1, 3, 5
dinamic, cu ajutorul listelor nlnuite. 3 1, 2, 4, 5
TU

4 1, 3
Implementarea static 5 2, 3
A. Matricea listei de adiacen L cu 2 linii i n+2m 6 7, 8
coloane pentru graful neorientat, respectiv cu n+m co- 7 6
I

loane pentru graful orientat, definit astfel: 8 6


ED
188 Implementarea structurilor de date

C
Prima linie conine etichetele nodurilor i listele de adiacen ale fiecrui nod; este
format din dou seciuni: Graful orientat G9
a. Primele n coloane conin etichetele nodurilor: Nod List de adiacen

I
L[0][i]=i (1in). 1 2

OG
b. Urmtoarele m2 coloane, respectiv m coloa- 2 1, 3, 4
ne, conin n ordine cele n liste de adiacen 3 5
ale celor n noduri. 4 2, 5
A doua linie conine informaiile necesare pentru a 5 3, 6

AG
identifica n prima linie lista de adiacen a fiecrui 6 5
nod; este format din dou seciuni:
a. Primele n coloane conin, n ordine, pentru fiecare nod i (1in), indicele
coloanei din prima linie din care ncepe lista de adiacen a nodului:
L[1][i]=j, unde j este indicele coloanei de unde ncepe lista de adiacen

ED
a nodului i. Dac nodul este izolat, se va memora valoarea 0 L[1][i]=0
(nu exist list de adiacen pentru acel nod).
b. Urmtoarele m2 coloane, respectiv m coloane, conin n ordine informaii
despre modul n care se nlnuiesc elementele din list. Dac nodul

P
L[0][i] se gsete n interiorul listei, atunci L[1][i]=i+1 (indicele
urmtorului element din list). Dac nodul L[0][i] se gsete la sfritul
I
listei, atunci L[1][i]=0 (s-a terminat lista de adiacen a nodului i).
Matricea este definit astfel:
a) pentru graful neorientat: int L[2][<n>+2*<m>];
b) pentru graful orientat: int L[2][<n>+<m>];

Graful neorientat G1
IC

Nodurile L1 L2 L3 L4 L5 L6 L7 L8

1 2 3 4 5 6 7 8 2 3 4 1 3 5 1 2 4 5 1 3 2 3 7 8 6 6
CT

9 12 15 19 21 23 25 26 10 11 0 13 14 0 16 17 18 0 20 0 22 0 24 0 0 0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
DA

Indicii coloanelor
Graful orientat G9
Nodurile L1 L2 L3 L4 L5 L6
1 2 3 4 5 6 2 1 3 4 5 2 5 3 6 8
DI

7 8 11 12 14 16 0 9 10 0 0 20 0 22 0 0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
RA

Indicii coloanelor
B. Vectorii listei de adiacen: un vector L cu dimensiunea m2, pentru graful neorien-
tat, respectiv cu dimensiunea m, pentru graful orientat, care conine listele de adia-
cen ale fiecrui nod, i un vector cap, cu dimensiunea n, care conine indicii de la
TU

care ncepe lista vecinilor fiecrui nod n vectorul L. Indicii din vectorul cap corespund
etichetelor nodurilor. Cei doi vectori sunt definii astfel:
a) pentru graful neorientat: int cap[<n>],L[2*<m>];
b) pentru graful orientat: int cap[<n>],L[<m>];
I
ED
Informatic 189

C
Graful neorientat G1
1 2 3 4 5 6 7 8

I
cap 1 4 7 11 13 15 17 18

OG
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
L 2 3 4 1 3 5 1 2 4 5 1 3 2 3 7 8 6 6

AG
L1 L2 L3 L4 L5 L6 L7 L8
Graful orientat G9
1 2 3 4 5 6

ED
cap 1 2 5 6 8 10

1 2 3 4 5 6 7 8 9 10

P
L 2 1 3 4 5 2 5 3 6 5

L1 L2 L3 L4 L5 L6
I
Observaie. Fiecare list de vecini Li, conine indicii coloanelor j n care se gsesc valori
de 1 n matricea de adiacen (a[i][j]=1).

Implementarea dinamic
Lista de adicen a fiecrui nod se memoreaz ntr-o list simplu nlnuit, ale crei ele-
IC

mente sunt de tip nod (informaia util memoreaz eticheta unui nod din list), iar adresa
primului element din fiecare list se memoreaz ntr-un vector L, care are lungimea logic
CT

egal cu numrul de noduri n i ale crui elemente sunt de tip pointer ctre tipul nod:
struct nod {int info;
nod * urm;};
nod *L[<n>];
DA

L
2
1
DI

1 3 4
2
5
3
RA

2 5
4
3 6
5 Graful orientat G9
TU

5
6
I
ED
190 Implementarea structurilor de date

C
L

2 3 4
1

I
OG
1 3 5
2
1 2 4 5
3

AG
1 3
4
2 3
5 Graful neorientat G1
7 8

ED
6
6
7

P
8 6 I
Aceast reprezentare este recomandat pentru grafurile care au un numr mare de
noduri i un numr mic de muchii.

Algoritmi pentru reprezentarea grafurilor folosind listele de adiacen


Din lista de adiacen implementat static cu matrice putei obine urmtoarele informaii:
IC

Graf neorientat Graf orientat


Lungimea listei de adiacen a nodului i Lungimea listei de adiacen a nodului i
neizolat, cu eticheta mai mic dect n, este neizolat, cu eticheta mai mic dect n, se
CT

egal cu diferena dintre primul indice j (j=i+1,n- calculeaz la fel ca i n cazul grafului
1) diferit de 0, din prima seciune a liniei a doua neorientat. Pentru nodul n lungimea listei de
(L[1][j]0), i indicele coloanei din care ncepe adiacen este egal cu (n+m+1 - L[1][n]).
lista de adiacen a nodului i (L[1][j] - L[1][i]). Gradul extern al nodului i este egal cu
DA

Pentru nodul n, lungimea listei de adiacen lungimea listei de adiacen a nodului.


este egal cu diferena dintre numrul total de Gradul intern al nodului i este egal, cu
coloane, plus 1, i indicele coloanei din care numrul de apariii ale etichetei nodului n a
ncepe lista de adiacen a nodului n (n+2m+1 doua seciune a primei linii a matricei (L[0][j]=i,
DI

- L[1][n]). Lungimea listei de adiacen se mai cu j=n+1,n+m).


poate determina prin numrarea n linia a doua
a elementelor diferite de 0, ncepnd cu
elementul din coloana L[1][i]), la care se
RA

adaug 1.
Gradul unui nod i este egal cu lungimea listei
de adiacen a nodului sau cu numrul de
apariii ale etichetei nodului n a doua seciune a
primei linii a matricei (L[0][j]=i, cu
TU

j=n+1,n+2*m).
Nodurile adiacente nodului i sunt nodurile a Succesorii nodului i sunt nodurile a cror
cror etichet apare n lista de adiacen a etichet apare n lista de adiacen a nodului i.
nodului i. Predecesorii nodului i sunt nodurile j n a
I

cror list de adiacen apare nodul i.


ED
Informatic 191

C
Graf neorientat Graf orientat
Nodurile adiacente nodului i sunt date de
reuniunea dintre mulimea succesorilor i

I
mulimea predecesorilor nodului.

OG
Numrul de vecini ai nodului i este egal cu Numrul de vecini ai nodului i este egal cu
gradul nodului. cardinalul mulimii de noduri adiacente nodului i.
Muchia [i,j] a grafului reprezint nodul i i un nod j Arcul [i,j] al grafului reprezint nodul i i un nod
din lista de adiacen a nodului i din prima linie a j din lista de adiacen a nodului i din vectorul L
matricei (L[0][j]Li). (L[0][j]Li)

AG
Din lista de adiacen implementat static cu doi vectori putei obine urmtoarele informaii:
Graf neorientat Graf orientat
Lungimea listei de adiacen a nodului i Lungimea listei de adiacen a nodului i

ED
neizolat, cu eticheta mai mic dect n, este neizolat, cu eticheta mai mic dect n, se
egal cu diferena dintre primul indice j (j=i+1,n-1) calculeaz la fel ca i n cazul grafului
diferit de 0, din vectorul cap (cap[j]0), i neorientat. Pentru nodul n, lungimea listei de
indicele elementului de la care ncepe lista de adiacen este egal cu (m+1 - cap[n]).

P
adiacen a nodului i (cap[j] - cap[i]). Pentru Gradul extern al nodului i este egal cu
nodul n, lungimea listei de adiacen este egal lungimea listei de adiacen a nodului.
cu diferena dintre numrul total de elemente Gradul intern al nodului i este egal cu
I
ale vectorul L, plus 1, i indicele elementului din numrul de apariii ale etichetei nodului n
care ncepe lista de adiacen a nodului n vectoul listei L (L[j]=i, cu j=1,m).
(2m+1 - cap[n]).

Gradul unui nod i este egal cu lungimea listei


de adiacen a nodului sau cu numrul de
IC

apariii ale etichetei nodului n vectorul listei L


(L[j]=i, cu j=1,2*m).
Nodurile adiacente nodului i sunt nodurile a Succesorii nodului i sunt nodurile a cror
CT

cror etichet apare n lista de adiacen a etichet apare n lista de adiacen a nodului i
nodului i din vectorul L. din vectorul L.
Predecesorii nodului i sunt nodurile j n a
cror list de adiacen din vectorul L apare
DA

nodul i.
Nodurile adiacente nodului i sunt date de
reuniunea dintre mulimea succesorilor i
mulimea predecesorilor nodului.
Numrul de vecini ai nodului i este egal cu Numrul de vecini ai nodului i este egal cu
DI

gradul nodului. cardinalul mulimii de noduri adiacente nodului i.


Muchia [i,j] a grafului reprezint nodul i i un nod j Arcul [i,j] al grafului reprezint nodul i i un nod
din lista de adiacen a nodului i din vectorul L j din lista de adiacen a nodului i din vectorul L
(L[j]Li). (L[j]Li).
RA

Din lista de adiacen implementat dinamic putei obine urmtoarele informaii:


Graf neorientat Graf orientat
TU

Numrul de elemente din toate listele simplu Numrul de elemente din toate listele simplu
nlnuite este egal cu 2m (dublul numrului nlnuite este egal cu m (numrul de arce).
de muchii).
Lungimea listei de adiacen a nodului i este Lungimea listei de adiacen i este egal cu
egal cu numrul de noduri ale listei ce are numrul de noduri ale listei care are adresa
I
ED

adresa nodului prim egal cu L[i]. nodului prim egal cu L[i].


192 Implementarea structurilor de date

C
Graf neorientat Graf orientat
Gradul unui nod i este egal cu lungimea listei Gradul extern al nodului i este egal cu
de adiacen. lungimea listei de adiacen a nodului.

I
Gradul intern al nodului i este egal, cu

OG
numrul de apariii ale etichetei nodului n
toate listele simplu nlnuite.
Nodurile adiacente nodului i sunt nodurile a Succesorii nodului i sunt nodurile a cror
cror etichet apare n lista ce are adresa etichet apare n lista ce are adresa nodului
nodului prim egal cu L[i]. prim egal cu L[i].

AG
Predecesorii nodului i sunt nodurile j n ale
cror liste (ce au adresa nodului prim egal cu
L[j]) apare nodul i.
Nodurile adiacente nodului i sunt date de

ED
reuniunea dintre mulimea succesorilor i
mulimea predecesorilor nodului.
Numrul de vecini ai nodului i este egal cu Numrul de vecini ai nodului i este egal cu
gradul nodului. cardinalul mulimii de noduri adiacente nodului i.

P
Muchia [i,j] a grafului reprezint nodul i i un nod j Arcul [i,j] al grafului reprezint nodul i i un nod j
din lista ce are adresa nodului prim egal cu L[i]. din lista ce are adresa nodului prim egal cu L[i].

1. Scriei lista de adiacen (folosind cele trei metode de implementare) a


I
Tem grafului neorientat G4. Folosind informaiile din lista de adiacen,
determinai: gradul nodului 5, nodurile izolate i nodurile terminale.
2. Scriei lista de adiacen a grafului orientat G14. Se vor folosi cele trei metode de

implementare. Ce proprietate are acest graf?


3. Scriei lista de adiacen a grafului orientat G8 (folosind cele trei metode de implemen-
IC

tare). Folosind informaiile din lista de adiacen, determinai: gradul intern al nodului 5,
gradul extern al nodului 4, succesorii i predecesorii nodului 2 i predecesorii nodului 3.
4. Scriei lista de adiacen a grafului orientat G11. Se vor folosi cele trei metode de imple-
CT

mentare. Din lista de adiacen, determinai: gradul intern al nodului 5, gradul extern al
nodului 2, nodurile adiacente nodului 5, succesorii i predecesorii nodului 4, nodurile
terminale i nodurile izolate.
G
G
G111888 5. Scriei lista de adiacen a grafului orientat G18 din figura 13.
DA

Se vor folosi cele trei metode de implementare.


6. Scriei lista de adiacen a grafului G13. Se vor folosi cele trei
metode de implementare. Cum identificai n fiecare imple-
mentare a listei de adiacen nodul surs al grafului? Fig 13
DI

7. Scriei lista de adiacen a grafului G14. Se vor folosi cele


trei metode de implementare. Cum identificai n fiecare implementare a listei de
adiacen nodul destinaie al grafului?
RA

Implementarea algoritmilor pentru reprezentarea grafurilor cu lista de adiacen


1. Crearea listei de adiacen n implementare static prin citirea listelor de vecini
din fiier. Determinarea gradului unui nod. Obinerea matricei de adiacen din
TU

matricea listei de adiacen.


ntr-un fiier text se gsesc urmtoarele informaii despre un graf neorientat (i varianta
orientat): pe prima linie, valorile pentru numrul de noduri n i numrul de muchii m,
desprite prin spaiu, iar pe urmtoarele n linii, desprite prin spaiu, numrul de vecini ai
I

unui nod i lista vecinilor (i varianta numrul de succesori ai unui nod i lista succesorilor).
ED
Informatic 193

C
Se citesc din fiierul text aceste informaii i se creeaz lista de adiacen implementat cu
matrice, respectiv cu vectori. Se afieaz nodurile cu gradul cel mai mare (i varianta cu
gradul extern cel mai mare). Se obine matricea de adiacen din lista de adiacen. Se

I
salveaz apoi matricea de adiacen ntr-un fiier text. n fiierul text se scriu: pe primul

OG
rnd ordinul grafului, iar pe urmtoarele rnduri liniile matricei de adiacen. Funcia
citeste() se folosete pentru a citi listele de adiacen din fiier, funcia grad() pentru
a determina gradul (i varianta gradul extern) al unui nod, funcia grad max() pentru a
determina gradul maxim (i varianta gradul extern maxim) al nodurilor din graf, funcia

AG
transpune() pentru a obine matricea de adiacen din lista de adiacen, iar funcia
scrie() pentru a scrie matricea de adiacen n fiier. Informaiile se citesc din fiierul text
graf13.txt, pentru graful neorientat, i graf14.txt, pentru graful orientat, i se salveaz n
fiierul text graf15.txt, pentru graful neorientat, i graf16.txt, pentru graful orientat. Fiierele
text graf13.txt i graf14.txt se creeaz cu un editor de texte. Pentru testarea programelor se

ED
folosesc graful neorientat G1 i graful orientat G9.
Graful neorientat i graful orientat implementarea cu matrice
#include<fstream.h>

P
int n,m,L[3][50],a[10][10];
//pentru graful neorientat
fstream f1("graf13.txt",ios::in),f2("graf15.txt",ios::out);
I
//pentru graful orientat
//fstream f1("graf14.txt",ios::in),f2("graf16.txt",ios::out);
void citeste()
{int i,j,x,k; f1>>n>>m;

for(i=1;i<=n;i++) L[1][i]=i; j=n+1;


for(i=1;i<=n;i++)
IC

{f1>>x;
if (x==0) L[2][i]=0;
else {L[2][i]=j;
CT

for (k=1;k<=x;k++) {f1>>L[1][j];


if(k!=x) L[2][j]=j+1;
else L[2][j]=0;
j++;}}}
DA

f1.close();}
int grad(int i)
{int g,j=L[2][i];
if (L[2][i]==0) g=0;
else {g=1;
DI

while (L[2][j]!=0) {g++;j++;}}


return g;}
int grad max()
{int i,max=0;
RA

for (i=1; i<=n; i++) if (grad(i)>max) max=grad(i);


return max;}
void transpune()
{int i,j;
TU

for (i=1; i<=n; i++)


{j=L[2][i];
if (L[2][i]!=0)
{while (L[2][j]!=0) {a[i][L[1][j]]=1; j++;}
I

a[i][L[1][j]]=1;}}}
ED
194 Implementarea structurilor de date

C
void scrie()
{int i,j; f2<<n<<endl;
for (i=1; i<=n; i++)

I
{for (j=1; j<=n; j++) f2<<a[i][j]<<" "; f2<<endl;}

OG
f2.close();}
void main()
{int i; citeste();
cout<<"Gradul cel mai mare este "<<grad max()<<endl;
cout<<"Nodurile cu gradul cel mai mare sunt: ";

AG
for (i=1; i<=n; i++) if (grad(i)==grad_max()) cout<<i<<" ";
transpune(); scrie();}
Graful neorientat i graful orientat implementarea cu vectori.
#include<fstream.h>

ED
int n,m, L[50],a[10][10],cap[10];
//pentru graful neorienat
fstream f1("graf13.txt",ios::in),f2("graf15.txt",ios::out);
//pentru graful orienat

P
//fstream f1("graf14.txt",ios::in),f2("graf16.txt",ios::out);
void citeste()
{int i,j=1,x,k; f1>>n>>m;
I
for(i=1;i<=n;i++)
{f1>>x;
if (x==0) cap[i]=0;
else {cap[i]=j;

for (k=1;k<=x;k++) {f1>>L[j]; j++;}}}


f1.close();}
IC

int grad(int i)
{int g,j;
if (cap[i]==0) g=0;
CT

else
{if (i<n) {j=i+1;
while (cap[j]==0 && j<=n) j++;
if (j==n+1) g=2*m+1-cap[i];
DA

// g=m+1-cap[i]; pentru graful orientat


else g=cap[j]-cap[i];}
else g=2*m+1-cap[i];}
return g;}
int grad max() {//este identic cu cea de la implementarea cu matrice}
DI

void transpune()
{int i,j;
for (i=1; i<=n; i++)
for (j=0;j<grad(i);j++) a[i][L[cap[i]+j]]=1;}
RA

void scrie() {//este identic cu cea de la implementarea cu matrice}


void main() {//este identic cu cea de la implementarea cu matrice}
2. Crearea listei de adiacen n implementare static din matricea de adiacen.
TU

Salvarea listelor de adiacen ntr-un fiier.


Se citete din fiierul creat anterior (graf15.txt, respectiv graf16.txt) matricea de adiacen a
grafului i se obine din ea lista de adiacen implementat cu matrice, respectiv cu vectori.
Se salveaz listele de adiacen ntr-un fiier text (graf17.txt, respectiv graf18.txt), astfel: pe
I

prima linie, valorile pentru numrul de noduri n i numrul de muchii m, desprite prin
ED
Informatic 195

C
spaiu, iar apoi, pe urmtoarele n linii, desprite prin spaiu, numrul de vecini ai unui nod
i lista vecinilor pentru graful neorientat, respectiv numrul de succesori ai unui nod i lista
succesorilor pentru graful orientat. Funcia citeste() se folosete pentru a citi matricea

I
de adiacen din fiier, funcia transpune() pentru a obine lista de adiacen din

OG
matricea de adiacen, iar funcia scrie() pentru a scrie listele de adiacen n fiier.
Pentru testarea programelor se folosesc graful neorientat G1 i graful orientat G9.
Graful neorientat i graful orientat implementarea cu matrice
#include<fstream.h>

AG
int n,m,L[3][50],a[10][10];
//pentru graful neorientat
fstream f1("graf15",ios::in),f2("graf17.txt",ios::out);
//pentru graful orientat

ED
//fstream f1("graf16.txt",ios::in),f2("graf18.txt",ios::out);
void citeste()
{int i,j; f1>>n;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) {f1>>a[i][j]; if(a[i][j]==1) m++;} f1.close();

P
m=m/2;} //numai pentru graful neorientat
void transpune()
{int i,j,k,g;
I
for(i=1;i<=n;i++) L[1][i]=i; k=n+1;
for(i=1;i<=n;i++)
{for(j=1,g=0;j<=n;j++)
if (a[i][j]==1) {L[1][k]=j; L[2][k]=k+1; k++; g++;}

if (g==0) L[2][i]=0;
else {L[2][i]=k-g; L[2][k-1]=0;}}}
IC

int grad(int i) {//identic cu cea de la implementarea cu matrice}


void scrie()
{int i,j=1,k; f2<<n<<" "<<m<<endl;
CT

for (i=1;i<=n;i++)
if (L[2][i]==0) f2<<0<<endl;
else {f2<<grad(i)<<" ";
for (k=1;k<=grad(i);k++,j++) f2<<L[1][j]<<" ";
DA

f2<<endl;} f2.close();}
void main()
{citeste(); transpune(); scrie();}
Graful neorientat i graful orientat implementarea cu vectori
DI

#include<fstream.h>
int n,m,L[50],cap[10],a[10][10];
//pentru graful neorientat
fstream f1("graf13.txt",ios::in),f2("graf15.txt",ios::out);
RA

//pentru graful orientat


//fstream f1("graf14.txt",ios::in),f2("graf16.txt",ios::out);
void citeste() {//este identic cu cea de la implementarea cu matrice}
void transpune()
TU

{int i,j,k=1,g;
for(i=1;i<=n;i++)
{for(j=1,g=0;j<=n;j++) if (a[i][j]==1) {L[k]=j; k++; g++;}
if(g==0) cap[i]=0; else cap[i]=k-g;}}
I

int grad(int i) {//identic cu cea de la implementarea cu vectori}


ED
196 Implementarea structurilor de date

C
void scrie()
{int i,j; f2<<n<<" "<<m<<endl;
for(i=1;i<=n;i++)

I
{f2<<grad(i)<<" ";

OG
for(j=0;j<grad(i);j++) f2<<L[cap[i]+j]<<" ";
f2<<endl;}
f2.close();}
void main() {//este identic cu cea de la implementarea cu matrice}
3. Crearea listei de adiacen n implementare dinamic prin citirea listei muchiilor

AG
din fiier. Determinarea vecinilor i a gradului unui nod.
ntr-un fiier text se gsesc urmtoarele informaii despre un graf neorientat (i varianta
orientat): pe prima linie, valorile pentru numrul de noduri n i numrul de muchii m, iar de pe

ED
urmtoarele m linii, cte o pereche de numere desprite prin spaiu, care reprezint etiche-
tele nodurilor ce formeaz o muchie (arc). Se citesc din fiierul text aceste informaii i se
creeaz lista de adiacen implementat dinamic. Se afieaz vecinii i gradul fiecrui nod.
Funcia init() se folosete pentru a iniializa cu valoarea NULL elementele vectorului L

P
(pointerii nodului prim al listei de adiacen a fiecrui nod din graf), funcia adauga nod()
pentru a aduga un nod naintea nodului prim la lista simplu nlnuit a unui nod din graf,
funcia creare() pentru a crea lista de adiacen, funcia grad() pentru a determina
I
gradul (i varianta, gradul extern) al unui nod, funcia afisare_vecini() pentru a afia
vecinii fiecrui nod, iar funcia afisare_grad() pentru a afia gradul fiecrui nod. Infor-
maiile se citesc din fiierul text graf11.txt pentru graful neorientat i graf12.txt pentru graful
orientat. Pentru testarea programelor se folosesc graful neorientat G1 i graful orientat G9.

#include<fstream.h>
struct nod {int info;
IC

nod * urm;};
nod *L[20];
int n,m;
CT

fstream f1("graf11.txt",ios::in);
void init()
{f>>n>>m; for (int i=1;i<=n;i++) L[i]=NULL;}
void adauga nod(nod *&prim, int y)
DA

{nod *p=new nod; p->info=y; p->urm=prim; prim=p;}


void creare()
{int x,y;
while (f>>x>>y) {adauga nod(L[x],y);adauga nod(L[y],x);}
DI

f.close();}
void afisare vecini()
{for (int i=1;i<=n;i++)
{cout<<"Vecinii nodului "<<i<<": ";
RA

for (nod *p=L[i];p!=NULL;p=p->urm) cout<<p->info<<" ";


cout<<endl;}}
int grad(int i)
{int g=0;
for (nod *p=L[i];p!=NULL; p=p->urm) g++; return g;}
TU

void afisare grade()


{for (int i=1;i<=n;i++)
cout<<"Gradul nodului "<<i<<": "<<grad(i)<<endl;}
void main()
I

{init(); creare(); afisare vecini(); afisare grade();}


ED
Informatic 197

C
1. Scriei un program care citete listele de adiacen ale grafului din
Tem fiierul text graf13.txt, pentru graful neorientat, respectiv din fiierul
graf14.txt, pentru graful orientat, i care afieaz nodurile izolate.

I
Listele de adiacen se implementeaz dinamic i static, n cele dou variante.

OG
2. Scriei un program care citete listele de adiacen ale grafului din fiierul text graf13.txt,
pentru graful neorientat, respectiv din fiierul graf14.txt, pentru graful orientat, i care
afieaz muchiile (arcele) grafului. Listele de adiacen se implementeaz dinamic i
static n cele dou variante.

AG
3. Scriei un program care citete din dou fiiere text, respectiv din g5.txt un graf orientat,
reprezentat prin lista muchiilor, i din fiierul g6.txt un graf orientat, reprezentat prin lista
vecinilor, i care verific dac cele dou grafuri sunt identice (Indicaie. Se reprezint
ambele grafuri prin matricea de adiacen i se compar cele dou matrice de adiacen).

ED
2.7.4.5. Aplicaii practice
1. ntr-un grup de n persoane s-au stabilit dou tipuri de relaii: de prietenie i de vecin-
tate. Scriei un program care s citeasc matricele de adiacen ale celor dou grafuri

P
dintr-un fiier text (pe primul rnd, numrul de persoane, i pe urmtoarele rnduri, n
ordine, liniile fiecrei matrice de adiacen) i care s afieze:
a. persoanele care sunt i prietene i vecini (Indicaie. Se determin muchiile din
I
graful intersecie a celor dou grafuri neorientate);
b. cel mai mare numr de persoane care se gsesc ntr-un grup de vecini prieteni
(Indicaie. Se determin gradul maxim n graful intersecie a celor dou grafuri.)

Pentru testarea programului formai un grup cu 10 dintre colegii votri i descriei cu


ajutorul a dou grafuri cele dou tipuri de relaii.
IC

2. ntr-un grup de n persoane s-a stabilit o relaie de cunotin: persoana x este n


relaie cu persoana y dac o cunoate pe aceasta. Relaia de cunotin nu este
CT

reciproc. O celebritate este o persoan care este cunoscut de toate persoanele din
grup, dar care nu cunoate nici o persoan (este un nod destinaie al grafului). Un
necunoscut este o persoan care cunoate toate persoanele din grup dar nu este
cunoscut de nici o persoan din grup (este un nod surs al grafului). Un singuratic
DA

este o persoan care cunoate o singur persoan din grup sau este cunoscut de o
singur persoan din grup (este un nod terminal al grafului). Un strin de grup este o
persoan care nu cunoate nici o persoan din grup i nu este cunoscut de nici o
persoan din grup (este un nod izolat al grafului). Demonstrai c n grup nu poate
DI

exista dect o singur celebritate i un singur necunoscut. Scriei un program care s


citeasc dintr-un fiier matricea de adiacen a grafului i care s afieze:
a. dac exist o celebritate, s se precizeze persoana, iar dac nu exist, s se
precizeze: persoana care cunoate cele mai puine persoane i persoana care este
RA

cunoscut de cele mai multe persoane;


b. dac exist un necunoscut, s se precizeze persoana, iar dac nu exist, s se
precizeze: persoana care este cunoscut de cele mai puine persoane i per-
soana care cunoate cele mai multe persoane;
TU

c. dac exist singuratici, s se precizeze persoanele;


d. dac exist strini de grup, s se precizeze persoanele;
e. cte persoane cunosc doar dou persoane din grup i sunt cunoscute la rndul
lor de trei persoane din grup (nodurile care au gradul intern egal cu 3, iar gradul
I
ED

extern egal cu 2);


198 Implementarea structurilor de date

C
f. cte persoane sunt cunoscute de un numr de membri egal cu numrul de
membri pe care i cunosc (nodurile care au gradul intern egal cu gradul extern);
g. care sunt persoanele care se cunosc reciproc (perechile de noduri ntre care

I
exist arce duble).

OG
3. La graful judeelor, adugai un nod cu eticheta 0, care reprezint exteriorul rii, i
muchiile corespunztoare, care evideniaz judeele limitrofe. Creai cu un editor de
texte fiierul judete.txt care s conin urmtoarele informaii: pe primul rnd, numrul de
judee, pe urmtoarele rnduri matricea de adiacen, pe urmtorul rnd, n ordinea

AG
etichetelor nodurilor, denumirile judeelor separate prin spaiu (pentru judeele care au
un nume format din mai multe cuvinte folosii ca separator linia de subliniere), pe
urmtorul rnd numele vecinilor Romniei separate prin spaiu, i apoi, cte un rnd
pentru fiecare jude limitrof, n care scriei separate prin spaiu urmtoarele informaii:

ED
eticheta nodului i ara (rile) cu care se nvecineaz, precizate prin numrul de ordine
din lista numelor. Scriei un program care s citeasc aceste informaii din fiier i s le
transpun ntr-o implementare a grafului, adecvat problemei, i care s afieze:
a. judeele care au cele mai multe judee vecine se va preciza numrul maxim de vecini

P
i numele judeelor care au aceast proprietate;
b. judeele care au cele mai puine judee vecine se va preciza numrul minim de vecini
i numele judeelor care au aceast proprietate;
I
c. judeele de la grani pentru fiecare jude se va preciza numele su i numele rilor
cu care se nvecineaz.
4. ntr-o zon turistic exist n localiti. ntre unele localiti exist legturi directe, fie

prin osele naionale, fie prin osele judeene. Legturile directe sunt caracterizate de
lungimea drumului, msurat n kilometri. Se vor folosi dou grafuri: Gn=(X,Un) pentru
IC

legturile prin osele naionale i Gj=(X,Uj) pentru legturile prin osele judeene. Cele
dou grafuri se vor citi din dou fiiere text, care conin pentru fiecare legtur direct,
pe cte un rnd, separate prin spaiu, cele dou etichete ale nodurilor asociate
CT

localitilor i distana dintre localiti. Scriei un program care s citeasc aceste


informaii din fiier i s le transpun ntr-o implementare a grafului, adecvat proble-
mei, i care s afieze:
DA

a. localitile la care nu ajung drumuri naionale (nodurile izolate, n primul graf);


b. cea mai scurt legtur direct dintre dou localiti se va preciza eticheta
nodurilor asociate localitilor, distana dintre localiti i tipul oselei prin care se
asigur legtura;
DI

c. pentru dou localiti precizate, a i b (etichetele nodurilor a i b se citesc de la


tastatur), s se precizeze dac exist legtur direct; dac exist, s se mai
precizeze tipul oselei i distana dintre localiti;
d. pentru o localitate p (eticheta p a nodului se citete de la tastatur), s se afieze
RA

toate localitile cu care are legturi directe i distana pn la aceste localiti


(Indicaie. Se determin graful reuniune a celor dou grafuri.);
e. localitatea care are cele mai multe legturi directe cu alte localiti i s se
afieze localitile cu care are legturi (nodul cu gradul maxim n graful reuniune).
TU

5. ntr-un munte exist n grote. Fiecare grot i se gsete la nlimea hi fa de baza


muntelui. ntre unele grote exist comunicare direct, prin intermediul unor tuneluri.
Exist i grote care comunic cu exteriorul. Desenai o reea ipotetic de grote i con-
I

struii matricea de adiacen a grafului neorientat asociat (grotele sunt nodurile, iar
ED
Informatic 199

C
tunelurile sunt muchiile). nlimile grotelor se vor memora ntr-un vector. Gsii o
modalitate de a evidenia grotele care comunic cu exteriorul. (Indicaie. Adugai la
graf nodul 0, care reprezint exteriorul muntelui.) Scriei matricea de adiacen i

I
vectorul cu nlimile grotelor, n fiierul text grote.txt. Scriei un program care s

OG
citeasc matricea de adiacen i vectorul din fiier i care s afieze:
a. numrul de tuneluri de comunicare (numrul de muchii ale grafului);
b. grotele care au legtur cu exteriorul (nodurile i pentru care exist muchie cu
nodul 0);

AG
c. grotele care comunic direct cu cele mai multe grote (nodurile cu cel mai mare grad);
d. grotele care nu comunic prin tuneluri cu alte grote (nodurile izolate);
e. cea mai nalt grot i cea mai joas grot care comunic cu exteriorul;
f. pentru o grot a crei etichet se citete de la tastatur, s se afieze grotele cu
care comunic direct, preciznd pentru fiecare tunel dac suie, coboar sau este

ED
la acelai nivel cu grota.
6. Reeaua de strzi dintr-un ora este format din strzi cu dou sensuri i strzi cu sens
unic de circulaie. Ea poate fi reprezentat printr-un graf orientat, n care interseciile sunt

P
nodurile, iar arcele sensul de circulaie pe strzile care leag dou intersecii (traficul
auto). Nodurile sunt intersecii de cel puin 3 strzi. Pentru a stabili prioritatea n intersecii
i pentru a fluidiza traficul interseciile vor fi modernizate. Pentru modernizare se vor folosi
I
panouri cu semne de circulaie, semafoare i se vor amenaja sensuri giratorii. Pentru
fiecare strad din care se poate intra n intersecie, se monteaz n intersecie un panou
cu semn pentru prioritate. Pentru fiecare strad pe care nu se poate intra din intersecie se
monteaz n intersecie un panou cu semnul de interzicere a circulaiei. n toate

interseciile vor fi montate panouri cu semne de circulaie, corespunztor strzilor incidente


IC

cu intersecia. Fiecare dintre aceste mijloace de modernizare are un cost: panoul cu semn
de circulaie costul c1, semaforul costul c2, i sensul giratoriu costul c3. Pentru a
stabili modul n care este modernizat fiecare intersecie, interseciile au fost clasificate n
CT

intersecii mici (intersecii cu 3 strzi, n care vor fi montate numai panouri cu semne de
circulaie), intersecii mari (intersecii cu 4 strzi, care vor fi semaforizate) i intersecii
foarte mari (intersecii cu peste 4 strzi, n care se vor amenaja sensuri giratorii). Desenai
o reea ipotetic de strzi i construii matricea de adiacen a grafului orientat asociat.
DA

Scriei matricea de adiacen n fiierul text strazi.txt. Scriei un program care s citeasc
matricea de adiacen din fiier i care s afieze:
a. interseciile la care nu se poate ajunge din nici o alt intersecie (nodurile care nu
au predecesori);
DI

b. interseciile de la care nu se poate ajunge la o nici o alt intersecie (nodurile care


nu au succesori);
c. dac exist intersecii fr nici o intersecie succesor sau fr nici o intersecie prede-
cesor, s se corecteze desenul reelei (prin adugarea unui numr minim de arce),
RA

astfel nct s nu existe asemenea intersecii i s se actualizeze i fiierul strazi.txt.


d. interseciile la care se poate ajunge direct din cele mai multe intersecii (nodurile
care au cel mai mare grad intern);
e. interseciile de la care se poate ajunge direct la cele mai multe intersecii
TU

(nodurile care au cel mai mare grad extern);


f. numrul de strzi pe care se circul n ambele sensuri (numrul de perechi de
noduri i i j pentru care, n matricea de adiacen, elementele a[i][j] i a[j][i] sunt
egale cu 1);
I
ED
200 Implementarea structurilor de date

C
g. numrul de intersecii mici, mari i foarte mari (clasificarea nodurilor n funcie de
numrul de noduri adiacente: noduri cu 3 noduri adiacente, cu 4 noduri adiacente
i cu cel puin 5 noduri adiacente);

I
h. numrul de panouri cu semne pentru prioritate care se vor folosi (suma gradelor

OG
interne ale nodurilor);
i. numrul de panouri cu semne pentru interzicerea circulaiei care se vor folosi
(diferena dintre suma gradelor externe ale nodurilor i numrul de strzi cu sens
dublu de circulaie);

AG
j. numrul de semafoare care se vor monta (suma gradelor interne ale nodurilor
care au 4 noduri adiacente);
k. costul de modernizare necesar pentru fiecare intersecie i costul total al moder-
nizrii.

ED
7. Pe un munte exist mai multe parcele cu fnee ale stenilor. Unele fnee au acces
direct la drumul stesc, altele nu. ntre proprietarii parcelelor vecine exist relaie de
prietenie sau nu. Dac doi proprietari vecini sunt prieteni, i permit unul altuia
accesul pe propria parcel. Pentru a transporta fnul, stenii care nu au acces la

P
drumul stesc, trebuie s treac peste parcelele altor steni, ca s ajung la el. Un
proprietar este considerat izolat dac nu are acces direct la drumul stesc i nici nu
este n relaie de prietenie cu vreunul dintre vecinii lui. Se vor folosi dou grafuri: unul
I
pentru a reprezenta relaia de vecintate a fneelor, iar altul pentru a reprezenta
relaia de prietenie dintre proprietari. Desenai o hart ipotetic a fneelor i stabilii
relaii ipotetice de prietenie ntre vecini. Construii matricele de adiacen ale celor

dou grafuri asociate. Scriei matricele de adiacen n fiierele text fanete.txt i


prieteni.txt. Scriei un program care s citeasc matricele de adiacen din fiiere i
IC

care s furnizeze urmtoarele informaii:


a. dac exist proprietari izolai, s se afieze lista proprietarilor vecini cu care
trebuie s stabileasc relaii de prietenie, pentru a ajunge la drumul stesc, i s
CT

se identifice vecinii care au acces direct la drumul stesc;


b. care este proprietarul cel mai neprietenos (care are cel mai mare procent de
vecini cu care nu este prieten).
DA

8. Se analizeaz migraia unei specii de psri cltoare pe perioada unui an. Migraia are
dou etape: migraia de toamn, cnd psrile migreaz din zonele reci ctre zonele
calde (migraia de la rece la cald), i migraia de primvar, cnd psrile migreaz din
zonele calde ctre zonele reci (migraia de la cald la rece). Fiecare etap a migraiei va
DI

fi reprezentat printr-un graf orientat. n graful migraiei de la rece la cald, nodurile care
aparin zonei reci au numai succesori, iar nodurile care aparin zonei calde au numai
predecesori. n graful migraiei de la cald la rece nodurile care aparin zonei calde au
numai succesori, iar nodurile care aparin zonei reci au numai predecesori. Fiecrui nod
RA

i se asociaz coordonatele geografice. Desenai cte o hart ipotetic pentru fiecare


etap de migraie. Construii, cu un editor de texte, fiierul migratie1.txt, care va conine
pe prima linie n1, numrul de noduri ale primului graf, pe urmtoarele n1 linii, matricea
de adiacen a grafului, i apoi, pe urmtoarele n1 linii, coordonatele geografice ale
TU

fiecrui nod de pe hart (sunt 6 entiti de informaie, separate prin spaiu: dou valori
numerice ntregi pentru latitudine, n grade i minute, i un caracter pentru emisfer,
dou valori numerice ntregi pentru longitudine, n grade i minute, i un caracter pentru
meridian). Construii cu un editor de texte fiierul migratie2.txt, care va conine acelai
I

tip de informaii, pentru cel de al doilea graf al migraiei. Scriei un program care s
ED
Informatic 201

C
citeasc aceste informaii din fiier, s le transpun ntr-o implementare a grafului
adecvat problemei (recomandare implementare prin matrice de adiacen i vector
de structuri pentru coordonatele geografice) i care s afieze urmtoarele informaii:

I
a. dac cele dou grafuri sunt corecte (dac a[i][j]=1, atunci a[j][i]=0 i produsul

OG
dintre gradul intern i gradul extern ale fiecrui nod trebuie s fie 0; n plus,
trebuie ca nodurile din zona cald s coincid n ambele grafuri);
b. dac n graful migraiei de la rece la cald exist un nod destinaie al grafului i
ce semnificaie are existena lui pentru migraie;

AG
c. dac psrile s-au rentors n aceleai zone, primvara (nodurile din zona rece
coincid n cele dou grafuri); n caz contrar, s se specifice noile locaii aprute n
zona rece n care a ajuns specia respectiv;
d. s se obin matricea de adiacen a hrii migraiei, pe ntreaga perioad a anului,

ED
prin reuniunea celor dou grafuri (dac dup migraia de primvar au aprut noi
locaii pe hart n zona rece, se vor aduga la primul graf ca noduri izolate).

2.7.5. Grafuri speciale

P
Se definesc urmtoarele grafuri speciale:
graful nul;
I
graful complet.
2.7.5.1. Graful nul
Graful G=(X,U) se numete graf nul dac mulimea U este vid (U=),

adic graful nu are muchii.


IC

Reprezentarea sa n plan se face prin noduri izolate.


Exemplu:
Graful N=(X,V) unde mulimea X={1,2,3,4} este mulimea nodurilor, iar
CT

mulimea V= este mulimea muchiilor este un graf nul (graful are noduri dar
nu are muchii) figura 14.
Fig. 14
Observaie. Matricea de adiacen a unui graf nul este matricea zero (nu
DA

conine nici un element cu valoarea 1).

2.7.5.2. Graful complet


Un graf cu n noduri este un graf complet dac are proprietatea c, oricare ar fi dou
DI

noduri ale grafului, ele sunt adiacente. El se noteaz cu Kn.


Observaii.
1. Se poate construi un singur graf neorientat complet, cu n noduri, deoare-
RA

ce ntre dou noduri, x i y, exist o singur muchie [x,y]. n figura 15 este


prezentat graful neorientat complet K4. El are 6 muchii. Desenai grafurile
neorientate complete K5 i K6. Numrai cte muchii au aceste grafuri. Fig. 15
TU

Teorema 6
Numrul m de muchii ale unui graf neorientat complet, cu n noduri (Kn), este:
n1
m n
I

2
ED
202 Implementarea structurilor de date

C
Demonstraie. Numrul de muchii este dat de numrul de submulimi de 2 elemente care se pot
2
forma dintr-o mulime cu n elemente, adic m = C n .

I
2. Se pot construi mai multe grafuri orientate complete, cu n noduri, deoarece dou

OG
noduri x i y pot fi adiacente n trei situaii: exist arcul [x,y], exist arcul [y,x] sau exist
arcele [x,y] i [y,x].
Teorema 7
Numrul de grafuri orientate complete care se pot construi cu n noduri este egal cu

AG
2
n k 3Cn
Demonstraie. Deoarece numrul de submulimi de 2 noduri care se pot forma dintr-o mulime de n
2

ED
noduri este a= C n , i pentru fiecare pereche astfel definit se pot defini trei situaii de adiacen,
a
rezult c numrul de grafuri complete care se pot construi este de 3 .
Exemplu. Pentru n=4 se pot
defini 36=729 grafuri orientate

P
complete. n figura 16 sunt pre-
zentate patru dintre acestea.
I
Definii alte patru grafuri com-
plete cu 4 noduri. Fig. 16
Observaii

1. n cazul matricei de adiacen a unui graf neorientat complet, valoarea fiecrui


element care nu se gsete pe diagonala principal este 1.
IC

2. n cazul matricei de adiacen a unui graf orientat complet pentru orice pereche de
noduri, i i j, diferite ntre ele (ij) a[i][j]=1 sau a[j][i]=1.
3. Numrul minim de arce ntr-un graf orientat complet cu n noduri este egal cu
CT

numrul de muchii ale grafului neorientat complet Kn.


4. Numrul maxim de arce ntr-un graf orientat complet cu n noduri este egal cu dublul
numrului de muchii ale grafului neorientat complet Kn.
DA

Algoritmi pentru prelucrarea grafurilor complete


1. Algoritm pentru a determina numrul minim de arce care trebuie adugate la un
graf orientat, pentru a obine un graf orientat complet.
DI

Algoritmul. Se numr perechile de noduri i i j (ij) ntre care nu exist nici un arc.
Implementarea algoritmului n program, informaiile despre graful orientat se citesc din
fiierul text gc.txt: de pe prima linie numrul de noduri, i apoi, de pe urmtoarele rnduri
RA

matricea de adiacen.
#include<iostream.h>
int n,a[10][10];
fstream f("gc.txt",ios::in);
TU

void citeste() {//se citete matricea de adiacen din fiier}


void main()
{int i,j,m=0; citeste();
for(i=2;i<=n;i++)
I

for(j=1;j<i;j++) if(a[i][j]==0 && a[j][i]==0) m++;


ED

cout<<"Numarul de arce care trebuie adaugate este "<<m;}


Informatic 203

C
2. Algoritm pentru a determina numrul maxim de noduri izolate pe care poate s
le conin un graf neorientat care are n noduri i m muchii.
Algoritmul. Se identific graful complet care se poate forma astfel nct s consume

I
ct mai multe muchii (mmax) din cele m muchii ale grafului (mmaxm). Graful complet astfel

OG
obinut are n1 noduri:
n1 1
m max n1 m
2
Numrul de noduri n1 este partea ntreag din rdcina pozitiv a ecuiei de gradul II:

AG
1 1 8 m
n1
2
Pentru diferena de muchii rmase (m-mmax) mai este necesar un nod, pentru a lega aceste

ED
muchii de nodurile grafului complet care s-a format. Numrul de noduri izolate este: nn11.
#include<iostream.h>
#include<math.h>
void main()

P
{int m,n,n1; cout<<"muchii= "; cin>>m; cout<<"noduri= "; cin>>n;
n1=(int)((1+sqrt(1+8*m))/2);
cout<<"Numarul maxim de noduri izolate este "<<n-n1-1;}
I
1. Scriei un program care citete, din fiierul text graf_c1.txt, informaii
Tem despre un graf neorientat (de pe prima linie, numrul de noduri, apoi
matricea de adiacen), i care verific dac este un graf complet.

2. Scriei un program care citete, din fiierul graf_c2.txt, informaii despre un graf orientat
(de pe prima linie, numrul de noduri, apoi matricea de adiacen) i care verific
IC

dac este un graf complet.

2.7.6. Grafuri derivate dintr-un graf


CT

Se definesc urmtoarele grafuri:


graful parial;
subgraful;
graful complementar.
DA

2.7.6.1. Graful parial


Fie graful G = (X,U) i mulimea VU. Graful Gp = (X,V) se numete graf parial
DI

al grafului G.
Altfel spus, un graf parial al grafului G este el nsui sau un graf care s-a obinut prin
eliminarea unor muchii (arce) din graful G.
RA

Exemple:
1. Pentru graful neorientat G1 = (X1,U1), definit anterior, graful G1p = (X1,U1p), definit astfel: G
G
G111ppp
mulimea nodurilor este X1={1,2,3,4,5,6,7,8}.
mulimea muchiilor este U1p ={[1,2], [1,3], [1,4], [2,3], [2,5], [3,4], [6,7]}.
TU

este subgraf al grafului G1 figura 17.

Graful Graful parial


G1 G1p
I
ED

Fig. 17
204 Implementarea structurilor de date

C
G
G
G111000ppp 2. Pentru graful orientat G10=(X10,U10) definit anterior, graful G10p = (X10, U10p) definit astfel:
mulimea nodurilor este X10={1,2,3,4,5,6,7,8,9,10}.
mulimea arcelor este U10p ={[2,3], [2,5], [2,6], [2,7], [4,1], [7,2], [8,9], [9,8]}.

I
este subgraf al grafului G10 figura 18.

OG
Graful
Graful parial
G10 G10p

AG
Fig. 18

Teorema 8

ED
m
Numrul de grafuri pariale ale unui graf cu m muchii (arce) este egal cu 2 .
Demonstraie. Grafurile pariale se pot obine: fr eliminarea unei muchii (arc) obinndu-se
graful iniial; prin eliminarea unei muchii (unui arc) obinndu-se grafurile pariale cu m-1 muchii);
...; prin eliminarea a m-1 muchii (arce) obinndu-se grafurile pariale cu o muchie (un arc); i a

P
tuturor muchiilor (arcelor) obinndu-se un graf parial numai cu noduri i fr muchii (arce), adic
graful vid:
Numrul de grafuri pariale care se pot obine cu m muchii (arce): Cm
I
m
Numrul de grafuri pariale care se pot obine cu m-1 muchii (arce): Cm 1
m
Numrul de grafuri pariale care se pot obine cu m-2 muchii (arce):: Cm 2
m

.........................................................................................................
Numrul de grafuri pariale care se pot obine cu o muchie (un arc): C 1m
IC

Numrul de grafuri pariale care se pot obine fr nici o muchie (nici un arc): 0
Cm
1 2 m
Numrul total de grafuri pariale este: Cm
m + Cm
m + Cm
m ++ C 1m + 0
Cm =2 .
CT

Algoritmi pentru prelucrarea grafurilor pariale


1. Generarea tuturor grafurilor pariale ale unui graf neorientat.
DA

Algoritmul. Se folosete metoda backtracking. n stiv se vor genera muchiile grafului


parial. Deoarece graful parial poate avea p muchii (0pm), se va apela repetat subpro-
gramul bt(), la fiecare apel generndu-se variantele cu p muchii. Fiecare apel al subpro-
gramului bt() trebuie s genereze C pn de muchii (arce) din graf. La fiecare apel al subpro-
DI

gramului, soluia se obine atunci cnd n stiv s-au generat cele p muchii ale grafului
parial. Evidena muchiilor este pstrat n matricea de inciden.
Implementarea algoritmului. Se citete din fiierul text graf15.txt matricea de adiacen
a unui graf neorientat. Pentru fiecare graf parial se afieaz muchiile. Matricea de inci-
RA

den b se obine din matricea de adiacen cu funcia transformare(). n variabila nr


se contorizeaz numrul de grafuri pariale generate. n funcia tipar() se afieaz
graful parial generat. Pentru testarea programului se folosete graful G1.
TU

#include<iostream.h>
fstream f("graf13.txt",ios::in);
typedef int stiva[100];
int n,m,p,k,ev,as,a[10][10],b[10][20],nr;
I

stiva st;
ED

void citeste()
Informatic 205

C
{int i,j; f1>>n>>x;
for (i=1;i<=n;i++)
for (j=1;j<=n;j++) {f1>>a[i][j]; if (a[i][j]==1) m++;}

I
m=m/2; f.close();}

OG
void transformare()
{int i,j,k=1;
for (i=1;i<=n;i++)
for (j=1;j<i;j++) if (a[i][j]==1) {b[i][k]=1; b[j][k]=1; k++;}}
void init() {st[k]=0;}

AG
int succesor()
{if (st[k]<m) {st[k]=st[k]+1; return 1;} else return 0;}
int valid()
{if (k>1 && st[k]<st[k-1]) return 0;
for (int i=1;i<k;i++) if (st[k]==st[i]) return 0;

ED
return 1;}
int solutie() {return k==p;}
void tipar()
{int i,j; nr++;

P
cout<<"Graful partial "<<nr<<endl; cout<<"Muchiile: ";
for(i=1;i<=p;i++)
{for(j=1;j<=n;j++) if (b[j][st[i]]==1) cout<<j<<" ";
I
cout<<"; ";}
cout<<endl;}
void bt() {//partea fix a algoritmului backtracking}
void main()

{citeste(); transformare();
for(p=m;p>=0;p--) bt();}
IC

2. Verificarea dac un graf Gp este graf parial al unui graf G.


Algoritmul. Se verific dac cele dou grafuri au acelai numr de noduri i dac graful
CT

Gp nu conine muchii care nu exist n graful G.


Implementarea algoritmului. Se citesc, din dou fiiere text g1p.txt i g2p.txt, informaii
despre dou grafuri neorientate (sau orientate): de pe prima linie, numrul de noduri, i
apoi, de pe urmtoarele rnduri, matricea de adiacen. Matricele de adiacen ale celor
DA

dou grafuri sunt a1 i a2, cu dimensiunea n, respectiv m. Funcia grafp() verific dac
graful Gp este graf parial al grafului G.
#include<iostream.h>
fstream f1("g1p.txt",ios::in),f2("g2p.txt",ios::in);
DI

int m,n,a1[10][10],a2[10][10];
int grafp()
{if (m!=n) return 0;
else for (int i=1;i<=n;i++)
RA

for(int j=1;j<=n;j++) if (a2[i][j]==1 && a1[i][j]==0) return 0;


return 1;}
void main()
{int i,j; f1>>n;
TU

for(i=1;i<=n;i++)
for(j=1;j<=n;j++) f1>>a1[i][j]; f1.close();
f2>>m;
for(i=1;i<=m;i++)
I

for(j=1;j<=m;j++) f2>>a2[i][j]; f2.close();


ED
206 Implementarea structurilor de date

C
if(grafp()) cout<<"este graf partial ";
else cout<<"nu este graf partial";}
3. Obinerea unui graf parial Gp al unui graf G.

I
OG
Algoritmul. Se elimin din graful G muchiile, n funcie de condiia impus de problem.
Reprezentarea cea mai adecvat pentru graf este matricea de adiacen, n care se
atribuie valoarea 0 elementelor a[i][j] i a[j][i], corespunztoare muchiilor [i,j]
care trebuie eliminate..
Implementarea algoritmului. Se citesc, din fiierul text g3p.txt, informaii despre graful

AG
neorientat: de pe prima linie numrul de noduri n i eticheta unui nod x, i apoi, de pe
urmtoarele rnduri, matricea de adiacen a grafului. Informaiile despre graful parial obi-
nut se scriu n fiierul text g4p.txt, astfel: pe primul rnd numrul de noduri n i numrul de
muchii m i pe urmtoarele m rnduri muchiile, sub form de perechi de etichete de

ED
noduri desprite prin spaiu. Cerina este s se obin subgraful prin eliminarea tuturor
muchiilor care au la extremiti un nod cu grad par i nodul x. n vectorul v se memoreaz
nodurile care au grad par. Funcia citete() se folosete pentru a citi informaiile despre
matricea de adiacen a grafului din fiierul text, funcia scrie() pentru a scrie n fiierul

P
text informaiile despre lista muchiilor grafului parial, funcia grad() pentru a determina
gradul unui nod, iar funcia graf partial() pentru a obine graful parial. Pentru a obine
I
graful parial, se caut toate muchiile care au la extremiti un nod cu gradul par i nodul x
(muchiile [v[i],x] pentru care a[v[i]][x]==1) i se elimin aceste muchii. Pentru testa-
rea programului se va folosi graful G3 i nodul 6.
#include<iostream.h>

fstream f1("g3p.txt",ios::in),f2("g4p.txt",ios::out);
int a[20][20],n,m,x,v[10];
IC

void citeste() {//se citete matricea de adiacen din fiier}


int grad(int i)
{int j,g=0;
CT

for (j=1;j<=n;j++) g+=a[i][j]; return g;}


void graf partial()
{int i,k=0;
for (i=1;i<=n;i++)
DA

if (grad(i)%2==0) {k++; v[k]=i;}


for (i=1;i<=k;i++)
if (a[v[i]][x]==1) {a[v[i]][x]=0; a[x][v[i]]=0; m--;}}
void scrie()
{int i,j; f2<<n<<" "<<m<<endl;
DI

for (i=1;i<=n;i++)
for (j=1;j<i;j++) if (a[i][j]==1) f2<<i<<" "<<j<<endl;
f2.close();}
void main() {citeste(); graf partial(); scrie();}
RA

1. Scriei un program care citete, din fiierul text graf16.txt, matricea


Tem de adiacen a grafului orientat G9 i care genereaz toate grafu-
rile pariale care se pot obine. Informaiile despre grafurile pariale
TU

se vor salva n fiierul text graf_p16.txt. Pentru fiecare graf parial generat se va scrie
pe un rnd textul Graful parial, urmat de numrul de ordine al grafului generat, iar pe
rndul urmtor textul Arcele urmat de lista de arce a grafului generat.
2. Scriei un program care citete, din dou fiiere text graf_1p.txt i graf_2p.txt informaii
I

despre matricele de adiacen a dou grafuri neorientate (i varianta grafuri orientate):


ED
Informatic 207

C
de pe prima linie numrul de noduri, apoi matricea de adiacen, i care verific dac
unul dintre grafuri este graf parial al celuilalt. n caz afirmativ, se afieaz care este
graful i care este graful parial. (Indicaie. Dac cele dou grafuri au acelai ordin n,

I
se identific graful care are mai multe muchii (m) i numrul de muchii ale celuilalt graf

OG
p (mp). Pentru graful cu m muchii, se genereaz toate matricele de adiacen ale
grafurilor pariale cu m muchii i n noduri i se verific dac una dintre ele este
identic cu matricea de adiacen a celuilalt graf.)
3. Scriei un program care citete din fiierul text graf19.txt matricea de adiacen a unui

AG
graf neorientat i care genereaz un graf parial prin eliminarea muchiilor care au la
extremiti un nod ce are gradul minim i un nod ce are gradul maxim n graf.
Informaiile despre graful parial obinut se scriu ntr-un fiier text sub forma listei de
muchii. Pentru testarea programului se va folosi graful G4.

ED
2.7.6.2. Subgraful
Fie graful G = (X,U). Graful Gs = (Y,V) se numete subgraf al grafului G dac YX
(subgraful conine numai noduri ale grafului) i muchiile (arcele) din mulimea V sunt

P
toate muchiile (arcele) din mulimea U care au ambele extremiti n mulimea de
noduri Y. Se spune c subgraful Gs este indus sau generat de mulimea de noduri Y.
I
Altfel spus, un subgraf al grafului G este el nsui sau un graf care s-a obinut prin
suprimarea din graful G a unor noduri i a tuturor muchiilor (arcelor) incidente cu
aceste noduri.

Exemple:
1. Pentru graful neorientat G1 = (X1,U1), definit anterior, graful G1s = (Y1,V1), definit astfel: G
G
G111sss
IC

mulimea nodurilor este Y1={1,2,4,5,6,7}.


mulimea muchiilor este V1={[1,2], [1,4], [2,5], [6,7]}.
este subgraf al grafului G1 figura 19.
CT

Subgraful
Graful G1s
G1
DA

Fig. 19

2. Pentru graful orientat G10=(X10,U10), definit anterior, graful G10s = (Y10,V10) definit astfel: G
G
G111000sss
mulimea nodurilor este Y10={1,2,3,6,7,9,10}.
DI

mulimea arcelor este V10={[1,2], [2,1], [2,3], [2,6], [2,7], [7,2]}.


este subgraf al grafului G10 figura 20.
RA
TU

Graful G10 Subgraful G10s


Fig. 20
Teorema 9
I

n
Numrul de subgrafuri ale unui graf cu n noduri este egal cu 2 -1.
ED
208 Implementarea structurilor de date

C
Demonstraie. Subgrafurile se pot obine: prin eliminarea niciunui nod (obinndu-se graful iniial);
a unui nod (obinndu-se subgrafurile cu n-1 noduri); ...; a n-1 noduri (obinndu-se subgrafurile cu
un nod):

I
Numrul de subgrafuri care se pot obine cu n noduri: Cn n

OG
Numrul de subgrafuri care se pot obine cu n-1 noduri: C nn 1
Numrul de subgrafuri care se pot obine cu n-2 noduri: C nn 2
.........................................................................................................

AG
Numrul de subgrafuri care se pot obine cu 1 nod: C 1n
n
Numrul total de subgrafuri este: C nn + C nn 1 + C nn 2 + + C 1n = 2 -1.

Algoritmi pentru prelucrarea subgrafurilor

ED
1. Generarea tuturor subgrafurilor unui graf.
Algoritmul. Se folosete metoda backtracking. n stiv se genereaz nodurile subgra-
fului. Deoarece subgraful poate avea p noduri (1pn), se va apela repetat subprogramul

P
bt(), la fiecare apel generndu-se variantele cu p noduri. Fiecare apel al subprogramului
bt() trebuie s genereze C pn de noduri din graf. La fiecare apel al subprogramului, soluia
I
se obine atunci cnd n stiv s-au generat cele p noduri ale subgrafului. Pentru nodurile
generate n stiv se afieaz muchiile (arcele) care exist n graf.
Implementarea algoritmului. Se citesc, din fiierul text graf1.txt, matricea de adiacen
a unui graf neorientat, respectiv, din fiierul graf2.txt, matricea de adiacen a unui graf

orientat. Pentru fiecare subgraf generat, se afieaz numrul de noduri i muchiile


IC

(arcele). n variabila nr se contorizeaz numrul de subgrafuri generate. n funcia


tipar() se afieaz subgraful generat. Pentru testarea programelor se folosesc graful
neorientat G1 i graful orientat G9.
CT

#include<fstream.h>
fstream f("graf1.txt",ios::in);
// fstream f("graf2.txt",ios::in); pentru graful orientat
typedef int stiva[100];
DA

int n,p,k,ev,as,a[10][10],nr;
stiva st;
void citeste() {//se citete matricea de adiacen din fiier}
void init() {st[k]=0;}
int succesor()
DI

{if (st[k]<n) {st[k]=st[k]+1; return 1;} else return 0;}


int valid()
{if (k>1 && st[k]<st[k-1]) return 0;
for (int i=1;i<k;i++) if (st[k]==st[i]) return 0;
RA

return 1;}
int solutie() {return k==p;}
void tipar()
{int i,j; nr++;
TU

cout<<"Subgraful "<<nr<<endl<<"Nodurile:";
for (i=1;i<=p;i++) cout<<st[i]<<" "; cout<<endl;
cout<<"Muchiile: "; // cout<<"Arcele: "; pentru graful orientat
for(i=1;i<=p;i++)
I

for(j=i+1;j<=p;j++) // for(j=1;j<=p;j++) pentru graful orientat


ED
Informatic 209

C
if (a[st[i]][st[j]]==1) cout<<st[i]<<"-"<<st[j]<<" ";
cout<<endl;}
void bt() {//partea fix a algoritmului backtracking}

I
void main()

OG
{citeste(); for(p=n;p>=1;p--) bt();}
2. Verificarea dac un graf Gs este subgraf al unui graf G.
Algoritmul. Se verific dac:
numrul de noduri din graful Gs este mai mic sau cel mult egal cu numrul de noduri

AG
din graful G;
etichetele nodurilor din graful Gs exist printre etichetele grafului G;
ntre nodurile din graful Gs exist muchiile dintre nodurile din graful G i numai acelea.
Implementarea algoritmului. Se citesc, din dou fiiere text g1s.txt i g2s.txt, informaii

ED
despre dou grafuri neorientate (orientate): de pe prima linie numrul de noduri i apoi,
de pe urmtoarele rnduri, matricea de adiacen. n fiierul g2s.txt pe ultimul rnd, dup
matricea de adiacen, este memorat un ir de numere care reprezint etichetele nodu-
rilor din acest graf. Matricele de adiacen ale celor dou grafuri sunt a1 i a2, cu

P
dimensiunea n, respectiv m. n vectorul v se memoreaz etichetele nodurilor celui de al
doilea graf. Funcia subgraf() verific dac graful Gs este subgraf al grafului G.
I
#include<iostream.h>
int m,n,a1[10][10],a2[10][10],v[10];
fstream f1("g1s.txt",ios::in),f2("g2s.txt",ios::in);
int subgraf()

{if (m>n) return 0;


else
IC

{for (int i=1;i<=m;i++) if (v[i]>n) return 0;


for(int i=1;i<=m;i++)
for(int j=1;j<=m;j++) if (a2[i][j]!=a1[v[i]][v[j]]) return 0;}
CT

return 1;}
void main()
{int i,j; f1>>n;
for(i=1;i<=n;i++)
DA

for(j=1;j<=n;j++) f1>>a1[i][j]; f1.close();


f2>>m;
for(i=1;i<=m;i++)
for(j=1;j<=m;j++) f2>>a2[i][j];
for(i=1;i<=m;i++) f2>>v[i]; f2.close();
DI

if(subgraf()) cout<<"este subgraf ";


else cout<<"nu este subgraf";}
3. Verificarea dac dou matrice de adiacen pot reprezenta matricele de
RA

adiacen ale unui graf i ale unui subgraf al acestuia.


Algoritmul. Matricele de adiacen ale celor dou grafuri au dimensiunea n, respectiv p.
Se identific graful care are ordinul mai mare (n) i gradul celuilalt graf p (np). Pentru
graful cu n noduri se genereaz toate matricele de adiacen ale subgrafurilor cu p noduri
TU

i se verific dac una dintre ele este identic cu matricea de adiacen a celuilalt graf).
Generarea tuturor subgrafurilor cu p noduri se face cu metoda backtracking. n stiv se
vor genera nodurile subgrafului.
Implementarea algoritmului. Se citesc din dou fiiere text, graf_1s.txt i graf_2s.txt,
I
ED

informaii despre matricele de adiacen a dou grafuri neorientate: de pe prima linie,


210 Implementarea structurilor de date

C
numrul de noduri, apoi matricea de adiacen. Se verific dac unul dintre grafuri este
subgraf al celuilalt, iar n caz afirmativ, se identific care este graful i care este
subgraful. Matricele de adiacen ale celor dou grafuri sunt a1 i a2. Variabila x se

I
folosete pentru a identifica relaia dintre cele dou grafuri: dac are valoarea 0, a doua

OG
matrice de adiacen se asociaz unui posibil subgraf, iar dac are valoarea 1, prima
matrice de adiacen se asociaz unui posibil subgraf. Variabila logic gasit se
folosete pentru a determina dac una dintre matricele de adiacen reprezint matricea
de adiacen a unui subgraf: are valoarea 0 False, dac nu este subgraf i valoarea 1

AG
True dac este subgraf. n matricea b se va construi matricea de adiacen a unui
subgraf format cu nodurile generate n stiv. Funcia zero() se folosete pentru a iniia-
liza cu 0 elementele matricei b nainte de generarea fiecrui subgraf. Funcia tipar()
se folosete pentru a genera matricea b i pentru a o compara cu matricea asociat unui
posibil subgraf. Funcia furnizeaz un rezultat logic: 1 true, dac matricea generat i

ED
matricea asociat unui posibil subgraf sunt egale; altfel, are valoarea 0 False.
Rezultatul acestei funcii este atribuit variabilei gasit. Subprogramul bt() se execut
att timp ct nu s-a generat o matrice de adiacen egal cu cea asociat unui posibil
subgraf (gasit==0) i se mai pot cuta soluii pentru matricea generat (k>0).

P
#include<iostream.h>
int n,p,a1[10][10],a2[10][10],b[10][10],v[10],nr,x,as,ev,k,gasit;
I
fstream f1("graf1 s.txt",ios::in),f2("graf2 s.txt",ios::in);
typedef int stiva[100];
stiva st;
void zero()

{for(int i=1;i<=p;i++)
for(int j=1;j<=p;j++) b[i][j]=0;}
IC

void init() {st[k]=0;}


int succesor()
{if (st[k]<n) {st[k]=st[k]+1; return 1;} else return 0;}
CT

int valid()
{if (k>1 && st[k]<st[k-1]) return 0;
for (int i=1;i<k;i++) if (st[k]==st[i]) return 0;
return 1;}
DA

int solutie() {return k==p;}


int tipar()
{int i,j; zero();
if (x==0)
{for(i=1;i<=p;i++)
DI

for(j=1;j<=p;j++) if (a1[st[i]][st[j]]==1) b[i][j]=1;


for(i=1;i<=p;i++)
for(j=1;j<=p;j++) if (a2[i][j]!=b[i][j]) return 0;}
else
RA

{for(i=1;i<=p;i++)
for(j=1;j<=p;j++) if (a2[st[i]][st[j]]==1) b[i][j]=1;
for(i=1;i<=p;i++)
for(j=1;j<=p;j++) if (a1[i][j]!=b[i][j]) return 0;}
TU

return 1;}
void bt(){//partea fix a algoritmului backtracking }
void main()
{int i,j,m; f1>>n;
I

for(i=1;i<=n;i++)
ED

for(j=1;j<=n;j++) f1>>a1[i][j]; f1.close();


Informatic 211

C
f2>>p;
for(i=1;i<=p;i++)
for(j=1;j<=p;j++) f2>>a2[i][j]; f2.close();

I
if (p>n) {m=n; n=p; n=m; x=1;}

OG
else x=0;
bt();
if (gasit)
if (x) cout<<"prima matrice de adiacenta este a subgrafului";
else cout<<"a doua matrice de adiacenta este a subgrafului";

AG
else cout<<"nu este subgraf";}
1. Scriei un program care citete din fiierul text graf16.txt matricea de
Tem adiacen a unui graf orientat i care genereaz toate subgrafurile
care se pot obine. Informaiile despre subgrafuri se vor salva n

ED
fiierul text graf_s16.txt. Pentru fiecare subgraf generat se va scrie, pe un rnd, textul
Subgraful x are p noduri (unde x este numrul de ordine al subgrafului generat, iar p
numrul de noduri) i pe rndul urmtor textul Arcele urmat de lista de arce a
subgrafului generat.

P
2. Scriei un program care citete din dou fiiere text, graf_1s.txt i graf_2s.txt informaii
despre matricele de adiacen a dou grafuri orientate (de pe prima linie numrul de
noduri, apoi matricea de adiacen) i care verific dac unul dintre grafuri este subgraf
I
al celuilalt. n caz afirmativ, se precizeaz care este graful i care este subgraful.
3. Scriei un program care citete din fiierul text graf16.txt matricea de adiacen a unui
graf orientat i care genereaz subgraful care se obine prin eliminarea nodului care

are cei mai muli vecini.


IC

2.7.6.3. Graful complementar


Fie graful G = (X,U) i mulimea de muchii (arce) V. Graful Gc = (X,V) se numete graf
CT

complementar al grafului G dac are proprietatea c dou noduri sunt adiacente n


graful Gc, numai dac nu sunt adiacente n graful G (U V = ).
Altfel spus, un graf complementar al grafului G conine aceleai noduri ca i graful G,
dar nici o muchie din acest graf.
DA

Exemple:
1. Pentru graful neorientat G1 = (X1,U1), definit anterior, graful G1c = (X1,V1), definit astfel: G
G
G111ccc
mulimea nodurilor este X1={1,2,3,4,5,6,7,8}.
DI

mulimea muchiilor este V1 ={[1,5], [1,6], [1,7], [2,4], [2,7], [5,7], [5,8]}.
este graf complementar al grafului G1 figura 21.

Graful Graful complementar


RA

G1 G1c

Fig. 21
TU

2. Pentru graful orientat G10=(X10,U10), definit anterior, graful G10c= (X10,V10), definit astfel: G G
G111000ccc
mulimea nodurilor este X10={1,2,3,4,5,6,7,8,9,10}.
mulimea arcelor este V10={[1,3], [1,5], [2,4], [2,8], [3,2], [4,2], [5,2], [5,6], [7,1], [8,2],
[9,3], [9,10]}.
I
ED

este graf complementar al grafului G10 figura 22.


212 Implementarea structurilor de date

C
6

I
OG
Graful Graful complementar
G10 G10c
10

Fig. 22

AG
Scriei un program care citete din dou fiiere text graf_1c.txt i
Tem graf_2c.txt informaii despre dou grafuri neorientate i varianta orientate
(de pe prima linie, numrul de noduri, apoi matricea de adiacen) i care

ED
verific dac unul dintre grafuri este graf complementar al celuilalt graf. (Indicaie. Dac
cele dou grafuri au acelai numr de noduri, se determin graful intersecie, care va trebui
s fie graful vid).

P
2.7.6.4. Aplicaii practice
1. Din grupul de n persoane ntre care s-au stabilit relaii de prietenie, afiai, pentru
I
fiecare persoan, persoanele cu care nu este n relaie de prietenie. (Indicaie. Se
genereaz graful complementar.)
2. Din grupul de n persoane ntre care s-au stabilit relaii de cunotin, eliminai strinii
de grup i singuraticii. (Indicaie. Se genereaz un subgraf al grafului iniial, prin

eliminarea tuturor nodurilor izolate sau terminale.)


IC

3. La graful judeelor, construii un vector n care memorai, pentru fiecare jude, un indice
pentru provincia istoric din care face parte (1 Muntenia, 2 Moldova etc.). Obinei
din graful judeelor, subgrafurile provinciilor istorice. Precizai provincia istoric ce
CT

conine cele mai multe judee, i provincia istoric ce conine cele mai puine judee.
4. Din graful grotelor, obinei subgraful grotelor care se gsesc la o nlime h, cu
h1hh2. Verificai cte dintre aceste grote comunic direct cu exteriorul muntelui.
Valorile pentru nlimile h1 i h2 se citesc de la tastatur.
DA

5. n reeaua de strzi a oraului, dou strzi se nchid pentru a fi reparate. Etichetele


interseciilor care sunt legate de aceste strzi se citesc de la tastatur. S se verifice
dac, prin nchiderea acestor strzi, traficul auto nu este perturbat, n sensul c vor
DI

exista intersecii la care nu se mai poate ajunge. (Indicaie. Se genereaz graful parial
al traficului, prin eliminarea arcelor dintre nodurile precizate, i se verific dac exist
noduri care au gradul intern egal cu 0.)
6. Se citesc, din dou fiiere text dou matrice de adiacen a dou grafuri care au acelai
RA

numr de noduri. S se verifice dac aceste matrice pot reprezenta matricele de


adiacen a relaiei de vecintate, respectiv a relaiei de prietenie pentru stenii care au
fnee. (Indicaie. Se verific dac graful cu mai puine muchii este graf parial al
celuilalt graf).
TUI
ED
Informatic 213

C
2.7.7. Conexitatea grafurilor

I
2.7.7.1. Lanul

OG
ntr-un graf G= (X,U) se definete lanul ca fiind o succesiune de noduri care
au proprietatea c, oricare ar fi dou noduri succesive, ele sunt adiacente.
Graful neorientat

AG
Dac mulimea nodurilor unui graf neorientat este X={x1, x2, ..., xn}, un lan de la nodul l1 la
nodul lk L(l1,lk) va fi definit prin mulimea L(l1,lk)=l1, l2, ..., li , , lk, unde liX pentru
orice i (1ik), iar muchiile [l1,l2], [l2,l3], [l3,l4], ..., [lk-1,lk] U. Lanul poate fi interpretat ca un
traseu prin care se parcurg anumite muchii ale grafului, traseul fiind ordinea n care se

ED
parcurg aceste muchii: [l1,l2], [l2,l3], [l3,l4], ..., [lk-1,lk]. Fiecare pereche de noduri succesive din
lan reprezint parcurgerea unei muchii. Dac exist L(xi,xj), se spune c nodul xj este
accesibil din nodul xi.

P
Graful orientat
Dac mulimea nodurilor unui graf orientat este X={x1, x2, ..., xn}, un lan de la nodul l1 la
nodul lk L(l1,lk) va fi definit prin mulimea L(l1,lk)=[l1, l2, ..., li , , lk], unde liX, pentru
I
orice i (1ik). Arcele [l1,l2], [l2,l3], [l3,l4], ..., [lk-1,lk] au proprietatea c, oricare ar fi dou arce
succesive, ele au o extremitate comun. La definirea unui lan, nu se ine cont de
orientarea arcelor, ci numai de faptul c dou noduri sunt legate de un arc.

Terminologie:
Lungimea unui lan reprezint numrul de parcurgeri ale muchiilor, respectiv arcelor.
IC

De exemplu, lungimea lanului L(l1,lk) este k-1. Dac o muchie (un arc) este parcurs de
mai multe ori, se va numra fiecare dintre parcurgerile sale.
CT

Lanul de lungime minim dintre nodul xi i nodul xj Lmin(xi,xj) este lanul cu


numrul minim de muchii (arce), din mulimea nevid de lanuri L(xi,xj).
Extremitile unui lan sunt formate din nodul cu care ncepe i nodul cu care se
termin lanul (l1 i lk).
DA

Sublanul este format dintr-un ir continuu de noduri din lan. De exemplu, pentru
lanul L(l1, lk)=l1, l2, ..., li, ..., lj, ..., lk, Ls (li, lj), definit astfel: Ls (li, lj)=li, li+1, ..., lj-1, lj este
un sublan al lanului L.
Exemple: G
G
DI

G111999
1. Pentru graful neorientat G19 = (X19,U19), definit astfel:
mulimea nodurilor este X19={1,2,3,4,5,6,7,8}.
mulimea muchiilor este U19 ={[1,2], [1,5], [1,6], [2,3], Fig. 23
RA

[2,5], [2,6], [3,4], [3,6], [3,7], [3,8], [4,8], [5,6], [6,7], [7,8]}.
L1(1,7)= {1, 2, 3, 8, 4, 3, 6, 5, 2, 3, 7} este un lan ntre nodul cu eticheta 1 i nodul cu eti-
cheta 7 (figura 23). Lungimea lanului este 10.
G
G
G222000
2. Pentru graful orientat G20 = (X20,U20), definit astfel:
TU

mulimea nodurilor este X20={1,2,3,4,5,6,7}.


mulimea arcelor este U20 ={[1,2], [1,4], [2,3], [2,4],
[3,6], [3,7], [4,1], [4,5], [5,2], [5,4], [6,3], [6,5], [7,6]}.
L1(1,5)= {1, 2, 5, 6, 3, 6, 7, 6, 5} este un lan ntre nodul cu Fig. 24
I

eticheta 1 i nodul cu eticheta 5 (figura 24). Lungimea lanului este 8.


ED
214 Implementarea structurilor de date

C
Clasificarea lanurilor n funcie de:

I
Noduri Muchii (arce)

OG
Elementare Simple
Conin numai noduri distincte dou cte Toate muchiile (arcele) din lan sunt
diferite ntre ele: [l1,l2] [l2,l3];

AG
dou: l1l2; l1l37; ...; l1 lk; l2 l3; ...; lk-1 lk
acelai nod poate fi parcurs o singur [l1,l2] [l3,l4]; ...; [l1,l2] [lk-1,lk]; ...;
dat. [lk-2,lk-1] [lk-1,lk] aceeai muchie (arc)
poate fi parcurs o singur dat.

ED
Neelementare Compuse
Conin noduri care se repet prin n lan se pot repeta unele muchii (arce)
acelai nod se poate trece de mai multe aceeai muchie (arc) poate fi parcurs
ori. de mai multe ori.

Exemple:
1. Pentru graful neorientat G19: P
I
Lanul L1(1,7) definit anterior este un lan neelementar, deoarece se repet nodul cu
eticheta 3. Este un lan compus, deoarece n lan se repet muchia [2,3].
Lanul L2(1,7) = {1, 2, 3, 6, 7} este un lan elementar deoarece fiecare nod este par-

curs o singur dat.


Lanul L3(1,7) = {1, 6, 3, 2, 6, 7} este un lan simplu, deoarece nicio muchie nu se
IC

repet, dar este un lan neelementar, deoarece se repet nodul cu eticheta 6.


2. Pentru graful orientat G20:
Lanul L1(1,5) definit anterior este un lan neelementar, deoarece se repet nodul cu
CT

eticheta 6. Este un lan compus, deoarece n lan se repet arcul [6,7].


Lanul L2(1,5) = {1, 2, 3, 7, 6, 5} este un lan elementar, deoarece fiecare nod este
parcurs o singur dat.
Lanul L3(1,5) = {1, 2, 4, 5, 2, 3, 6, 5} este un lan simplu, deoarece niciun arc nu se
DA

repet, dar este un lan neelementar deoarece se repet nodul cu eticheta 2.


Teorema 10
Dac un graf conine un lan ntre dou noduri, x i y,
DI

atunci conine un lan elementar ntre nodurile x i y.


Demonstraie. Considerm lanul L(x,y)=x, l1, l2, ..., lk, y. Dac lanul nu este elementar, el conine
cel puin un nod z care se repet exist i i j, astfel nct li= lj=z: L(x,y)=x, l1, l2, ..., li, ..., lj, ..., lk, y.
RA

Nodul z aparinnd lanului L(x,y), nseamn c el este accesibil din nodul x, iar nodul y este accesibil
din nodul z. nseamn c din lan se poate elimina sublanul care leag nodul z de el nsui: L(x,y)=x,
l1, l2, ..., li, lj+1, ..., lk, y n acelai mod, se pot elimina din lan, toate sublanurile care leag un nod de
el nsui, obinndu-se n final un lan n care fiecare nod nu apare dect o singur dat, adic un lan
TU

elementar.
Exemplu:
n graful neorientat G19, lanul L1(1,7) este un lan neelementar. Prin eliminarea din acest lan
a sublanului {8, 4 ,3}, se obine lanul {1, 2, 3, 6, 5, 2, 3, 7}, care este un lan neelementar.
I
ED

Prin eliminarea din acest lan a sublanului {6, 5, 2, 3}, se obine lanul {1, 2, 3, 7}, care este
un lan elementar.
Informatic 215

C
Teorema 11
Dac un lan este elementar, atunci este i lan simplu.

I
Demonstraie prin reducere la absurd. Presupunem c lanul elementar este lan compus. Dac

OG
este lan compus, el trebuie s parcurg de dou ori aceeai muchie (arc), ceea ce ar nsemna s
treac de dou ori prin nodurile adiacente muchiei (arcului). Lanul fiind elementar, nu trece ns de
dou ori prin acelai nod.
Algoritmi pentru determinarea lanurilor elementare ntr-un graf

AG
1. Afiarea lanurilor elementare dintre dou noduri.
Algoritmul. Pentru generarea lanurilor elementare ntre nodul x i nodul y, se folosete
metoda backtracking. Nodurile lanului elementar vor fi generate n stiv. Primul nod din
stiv este nodul x. Condiia ca un nod adugat n stiv s fac parte din soluie (s fie valid)

ED
este s formeze o muchie (un arc) cu nodul adugat anterior n stiv i s nu mai existe n
stiv (condiia ca lanul s fie elementar). Soluia se obine atunci cnd nodul adugat n
stiv este nodul y.
Implementarea algoritmului. Se citete din fiierul text graf1.txt matricea de adiacen a

P
unui graf neorientat, respectiv, din fiierul graf2.txt matricea de adiacen a unui graf
orientat. Se mai citesc de la tastatur dou valori numerice care reprezint etichetele a
I
dou noduri din graf. Se caut toate lanurile elementare care exist ntre cele dou
noduri i se afieaz. Dac nu exist nici un lan elementar, se afieaz un mesaj.
Funcia citeste() se folosete pentru a citi matricea de adiacen din fiier. Variabila
este se folosete pentru a verifica dac s-a gsit un lan elementar ntre cele dou noduri

(are valoarea 0 False, dac nu s-a gsit un lan elementar). Pentru testarea programelor
se folosesc graful neorientat G1 i graful orientat G9.
IC

#include<fstream.h>
typedef stiva[100];
int a[20][20],n,k,as,ev,x,y,este=0;
CT

stiva st;
fstream f("graf1.txt",ios::in);
void citeste() {//se citete matricea de adiacen din fiier}
void init() {st[k]=0;}
DA

int succesor()
{if (st[k]<n) {st[k]=st[k]+1; return 1;} else return 0;}
int valid()
{if(k>1) //condiia ca dou noduri succesive s fie adiacente
DI

if (a[st[k-1]][st[k]]==0) return 0;
//pentru graful orientat
//if (a[st[k]][st[k-1]]==0 && a[st[k-1]][st[k]]==0) return 0;
for (int i=1;i<k;i++) //condiia ca lanul s fie elementar
RA

if (st[k]==st[i]) return 0;
return 1;}
int solutie() {return st[k]==y;}
//se obine soluia atunci cnd ultimul nod adugat n stiv este y
void tipar ()
TU

{for (int i=1,este=1;i<=k;i++) cout<<st[i]<<" "; cout<<endl;}


void bt() {//partea fixa a algoritmului}
{k=2; init();
while (k>1)
I

{as=1; ev=0;
ED

while(as && !ev)


216 Implementarea structurilor de date

C
{as=succesor();
if(as) ev=valid();}
if(as)

I
if (solutie()) tipar();

OG
else {k++; init();}
else k--;}}
void main()
{citeste(); cout<<"x= "; cin>>x; cout<<"y= "; cin>>y; st[1]=x; bt();
if (!este) cout<<"Nu exista lant";}

AG
2. Afiarea tuturor lanurilor elementare din graf.
Algoritmul. Pentru generarea tuturor lanurilor elementare din graf, se vor genera lanurile
elementare dintre nodul x (1xn) i nodul y (1yn), folosind metoda backtracking, care
se va apela pentru fiecare pereche de noduri x i y (xy).

ED
Implementarea algoritmului. Se citete din fiierul text graf1.txt matricea de adiacen a
unui graf neorientat, respectiv, din fiierul graf2.txt matricea de adiacen a unui graf
orientat. Se caut toate lanurile elementare care exist n graf i se afieaz. Dac nu

P
exist nici un lan elementar, se afieaz un mesaj. Pentru testarea programelor se
folosesc graful neorientat G1 i graful orientat G9.
#include<fstream.h>
I
typedef stiva[100];
int a[20][20],n,k,as,ev,x,y,este=0;
stiva st;
fstream f("graf1.txt",ios::in);

void citeste() {//la fel ca n exemplul precedent }


void init() {//la fel ca n exemplul precedent }
IC

int succesor() {//la fel ca n exemplul precedent }


int valid() {//la fel ca n exemplul precedent }
int solutie() {//la fel ca n exemplul precedent }
CT

void tipar () {//la fel ca n exemplul precedent }


void bt() {//partea fix a algoritmului ca n exemplul precedent}
void main()
{citeste();
DA

for (x=1;x<=n;x++)
for (y=1;y<=n;y++) if (x!=y) {st[1]=x; bt();}
if (!este) cout<<"Nu exista lanturi elementare";}
3. Verificarea unui ir de etichete de noduri dac formeaz un lan simplu.
DI

Algoritmul. Se verific dac:


irul de etichete poate forma un lan (dac fiecare pereche de noduri consecutive din
lan este legat prin muchie, respectiv arc);
RA

lanul este simplu (se verific dac muchiile formate cu nodurile din lan nu se repet).
Implementarea algoritmului. Se citesc din fiierul text graf3.txt lista muchiilor unui graf
neorientat, respectiv, din fiierul graf4.txt lista arcelor unui graf orientat. Se citete apoi, de
la tastatur, un ir de k numere, care reprezint etichete ale nodurilor din graf. Se verific
TU

dac acest ir de noduri poate reprezenta un lan simplu n graf. irul de numere citite de la
tastatur se memoreaz n vectorul v. n vectorul z cu nregistrri de tip muchie, se memo-
reaz muchiile (arcele) pe care le formeaz dou noduri succesive din irul de numere.
Pentru a identifica dou muchii (arce) identice, perechile de etichete care formeaz o
I

muchie sunt memorate ordonat. Funcia citeste() se folosete pentru a citi informaiile
ED

din fiier i pentru a le memora n matricea de adiacen a grafului, funcia lan() se


Informatic 217

C
folosete pentru a verifica dac irul de numere poate reprezenta un lan din graf, funcia
simplu() se folosete pentru a verifica dac lanul este un lan simplu. Pentru testarea
programelor se folosesc graful neorientat G1 i graful orientat G9.

I
#include<fstream.h>

OG
struct muchie {int x,y;};
muchie z[10];
int k,n,m,a[10][10],v[10];
fstream f("graf3.txt",ios::in);
void citeste()

AG
{int i,x,y; f>>n>>m;
for(i=1;i<=m;i++) {f>>x>>y; a[x][y]=1; a[y][x]=1;} f.close();}
int lant()
{for(int i=1;i<k;i++) if (a[v[i]][v[i+1]]==0) return 0;

ED
return 1;}
int simplu()
{for(int i=1;i<k;i++)
for(int j=i+1;j<=k;j++) if(z[i].x==z[j].x && z[i].y==z[j].y) return 0;

P
return 1;}
void main()
{int i; citeste(); cout<<"k= ";cin>>k;
I
for(i=1;i<=k;i++) {cout<<"Eticheta "<<i<<" = "; cin>>v[i];}
for(i=1;i<k;i++) if (v[i]<v[i+1]) {z[i].x=v[i];z[i].y=v[i+1];}
else {z[i].x=v[i+1];z[i].y=v[i];}
if (lant())

if (simplu()) cout<<"este lant simplu";


else cout<<"nu este lant simplu";
IC

else cout<<"nu este lant";}


1. Scriei un program care citete dintr-un fiier text lista muchiilor unui
Tem graf neorientat (graf3.txt) sau variant graf orientat (graf4.txt), i care:
CT

a. Verific dac un ir de k numere citite de la tastatur reprezint


un lan elementar pentru graf.
b. Caut toate lanurile elementare cu lungimea d i le afieaz. Valoarea numeric d se
citete de la tastatur. Dac nu exist nici un lan elementar cu lungimea d, se
DA

afieaz un mesaj.
c. Caut toate lanurile elementare, cu lungimea cea mai mic, ce exist ntre dou
noduri x i y, i le afieaz. Etichetele nodurilor se citesc de la tastatur. Dac nu
exist nici un lan elementar, se afieaz un mesaj..
DI

d. Caut toate lanurile elementare ntre dou noduri x i y, care trec printr-un nod z
care are gradul minim n graf. Etichetele celor dou noduri se citesc de la tastatur.
Dac nu exist nici un lan elementar, se afieaz un mesaj.
RA

e. Caut toate lanurile elementare de lungime maxim i afieaz cte lanuri s-au
gsit i care sunt ele. Dac nu exist nici un lan elementar, se afieaz un mesaj.
f. Caut i afieaz cel mai lung lan elementar care este format din noduri care au
etichete cu numere consecutive, ordonate cresctor.
TU

g. Caut i afieaz cel mai scurt lan elementar care trece prin p noduri i prin q muchii
(arce) date. Se citesc de la tastatur urmtoarele valori numerice: p numr de noduri,
un ir de p numere, care reprezint etichete ale nodurilor din graf, q numr de muchii
i un ir de q perechi de numere, care reprezint muchii (arce) din graf.
I

2. ntr-un fiier text sunt memorate informaii despre dou grafuri neorientate G i G: pe
ED

primul rnd numrul de noduri ale celor dou grafuri (n1 i n2), pe urmtoarele n1
218 Implementarea structurilor de date

C
rnduri matricea de adiacen a grafului G, iar pe urmtoarele n2 rnduri matricea de
adiacen a grafului G. Scriei un program care citete din fiierul text informaiile
despre cele dou grafuri i care determin dou noduri p i q (p din graful G i q din

I
graful G) care dac se leag printr-o muchie asigur legtura, printr-un lan de

OG
lungimea k, ntre dou noduri precizate x i y (x din graful G i y din graful G). Valorile
pentru x, y i k se citesc de la tastaur.

2.7.7.2. Ciclul

AG
Un lan care are toate muchiile distincte dou cte dou i
extremiti care coincid se numete ciclu.
Ciclul este un lan simplu ([l1,l2] [l2,l3]; [l1,l2] [l3,l4]; ...; [l1,l2] [lk-1,lk]; ...; [lk-2,lk-1] [lk-1,lk]),

ED
n care extremitile coincid: l1=lk.
Un graf fr cicluri se numete graf aciclic.
Dac toate nodurile unui ciclu sunt distincte dou cte dou, cu excepia extremitilor,
ciclul se numete ciclu elementar.

P
Exemple:
1. Pentru graful neorientat G19:
I
Lanul L4(1,1) ={1, 2, 3, 6, 2, 1} nu este un ciclu deoarece n lan se repet muchia [1,2].
Lanul L5(1,1) = {1, 2, 6, 3, 7, 6, 1}=C1 este un ciclu neelementar deoarece se repet
nodul cu eticheta 6.
Lanul L6(1,1) = {1, 2, 3, 7, 6, 1}=C2 este un ciclu elementar deoarece nu se repet

niciun nod.
IC

2. Pentru graful orientat G20:


Lanul L4(1,1) ={1, 2, 4, 5, 2, 1} nu este un ciclu deoarece n lan se repet arcul [1,2].
Lanul L5(1,1) = {1, 2, 5, 6, 3, 2, 4, 1}=C1 este un ciclu neelementar deoarece se
CT

repet nodul cu eticheta 2.


Lanul L6(1,1) = {1, 2, 3, 6, 5, 4, 1} este un ciclu elementar deoarece nu se repet
niciun nod.
G
G
G222111 3. Un circuit electric poate fi reprezentat cu ajutorul unui graf orientat G21, n care nodurile
DA

reelei sunt nodurile grafului, iar sensul arcelor este dat de sensul ales pentru curentul
electric figura 25.
DI

R1 I1 I2 R3

I3
1
R1, I1 R ,I
E1 R6 , I3 , E1 3 2
RA

R6 R2 , I4 R4 , I5
R2 R4 2 3 4

I5
R5 , I6 , E2
I6 E2 I4 R5
TU

Fig. 25
Un ochi al reelei electrice reprezint un ciclu n graful orientat. Fiecare arc k are asociate
trei mrimi: rezistena Rk, intensitatea curentului Ik i tensiunea electromotoare a sursei Ek.
I

Semnul curentului electric este dat de sensul arcului: dac arcul intr n nod, curentul
ED

electric are semnul plus, iar dac arcul iese din nod, curentul electric are semnul minus.
Informatic 219

C
Pentru fiecare nod din graf, se aplic teorema nti a lui Kirchhoff:
p

I
Ik 0

OG
k 1
unde p este suma dintre gradul intern i gradul extern ale nodului.
Pentru fiecare ciclu din graf, se aplic teorema a doua a lui Kirchhoff:
q q
Ek I k R k

AG
k 1 k 1
unde q este numrul de arce ale ciclului.
Pentru circuitul electric din figura 25, se consider cunoscute urm-
Tem toarele mrimi: R1, R2, R3, R5, Rk, I1, E1 i E2. Scriei un program care

ED
s calculeze n graful circuitului electric mrimea rezistenei R4.
Teorema 12
Dac un graf conine un ciclu, atunci conine i un ciclu elementar.

P
Demonstraie la fel ca demonstraia de la Teorema 11, de la subcapitoul Lanuri.

Dou lanuri L1=l1, l2, ..., li, , lk-1, lk, l1 i L1=l1, l2, ..., li, , lk-1, lk, l1
I
care au aceeai lungime k, formeaz acelai ciclu dac exist un numr ntreg
j, astfel nct li= l (i+j) mod k+1, pentru orice i=1, 2, 3,, k.
Exemplu:

n graful neorientat G19 lanuri L1=l1, l2, l3, l4, l1 = 1, 2, 6, 5, 1 i L1=l1, l2, l3, l4, l1 = 2,
IC

6, 5, 1, 2 care au lungimea 4, formeaz acelai ciclu. Se observ l1=1 i l4=1. Din (1+j)
mod 4 + 1 = 4, rezult c j=2. Verificm dac pentru acest j i pentru orice i= 2, 3, 4, exist
dou noduri cu aceeai etichet n ambele lanuri:
CT

i=2 (2+2) mod 4 + 1 = 1; dar: l2=2 i l1=2 l2= l1.


i=3 (3+2) mod 4 + 1 = 2; dar: l3=6 i l2=6 l3=l2.
i=4 (4+2) mod 4 + 1 = 3; dar: l4=5 i l3=5 l2=l3.
n graful neorientat G19 lanuri L1=l1, l2, l3, l4, l1 = 1, 2, 6, 5, 1 i L1=l1, l2, l3, l4, l1 = 2,
DA

5, 6, 1, 2 care au lungimea 4, nu formeaz acelai ciclu. Se observ l1=1 i l4=1. Din (1+j)
mod 4 + 1 = 4, rezult c j=2. Verificm dac pentru acest j i pentru orice i= 2, 3, 4, exist
dou noduri cu aceeai etichet n ambele lanuri:
i=2 (2+2) mod 4 + 1 = 1; dar: l2=2 i l1=2 l2= l1.
DI

i=3 (3+2) mod 4 + 1 = 2; dar: l3=6 i l2=5 l3l2.

Algoritm pentru determinarea ciclurilor elementare ntr-un graf


RA

Algoritmul. Se genereaz toate lanurile elementare care pornesc din nodul x (1xn),
trec prin cel puin trei noduri i se pot nchide cu nodul x. Pentru generarea acestor lanuri
elementare se folosete metoda backtracking, care se va apela pentru fiecare nod x.
Soluia se obine atunci cnd nodul adugat n stiv formeaz o muchie (un arc) cu nodu x
TU

i stiva conine cel puin 3 noduri.


Implementarea algoritmului. Se citete din fiierul text graf1.txt matricea de adiacen a
unui graf neorientat, respectiv, din fiierul graf2.txt matricea de adiacen a unui graf
orientat. Se caut toate ciclurile elementare care exist n graf i se afieaz. Dac nu
I

exist nici un ciclu elementar, se afieaz un mesaj. Pentru testarea programelor se


ED

folosesc graful neorientat G1 i graful orientat G9.


220 Implementarea structurilor de date

C
#include <fstream.h>
typedef stiva[100];
int a[20][20],n,k,as,ev,x,este=0;

I
stiva st;

OG
fstream f("graf1.txt",ios::in);
void citeste() {// se citete matricea de adiacen din fiier}
void init()
{//este identic cu cea de la afiarea lanurilor elementare}
int succesor()

AG
{//este identic cu cea de la afiarea lanurilor elementare}
int valid()
{//este identic cu cea de la afiarea lanurilor elementare}
int solutie() {return a[st[k]][x]==1 && k>2;}
//se obine soluia atunci cnd ultimul nod adugat este adiacent

ED
//nodului x i n stiv exist cel puin trei noduri
void tipar ()
{for (int i=1,este=1;i<=k;i++) cout<<st[i]<<" "; cout<<x<<endl;}
void bt() {//partea fixa a algoritmului }

P
void main()
{citeste();
for (x=1;x<=n;x++) {st[1]=x; bt();}
I
if (!este) cout<<"Nu exista nici un ciclu elementar";}
1. n exemplul precedent, sunt afiate lanuri care formeaz acelai
Tem ciclu (acelai ciclu este afiat de mai multe ori; deosebirea const

doar n nodul cu care se ncepe i se ncheie ciclul). Modificai


programul astfel nct s se elimine afiarea informaiei redundante (afiarea aceluiai
IC

ciclu de mai multe ori).


2. Scriei un program care citete din fiierul text graf3.txt lista muchiilor unui graf neori-
entat i afieaz toate ciclurile elementare care trec printr-un nod cu gradul minim.
CT

3. Scriei un program care citete din fiierul text graf3.txt lista muchiilor unui graf neori-
entat i care verific dac un ir de k numere citite de la tastatur reprezint un ciclu
elementar pentru graf.
DA

4. Scriei un program care citete din fiierul text graf4.txt lista arcelor unui graf orientat i care:
a. Caut toate ciclurile elementare care exist n graf i le afieaz. Dac nu exist
niciun ciclu elementar, se afieaz un mesaj.
b. Caut toate ciclurile elementare care trec prin toate nodurile grafului i le afiea-
DI

z. Dac nu exist nici un ciclu elementar care trece prin toate nodurile grafului,
se afieaz un mesaj.
c. Caut toate ciclurile elementare de lungime maxim care trec prin nodul x i le
RA

afieaz. Eticheta nodului se citete de la tastatur. Dac nu exist nici un ciclu


elementar care s treac prin nodul x, se afieaz un mesaj.

2.7.7.3. Drumul
TU

ntr-un graf orientat G= (X,U) se definete un drum ca fiind o succesiune


de noduri care au proprietatea c oricare ar fi dou noduri succesive
ele sunt legate printr-un arc.
I

Dac, ntr-un graf orientat, mulimea nodurilor este X={x1, x2, ..., xn}, iar mulimea arcelor
ED

este U={u1, u2, ..., um}, un drum de la nodul d1 la nodul dk D(d1,dk) va fi definit prin
Informatic 221

C
mulimea nodurilor D(d1,dk) = d1, d2, ..., dk, unde diU, pentru orice i (1ik), iar arcele
[d1,d2], [d2,d3], [d3,d4], ..., [dk-1,dk] U. Drumul poate fi privit ca un lan n care parcurgerea
de la un nod la altul trebuie s se fac n sensul arcului care leag nodurile. Dac exist

I
D(xi,xj), se spune c nodul xj este accesibil din nodul xi.

OG
Terminologie:
Lungimea unui drum este dat de numrul de arce care l compun. n cazul n care
arcele au asociate lungimi, lungimea unui drum este dat de suma lungimilor arcelor
care l compun.

AG
Drumul de lungime minim dintre nodul di i nodul dj Dmin(di,dj) este drumul cu
numrul minim de arce din mulimea nevid de drumuri D(di,dj).
Subdrumul este format dintr-un ir continuu de noduri din drum. De exemplu, pentru
lanul D(d1, dk)=d1, d2, ..., di, ..., dj, ..., dk, Ds (di, dj) definit astfel: Ds(di, dj) = di, di+1, ...,

ED
dj-1, dj este un subdrum al drumului D.
Drumul elementar este drumul n care nodurile sunt distincte dou cte dou. Drumul
simplu este drumul n care arcele sunt distincte dou cte dou.

P
Exemple Pentru graful orientat G20:
Lanul L7(1,6) = {1, 2, 5, 6} nu este un drum deoarece parcurgerea nu se face n
sensul sgeilor.
I
Lanul L8(1,6) = {1, 2, 3, 6, 3, 6} = D1 este un drum neelementar, deoarece se repet
eticheta nodurilor 3 i 6 i compus, deoarece prin arcul [3,6] s-a trecut de dou ori.
Lanul L9(1,6) = {1, 2, 3, 7, 6} = D2 este un drum elementar, deoarece nu se repet

nici un nod.
Lanul L9(1,6) = {1, 2, 4, 5, 2, 3, 6}=D3 este un drum simplu, deoarece nici un arc nu
IC

a fost parcurs de dou ori, dar este un drum neelementar, deoarece se repet nodul
cu eticheta 2.
Teorema 13
CT

Dac un graf neorientat conine un drum ntre dou noduri, x i y,


atunci, conine i un drum elementar, ntre nodurile x i y.
DA

Demonstraie la fel ca demonstraia de la Teorema 11 de la subcapitolul Lanuri.

Algoritmi pentru determinarea drumurilor elementare ntr-un graf orientat


1. Afiarea drumurilor elementare din graf.
DI

Algoritmul. Se va folosi algoritmul pentru determinarea tuturor lanurilor elementare din graf, la
care elementul soluiei generat n stiv, la nivelul k (k1), va fi considerat valid numai dac
trecerea de la nodul de pe nivelul k-1 la nodul de pe nivelul k se face, n graf, n sensul arcului.
RA

Implementarea algoritmului. Se citete din fiierul graf2.txt matricea de adiacen a


unui graf orientat. Se caut toate drumurile elementare care exist n graf i se
afieaz. Dac nu exist nici un drum elementar, se afieaz un mesaj. Pentru testarea
programului se folosete graful orientat G9.
TU

#include <fstream.h>
typedef stiva[100];
int a[20][20],n,k,as,ev,x,este=0;
stiva st;
I

fstream f("graf2.txt",ios::in);
ED

void citeste() {//se citete matricea de adiacen din fiier}


222 Implementarea structurilor de date

C
void init() {//identic cu cea de la afiarea lanurilor elementare}
int succesor(){//ca cea de la afiarea lanurilor elementare}
int valid()

I
{if(k>1) if (a[st[k-1]][st[k]]==0) return 0;

OG
for (int i=1;i<k;i++) if (st[k]==st[i]) return 0;
return 1;}
int solutie() {return st[k]==y;}
void tipar ()
{for (int i=1,este=1;i<=k;i++) cout<<st[i]<<" "; cout<<x<<endl;}

AG
void bt() {//partea fixa a algoritmului }
void main()
{citeste();
for (x=1;x<=n;x++)
for (y=1;y<=n;y++) if (x!=y) {st[1]=x; bt();}

ED
if (!este) cout<<"Nu exista";}

2. Algoritmul Roy-Warshall de determinare a matricei drumurilor.


Matricea drumurilor este o matrice ptrat binar de dimensiune n (n reprezentnd

P
ordinul grafului), definit astfel:
1, dac exist drum de la nodul i la nodul j
I
a[i][j]
0, dac nu exist drum de la nodul i la nodul j
Informaiile din matricea drumurilor se pot folosi pentru a verifica dac exist drum
ntre dou noduri ale grafului

Algoritmul. Dac nu exist un arc de la nodul i la nodul j, considerm c exist drum de la


IC

nodul i la nodul j, dac exist un nod k (ki i kj) care are proprietatea c exist un drum
de la nodul i la nodul k i un drum de la nodul k la nodul j. Matricea
drumurilor se obine din matricea de adiacen prin transformri
CT

succesive, astfel: se genereaz toate nodurile k (1kn), iar pentru


fiecare nod k se genereaz toate perechile de noduri i (ik) i j (jk)
i se verific dac a[i][k]=1 i a[k][j]=1. n caz afirmativ, n matri- Fig. 26
cea de adiacen se atribuie valoarea 1 elementului a[i][j].
DA

1 2 3 4 5
G
G
G222222 Pentru graful G22 din figura 26 matricea de adiacen sufer 1 0 1 0 0 0
urmtoarele cinci transformri. La fiecare transformare, dac 2 0 0 1 0 0
drumul de la nodul i la nodul j trece prin nodul intermediar k 3 1 1 0 1 0
DI

(drumul trece de la nodul i la nodul k i de la nodul k la nodul 4 0 0 0 0 1


j), atunci elementului a[i][j] i se va atribui valoarea 1. 5 0 0 0 1 0
k=1 k=2 k=3
1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
RA

1 0 1 0 0 0 1 0 1 1 0 0 1 1 1 1 1 0
2 0 0 1 0 0 2 0 0 1 0 0 2 1 1 1 1 0
3 1 1 0 1 0 3 1 1 1 1 0 3 1 1 1 1 0
4 0 0 0 0 1 4 0 0 0 0 1 4 0 0 0 0 1
TU

5 0 0 0 1 0 5 0 0 0 1 0 5 0 0 0 1 0
k=4 k=5
1 2 3 4 5 1 2 3 4 5
1 1 1 1 1 0 1 1 1 1 1 1
I

2 1 1 1 1 0 2 1 1 1 1 1
ED

3 1 1 1 1 0 3 1 1 1 1 1
4 0 0 0 0 1 4 0 0 0 1 1
5 0 0 0 1 1 5 0 0 0 1 1
Informatic 223

C
Interpretarea datelor din matricea obinut n urma transformrilor se face astfel: exist
drum de la nodul i la nodul j dac a[i][j]=1. De exemplu, exist drum de la nodul 2
la nodul 4, dar nu exist drum de la nodul 4 la nodul 2.

I
Implementarea algoritmului. Se citete din fiierul graf20.txt matricea de adiacen a

OG
unui graf orientat. Se afieaz toate perechile de noduri din graf ntre care exist un
drum. Funcia citeste() se folosete pentru a citi matricea de adiacen din fiier.
Funcia transforma() se folosete pentru a transforma matricea de adiacen n matri-
cea drumurilor. Matricea de adiacen va suferi n transformri succesive (pentru fiecare

AG
nou valoare a lui k), astfel: fiecare element a[i][j], cu ik i jk, este nlocuit cu
valoarea produsului a[i][k]*a[k][j] ceea ce este echivalent cu a atribui valoarea 1
acestui element dac a[i][k]=1 i a[k][j]=1. Funcia afiseaza() se folosete pentru
a afia toate perechile de noduri i i j ntre care exist drum. Aceste perechi sunt identificate

ED
n matricea drumurilor ca fiind indicele pentru linie i indicele pentru coloan ale elementelor
care au valoarea 1. Pentru testarea programului se folosete graful orientat G22.
#include <fstream.h>
int a[20][20],n;

P
fstream f("graf20.txt",ios::in);
void citeste() {//se citete matricea de adiacen din fiier}
void transforma()
I
{for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(a[i][j]==0 && i!=k && j!=k) a[i][j]=a[i][k]*a[k][j];}

void afiseaza()
{cout<<"Exista drum intre perechile de noduri"<<endl;
IC

for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(a[i][j]==1 && i!=j) cout<<"("<<i<<","<<j<<")"<<" ";}
CT

void main() {citeste(); transforma(); afiseaza();}


Complexitatea algoritmului Roy-Warshall
Algoritmul de transformare a matricei de adiacen n matricea drumurilor are ordinul de com-
3
DA

plexitate O(nnn)= O(n ), deoarece fiecare structur repetitiv for se execut de n ori, iar
structurile for sunt imbricate.
Scriei un program care citete, din fiierul text graf4.txt, lista muchiilor
Tem unui graf orientat i care:
DI

a. Verific dac un ir de k numere citite de la tastatur reprezint un


drum elementar pentru graf.
b. Caut toate drumurile elementare cu lungimea cea mai mic dintre dou noduri x i y
i le afieaz. Etichetele nodurilor se citesc de la tastatur. Dac nu exist niciun
RA

drum elementar, s se afieze un mesaj.


c. Caut toate drumurile elementare de lungime maxim i afieaz cte drumuri s-au
gsit i care sunt ele. Dac nu exist niciun drum elementar, s se afieze un mesaj.
TU

2.7.7.4. Circuitul
ntr-un graf orientat un drum care are toate arcele distincte
dou cte dou i extremiti care coincid se numete circuit.
I

Circuitul este un drum simplu (arcele sunt distincte dou cte dou ([d1,d2][d2,d3];
ED

[d1,d2][d3,d4]; ...; [d1,d2][dk-1,dk]; ...; [dk-2,dk-1][dk-1,dk]) n care extremitile coincid (d1=dk).


224 Implementarea structurilor de date

C
Circuitul elementar este circuitul n care toate nodurile sunt distincte dou cte dou, cu
excepia primului i a ultimului care coincid.
Exemple Pentru graful orientat G20:

I
Lanul L10(1,1) ={1, 2, 3, 6, 3, 6, 3, 7, 6, 5, 4, 1} nu este un circuit, deoarece arcele

OG
[3,6] i [6,3] au fost parcurse de dou ori.
Lanul L11(1,1) = {1, 2, 3, 6, 3, 7, 6, 5, 2, 4, 1}=C1 este un circuit neelementar,
deoarece se repet eticheta nodurilor 3 i 6.
Lanul L12(1,1) = {1, 2, 3, 7, 6, 5, 4, 1} =C2 este un circuit elementar, deoarece nu se

AG
repet eticheta niciunui nod.
Teorema 14
Dac un graf conine un circuit, atunci conine i un circuit elementar.

ED
Demonstraie la fel ca demonstraia de la Teorema 11 de la subcapitolul Lanuri.

Algoritm pentru determinarea circuitelor elementare ntr-un graf orientat


Algoritimul. Se folosete acelai algoritm ca i n cazul determinrii ciclurilor elementare ntr-un

P
graf orientat, cu deosebirea c se ine cont de orientarea arcului care leag dou noduri.
#include <fstream.h>
typedef stiva[100];
I
int a[20][20],n,k,as,ev,x,este=0;
stiva st;
fstream f("graf2.txt",ios::in);

void citeste() {//se citete matricea de adiacen din fiier}


void init() {//identic cu cea de la afiarea lanurilor elementare}
int succesor() {//identic cu cea de la afiarea lanurilor elementare}
IC

int valid()
{if(k>1) if (a[st[k-1]][st[k]]==0) return 0;
for (int i=1;i<k;i++) if (st[k]==st[i]) return 0;
CT

return 1;}
int solutie() {return a[st[k]][x]==1 && k>1;}
//se obine soluia atunci cnd ultimul nod adugat este adiacent
//nodului x i n stiv exist cel puin dou noduri
DA

void tipar ()
{for (int i=1,este=1;i<=k;i++) cout<<st[i]<<" "; cout<<x<<endl;}
void bt() {//partea fixa a algoritmului }
void main() {citeste();
DI

for (x=1;x<=n;x++) {st[1]=x; bt();}


if (!este) cout<<"Nu exista circuite";}
Scriei un program care citete, din fiierul text graf4.txt, lista arcelor
Tem unui graf orientat i care:
RA

a. Caut toate circuitele elementare care exist n graf i le afieaz.


Dac nu exist niciun circuit elementar, se afieaz un mesaj.
b. Caut toate circuitele elementare de lungime maxim care trec printr-un nod x i le
afieaz. Eticheta nodului se citete de la tastatur. Dac nu exist niciun circuit
TU

elementar care s treac prin nodul x, se afieaz un mesaj.


c. Caut toate circuitele elementare care trec prin toate nodurile grafului i le afieaz.
Dac nu exist niciun circuit elementar care trece prin toate nodurile grafului, se
I

afieaz un mesaj.
ED
Informatic 225

C
d. Caut toate circuitele elementare care trec numai prin noduri care au gradul intern
egal cu gradul extern i le afieaz. Dac nu exist niciun circuit elementar, se
afieaz un mesaj.

I
OG
2.7.7.5. Graful conex
Un graf G se numete graf conex dac are proprietatea c, pentru
orice pereche de noduri diferite ntre ele, exist un lan care s le lege.

AG
Altfel spus, un graf este conex dac, pentru orice pereche de noduri {xi, xj}, care au
proprietatea xixj exist un lan de la xi la xj.
Exemple:
1. Graful neorientat G19 = (X19,U19) definit anterior este un graf conex, deoarece oricare ar

ED
fi dou noduri din mulimea Xx, ele pot fi legate printr-un lan. De exemplu, (1,2) {1,2}
sau {1,5,2}; (1,3) {1,2,3} sau {1,6,3}; (1,3) {1,2,3} sau {1,6,3}; (1,4) {1,2,3,4}
sau {1,6,7,4}; (1,5) {1,5} sau {1,2,6,5} etc.

P
2. Graful orientat G20 = (X20,U20) definit anterior este un graf conex, deoarece oricare ar fi
dou noduri din mulimea Xx, ele pot fi legate printr-un lan. De exemplu, (1,2) {1,2}
sau {1,4,2}; (1,3) {1,2,3} sau {1,2,5,6,3}; (1,3) {1,2, 3} sau {1,2,5,6,3}; (1,4) {1,
I
4} sau {1,2,5,4}; (1,5) {1,2,5} sau {1,4,5} etc.
3. Graful neorientat G23 = (X23,U23) figura 27 definit astfel: G
G
G222333
mulimea nodurilor este X23={1,2,3,4,5,6,7,8}.

mulimea muchiilor este U23 ={[1,2], [1,4], [2,3],


[2,4], [3,4], [5,6], [5,7] }.
IC

nu este conex, deoarece nu exist nici un lan ntre un


nod din mulimea C1={1,2,3,4} i un nod din mulimea
C2={5,6,7}, sau din mulimea C3={8}.
Fig. 27
CT

Dac un graf G=(X,U) nu este conex, se poate defini un


subgraf conex al grafului G, adic se poate defini o mulime X'X care s induc subgraful
G'=(X',U'), ce are proprietatea c este conex.
DA

Dac un graf G=(X,U) nu este conex, se numete component conex a grafului un


subgraf conex al su C=(X',U'), maximal n raport cu aceast proprietate (conine
numrul maxim de noduri din G care au proprietatea c sunt legate cu un lan).
Altfel spus, subgraful conex C este o component conex a grafului dac are proprietatea c
DI

nu exist nici un lan, al grafului G, care s uneasc un nod xi al subgrafului C (xiX') cu un


nod xj care nu aparine subgrafului C (xjXX').
Observaie: Un graf conex are o singur component conex (graful nsui).
RA

Exemplu n graful neorientat G23 definit anterior, fiecare dintre cele trei mulimi de noduri,
C1, C2 i C3, induce cte o component conex.
Dac un graf este definit prin mulimea nodurilor i mulimea muchiilor,
TU

mulimea nodurilor este X23={1,2,3,4,5,6,7,8}.


mulimea muchiilor este U23 ={[1,2], [1,4], [2,3], [2,4], [3,4], [5,6], [5,7] }.
pentru identificarea componentelor conexe, procedai astfel:
PAS1. Se formeaz prima component conex, pornind de la prima muchie. Se scriu
I

nodurile incidente cu muchia n prima component conex C1={1,2} i se mar-


ED

cheaz muchia: [1,2]. Componenta conex C1 este componenta curent.


226 Implementarea structurilor de date

C
PAS2. Se parcurg celelalte muchii. Dac se gsete o muchie nemarcat, care conine
noduri din componenta conex curent, se adaug nodurile la component:
C1={1,2,4,3}, i se marcheaz muchia: [1,4], [2,3], [2,4], [3,4].

I
PAS3. Dac mai exist muchii nemarcate, se identific prima muchie nemarcat i se formea-

OG
z urmtoarea component conex, scriind nodurile incidente cu muchia C2={5,6}
i se marcheaz muchia: [5,6]. Componenta conex C2 este componenta curent.
PAS4. Se parcurg celelalte muchii. Dac se gsete o muchie nemarcat care conine
noduri din componenta conex curent, se adaug nodurile la component:

AG
C2={5,6,7} i se marcheaz muchia: [5,7].
PAS5. Se execut Pasul 3 i Pasul 4 pn se marcheaz toate muchiile, identificnd
urmtoarele componente conexe.
PAS6. Se verific dac toate nodurile din mulimea nodurilor se regsesc ntr-o component
conex. Dac exist noduri care nu aparin unei componente conexe, acestea sunt

ED
noduri izolate, i vor forma, fiecare dintre ele, o component conex. C3={8}.
Teorema 15
Numrul minim de muchii mmin necesare pentru ca un graf neorientat, cu n noduri, s fie

P
conex este n1.
Altfel spus, ntr-un graf neorientat conex cu m muchii i n noduri: mn1.
I
Demonstraie. Notm cele dou propoziii, astfel:
(1) Graful G neorientat, cu n noduri, are n-1 muchii i este conex.
(2) Graful G neorientat, cu n noduri, este conex i minimal cu aceast proprietate (dac se nltur

orice muchie din graf, el devine neconex).


Trebuie s demonstrm c (1)(2) Se folosete principiul induciei matematice (se noteaz cu Pi
IC

propoziia i):
P1 Graful G1, cu un nod i nici o muchie (m=1-1=0), este conex i este minimal cu aceast
proprietate (nu mai exist muchii care s fie eliminate).
CT

P2 Graful G2, cu dou noduri i o muchie (m=2-1=1), este conex (muchia nu poate lega dect cele
dou noduri) i este minimal cu aceast proprietate (prin eliminarea muchiei, nodurile sunt izolate
obinndu-se dou componente conexe).
P3 Graful G3, cu trei noduri i dou muchii (m=3-1=2), este conex (cele dou muchii sunt incidente;
DA

unul dintre noduri este adiacent cu cele dou muchii i prin el va trece lanul care leag celelalte
dou noduri) i este minimal cu aceast proprietate (prin eliminarea unei muchii, unul dintre noduri
este izolat, obinndu-se dou componente conexe).
.
Pn Graful Gn, cu n noduri i n-1 muchii, este conex i minimal cu aceast proprietate (se presupune
DI

adevrat).
Pn+1 Considernd propoziia Pn adevrat, trebuie s demonstrm c graful Gn+1, cu n+1 noduri i
n+2 muchii, este conex i minimal cu aceast proprietate. Prin adugarea unui nod i a unei muchii la
graful Gn, se poate obine un graf conex. Nodul adugat se leag cu muchia nou de graful Gn (i,
RA

implicit, la lanurile din acest graf), obinndu-se un nou graf conex. Presupunem c graful obinut nu
este minimal cu aceast proprietate. nseamn c, prin eliminarea unei muchii, se obine un graf
conex. Dac eliminm muchia adugat, se izoleaz nodul n+1, obinndu-se dou componente
conexe. Dac se elimin o muchie din graful Gn, se obin dou componente conexe, deoarece graful
TU

Gn este minimal cu aceast proprietate. Rezult c graful Gn este minimal cu aceast proprietate.
Exemple de grafuri conexe cu n noduri i numr minim de muchii:
Fiecare nod este legat de alte dou, cu excepia a dou noduri terminale. Exist n2 noduri cu
gradul 2 i dou noduri cu gradul 1:
I
ED

2 (n 2) 2 1
m min n1
2
Informatic 227

C
Un nod este legat de celelalte n1 noduri. Exist un nod cu gradul n1 i n1 noduri cu gradul 1:
1 (n 1) (n 1) 1
m min n1
2

I
OG
Propoziia 4. Dac un graf cu n noduri are p componente conexe, atunci numrul minim
de muchii care trebuie adugate, ca s devin conex, este p1.
Demonstraie. Putem considera fiecare component conex ca un nod al unui graf cu p noduri.
Numrul minim de muchii necesare pentru ca acest graf s fie conex este p1.

AG
Propoziia 5. Dac un graf conex cu n noduri are n-1 muchii, atunci orice pereche de
noduri este legat printr-un lan, i numai unul.
Demonstraie prin reducere la absurd. Graful G fiind conex, nseamn c exist cel puin un lan
care leag oricare dou noduri, x i y. Presupunem c exist cel puin dou lanuri ntre nodurile x i

ED
y: L1 i L2. nseamn c, suprimnd o muchie din lanul al doilea, graful rmne conex, deoarece
nodurile x i y vor fi legate prin lanul L1. nseamn c un graf cu n noduri i n-2 muchii este conex,
ceea ce contrazice Teorema 15. Rezult c cele dou noduri, x i y, nu sunt legate dect printr-un
singur lan.

P
Propoziia 6. Dac un graf neorientat cu n noduri i m muchii este conex, numrul maxim
de muchii care se pot elimina pentru a obine un graf parial conex este: mn+1.
Demonstraie. Deoarece numrul minim de muchii necesare pentru ca un graf s fie conex este n1,
I
atunci din graf se pot elimina restul muchiilor: mn+1.
Teorema 16

Un graf neorientat conex cu n noduri i n1 muchii este aciclic i


maximal cu aceast proprietate.
IC

Demonstraie: Notm cele dou propoziii, astfel:


(1) Graful G neorientat, cu n noduri, este conex i are n-1 muchii.
(2) Graful G neorientat, cu n noduri, este aciclic i maximal cu aceast proprietate.
CT

Trebuie s demonstrm c (1)(2).


1) Este aciclic prin reducere la absurd. Presupunem c acest graf conine cel puin un ciclu,
C=x1, x2, x3, ..., xi, x1. nseamn c, dac vom nltura din graf muchia [x1, x2], se obine un graf
conex nodul va fi legat de toate celelalte noduri din ciclu prin lanul L=x2, x3, ..., xi, x1 ceea ce
DA

contrazice teorema anterioar, c un graf cu n noduri i n-1 muchii este conex i minimal cu
aceast proprietate.
2) Este maximal cu aceast proprietate (dac se adaug o nou muchie, graful nu mai este
aciclic) prin reducere la absurd. Presupunem c, prin adugarea unei muchii oarecare [x,y], se
obine un graf aciclic. Graful fiind conex, nseamn c ntre nodurile x i y exist un lan L(x,y) =x,
DI

..., z, , y, iar prin adugarea muchiei [x,y] lanul se nchide, formnd un ciclu C=x, ..., z,, y ,
x ceea ce contrazice presupunerea c graful este aciclic.
Propoziia 7. Dac un graf neorientat conex are n noduri i m muchii, numrul de muchii
RA

care trebuie eliminate, pentru a obine un graf parial conex aciclic, este egal cu mn+1.
Demonstraie. Din Propoziia 6, rezult c nlturnd din graf mn+1 muchii se obine un graf
parial conex, iar din Teorema 16 rezult c acest graf este aciclic. Graful fiind conex, nseamn c
ntre oricare dou noduri, xi i xj, exist un lan elementar i numai unul (Propoziia 5). Orice nou
TU

muchie [xi, xj] adugat va forma cu acest lan un ciclu elementar.


Propoziia 8. Dac un graf are n noduri, m muchii i p componente conexe, numrul de
muchii care trebuie eliminate, pentru a obine un graf parial aciclic, este egal cu m-n+p.
I

Demonstraie. Fiecare component conex i (1i p) va avea ni noduri i mi muchii, iar:


ED
228 Implementarea structurilor de date

C
p p
. n i n i m i m .
i 1 i 1
Numrul de muchii care trebuie eliminate din componenta conex i, pentru a obine un graf parial

I
conex aciclic, este egal cu mi - ni +1 (Propoziia 7). Rezult c numrul total de muchii care trebuie

OG
eliminate din graf, pentru a obine graf parial conex aciclic, este egal cu:
p p p
(m i n i 1) m i n i p m n p
i 1 i 1 i 1

AG
Propoziia 9. Pentru a obine, dintr-un graf neorientat conex, dou componente conexe,
numrul minim de muchii care trebuie nlturate mmin este egal cu gradul minim din graf:
mmin = gradmin.
Demonstraie. Cele dou componente conexe ale unui graf neorientat conex G=(X,U) se obin astfel:

ED
Componenta conex C1=(X1,U1) se formeaz dintr-un nod izolat xi pentru a elimina un numr
minim de muchii, nodul se alege dintre nodurile care au gradul minim: X1=xi i U1=.
Componenta conex C2=(X2,U2) se formeaz din restul nodurilor din graf: X2=Xxi i
card(U1)=mgradmin.

P
Teorema 17
Numrul maxim de muchii mmax dintr-un graf neorientat, cu n noduri i p componente
I
conexe, este:
(n p ) (n p 1)
m max
2

Demonstraie prin reducere la absurd. Numrul maxim de muchii corespunde unor p1


componente conexe formate din noduri izolate i o component conex format cu np+1 noduri.
IC

Pentru ca s se obin numrul maxim de muchii, ultima component trebuie s fie un graf complet
Knp+1 care are numrul de muchii m:
(n p ) (n p 1)
CT

m
2
S presupunem c exist ns un graf format din p2 componente conexe formate din noduri izolate
i cu dou componente conexe C1 cu n1 noduri i m1 muchii i C2 cu n2 noduri i m2 muchii, cu n1
n2 2, n1 + n2 = np+2 care are numrul maxim de muchii m1 + m2 = mmax. Cele dou componente
DA

conexe pentru a avea un numr maxim de muchii trebuie s fie grafuri complete: C1=Kn1 i C2=Kn2.
Modificm acest graf, mutnd un nod din componenta C2 n componenta C1. n componenta C1 acest
nod trebuie unit prin muchii cu cele n1 noduri ale componentei. Numrul de muchii ale componentei
C1 va fi m1 + n1. n componenta C2 prin eliminarea nodului, se nltur i cele n2 1 muchii care l
DI

uneau cu celelate noduri din graf. Numrul de muchii ale componentei C2 va fi m2 n2 + 1. Numrul
total de muchii al noului graf este m1 + n1 + m2 n2 + 1 m1 + m2 + 1 = mmax+ 1. Concluzia
contrazice ipoteza c graful iniial avea numrul maxim de muchii. nseamn c graful care are
numrul maxim de muchii este cel care conine p1 componente conexe formate din noduri izolate i
RA

o component conex format cu np+1 noduri care este graful complet Knp+1.

2.7.7.6. Graful tare conex


Un graf orientat G se numete graf tare conex dac are proprietatea c, pentru orice
TU

pereche de noduri diferite ntre ele, exist un drum care s le lege.


Altfel spus, un graf orientat este tare conex dac pentru orice pereche de noduri {xi, xj},
care au proprietatea xixj exist un drum de la xi la xj.
I
ED
Informatic 229

C
Exemple:
1. Graful orientat G20 = (X20,U20), definit anterior, este un graf tare conex, deoarece exist
un circuit elementar care trece prin toate nodurile grafului: {1,2,3,7,6,5,4,1}; altfel spus,

I
oricare ar fi dou noduri din mulimea X20, ele pot fi legate printr-un drum.

OG
2. Graful orientat G24 = (X24,U24) figura 28 definit astfel: GG
G222444
mulimea nodurilor este X24={1,2,3,4,5,6}.
mulimea arcelor este U24 ={[1,2], [1,4], [2,3], [3,1], [4,5], [5,4]}.
nu este conex, deoarece nu exist nici un drum ntre un nod

AG
din mulimea C2={4,5} i un nod din mulimea C1={1,2,3},
sau din mulimea C3={6}.
Dac un graf orientat G=(X,U) nu este tare conex, se poate
defini un subgraf tare conex al grafului G, adic se poate

ED
defini o mulime X'X care s induc subgraful G'=(X',U'), ce
are proprietatea c este tare conex. Fig. 28

Dac un graf G=(X,U) nu este conex, se numete component tare conex a grafului

P
un subgraf conex C=(X',U') al su, maximal n raport cu aceast proprietate (conine
numrul maxim de noduri din G care au proprietatea c sunt legate printr-un drum).
I
Altfel spus, subgraful tare conex C este o component tare conex a grafului dac are
proprietatea c nu exist nici un drum al grafului G care s uneasc un nod xi al subgrafului
C (xiX') cu un nod xj care nu aparine subgrafului C (xjX-X').

Exemplu n graful orientat G24 definit anterior, fiecare dintre cele trei mulimi de noduri
C1, C2 i C3 induce cte o component tare conex.
IC

Observaie: Un graf tare conex are o singur component tare conex (graful nsui).
Terminologie:
CT

Subgraful predecesorilor unui nod este format din acel nod i din mulimea nodurilor
din care este accesibil nodul.
Subgraful succesorilor unui nod este format din acel nod i din mulimea nodurilor
care sunt accesibile din el.
DA

Observaie: Componenta tare conex din care face parte un nod este dat de
intersecia dintre subgraful predecesorilor i subgraful succesorilor acelui nod.
Dac un graf este definit prin mulimea nodurilor i mulimea muchiilor,
DI

mulimea nodurilor este X24={1,2,3,4,5,6}.


mulimea arcelor este U24 ={[1,2], [1,4], [2,3], [3,1], [4,5], [5,4]}.
pentru identificarea componentelor tare conexe procedai astfel:
PAS1. Se identific subgraful succesorilor primului nod din primul arc (n exemplu, nodul
RA

1), folosind algoritmul de determinare a unei componente conexe: S1={1,2,3,4,5}.


PAS2. Se identific subgraful predecesorilor primului nod din primul arc (n exemplu,
nodul 1), folosind algoritmul de determinare a unei componente conexe, n care
se iau n calcul numai nodurile care apar n arc n a doua poziie: P1={1,2,3}.
TU

PAS3. Se determin componenta tare conex prin intersecia celor dou mulimi de
noduri: C1= S1 P1 ={1,2,3}.
PAS4. Se identific, n mulimea arcelor, primul nod care nu face parte din componenta
I

tare conex evideniat anterior (n exemplu, nodul 4) i se reiau Pasul 1, Pasul 2


ED

i Pasul 3, pentru a determina subgraful succesorilor, respectiv subgraful predece-


230 Implementarea structurilor de date

C
sorilor nodului i apoi urmtoarea component conex, prin intersecia celor dou
mulimi (n exemplu, nodul 4 i S2={4,5}, P2={1,2,3,4,5} i C2= S2 P2 ={4,5}). Se
repet acest pas pn cnd nu se mai identific n mulimea arcelor niciun nod

I
care s nu aparin unei componente tare conexe.

OG
PAS5. Se verific dac toate nodurile din mulimea nodurilor se regsesc ntr-o
component tare conex. Dac exist noduri care nu aparin unei componente
tare conexe, acestea sunt noduri izolate i vor forma, fiecare dintre ele o
component conex. C3={6}.

AG
Graful componentelor tare conexe ale unui graf care nu este tare conex G=(X,U)
se obine prin reducerea fiecrei componente conexe la un nod.
Identificarea grafului componentelor tare conexe este util n rezolvarea unor probleme,
prin descompunerea problemei n subprobleme (rezolvarea problemei pentru fiecare com-

ED
ponent tare conex) i combinarea soluiilor strategia divide et impera.
Exemplu:
G
GG222555 n graful orientat G25 = (X25,U25) figura 29 definit astfel:

P
mulimea nodurilor este X25={1,2,3,4,5,6,7}.
mulimea arcelor este U25 ={[1,2], [1,4], [2,3], [3,1], [4,5],
[5,6], [6,4], [7,5], [7,3]}.
I
G
G
Gccc222555 componentele tare conexe sunt C1={1,2,3}, C2={4,5,6} i C3={7},
iar graful componentelor tare conexe Gc25 = (Xc25,Uc25) figura Fig. 29
30 este definit astfel.

mulimea nodurilor este Xc25={ C1, C2, C3}.


mulimea arcelor este Uc25 ={[ C1, C2], [ C3, C1], [ C3, C2]}.
IC

Algoritmi pentru determinarea conexitii grafurilor Fig. 30


CT

1. Determinarea componentelor conexe ntr-un graf.


Algoritmul. O component conex este format din toate nodurile ntre care exist un lan
elementar. Deoarece un nod nu poate s aparin dect unei componente conexe, se va
folosi un vector cu n elemente pentru a memora nodurile care au fost deja nregistrate ntr-o
DA

component conex. Iniial, elementele vectorului au valoarea 0 (nici un nod nu a fost


nregistrat ntr-o component conex), iar dac un nod x va fi adugat la o component
conex, valoarea elementului x din vector va fi 1. Pentru a verifica dac exist un lan
elementar ntre dou noduri x i y se folosee metoda backtracking.
DI

Observaie. Acest algoritm poate fi folosit att n grafurile neorientate, ct i n grafurile


orientate. Mai poate fi folosit i pentru a verifica dac un graf este conex: fie se verific
dac ntre nodul 1 i fiecare dintre celelalte noduri ale grafului exist un lan elementar, fie
RA

se verific dac prima component conex obinut conine toate nodurile grafului.
Implementarea algoritmului. Se citete din fiierul graf19.txt matricea de adiacen a unui
graf neorientat (varianta din fiierul graf20.txt matricea de adiacen a unui graf orientat)
i se afieaz componentele conexe. n vectorul v se memoreaz nodurile care au fost deja
TU

nregistrate ntr-o component conex. Variabila este se folosete pentru a verifica dac
s-a gsit un lan elementar ntre dou noduri (are valoarea 0 False, dac nu s-a gsit un
lan elementar). Variabila m se folosete pentru a numra componentele conexe identifi-
I

cate. Funcia citeste() se folosete pentru a citi matricea de adiacen din fiier. Funcia
ED

componente() se folosete pentru a afia componentele conexe ale grafului: pentru fiecare
Informatic 231

C
nod x (1xn) care nu a fost afiat ntr-o component conex (v[x]=0), se caut toate no-
durile y (1yn i yx ) care sunt legate cu un lan elementar de nodul x. Pentru un nod y
gsit, se marcheaz n vectorul v faptul c a fost adugat la o component conex

I
(v[y]=1). Pentru testarea programului se folosesc graful neorientat G4 i graful neorientat G22.

OG
#include <fstream.h>
typedef stiva[100];
int a[20][20],n,k,as,ev,x,y,v[20],este=0;
stiva st;

AG
fstream f("gr8af19.txt",ios::in);
void citeste() {//se citete matricea de adiacen din fiier}
void init(){//identic cu cea de la afiarea lanurilor elementare}
int succesor() {//identic cu cea de la afiarea lanurilor elementare}
int valid() {//identic cu cea de la afiarea lanurilor elementare}

ED
int solutie() {return st[k]==y;}
//se obine soluia atunci cnd ultimul nod adugat n stiv este y
void tipar() {este=1;}
//dac exist soluie (un lan ntre nodurile x i y),

P
//variabila este va avea valoarea 1
void bt() {//identic cu cea de la afiarea lanurilor elementare }
void componente()
I
{int m=0;
for(x=1;x<=n;x++)
if (v[x]==0)
{m++; st[1]=x; v[x]=1;

cout<<"Componenta conexa "<<m<<": "<<x<<" ";


for(y=1;y<=n;y++)
IC

if (x!=y) {este=0; bt();


if (este) {v[y]=1; cout<<y<<" ";}}
cout<<endl;}}
CT

void main() {citeste(); componente();}


2. Determinarea componentelor conexe ntr-un graf orientat.
Algoritmul. O component conex este format din toate nodurile ntre care exist un
drum, cel puin de la un nod la altul (drumul nu trebuie s asigure legtura n ambele
DA

sensuri). Altfel spus, dac exist un drum de la un nod x la un nod y, cele dou noduri x i
y aparin aceleiai componente conexe chiar dac nu exist i un drum de la nodul y la
nodul x. i n acest algoritm se folosete un vector cu n elemente pentru a memora
nodurile care au fost deja nregistrate ntr-o component conex. Pentru a verifica dac
DI

exist un drum de la nodul x la nodul y se folosete matricea drumurilor.


Pentru graful G22 din figura 26, n matricea drumurilor se observ c exist drum de la
nodul 1 la oricare celelalte patru noduri din graf. Graful are o singur component conex.
RA

Implementarea algoritmului. Se citete din fiierul graf20.txt 1 2 3 4 5


matricea de adiacen a unui graf orientat i se determin 1 1 1 1 1 1
dac graful este conex. Dac nu este, se afieaz compo- 2 1 1 1 1 1
nentele conexe. n vectorul v se memoreaz nodurile care au 3 1 1 1 1 1
TU

fost deja nregistrate ntr-o component conex. Funcia 4 0 0 0 1 1


5 0 0 0 1 1
citeste() se folosete pentru a citi matricea de adiacen n
fiier. Funcia transform() se folosete pentru a transforma matricea de adiacen n
I

matricea drumurilor. Funcia componente() se folosete pentru a afia componentele conexe


ED

ale grafului: pentru fiecare nod i (1i n) care nu a fost afiat ntr-o component conex
232 Implementarea structurilor de date

C
(v[i]=0), se caut toate nodurile j (1j n i ji) la care ajunge un drum ce pornete din nodul
i. Pentru un nod j gsit, se marcheaz n vectorul v faptul c a fost adugat la o component
conex (v[j]=1). Pentru testarea programului se folosete graful orientat G22.

I
#include <fstream.h>

OG
typedef stiva[100];
int a[20][20],n,v[20];
fstream f("graf20.txt",ios::in);
void citeste() {//se citete matricea de adiacen din fiier}
void transforma()

AG
{for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(a[i][j]==0 && i!=k && j!=k) a[i][j]=a[i][k]*a[k][j];}

ED
void componente()
{int i,j,m=0;
for(int i=1;i<=n;i++)
if (v[i]==0)

P
{m++; v[i]=1; cout<<"Componenta conexa "<<m<<": "<<i<<" ";
for(int j=1;j<=n;j++)
if(a[i][j]==1 && i!=j) {v[j]=1; cout<<j<<" ";}
I
cout<<endl;}}
void main() {citeste(); transforma(); componente();}

3. Determinarea componentelor tare conexe ntr-un graf orientat.


Algoritmul. O component tare conex este format din toate nodurile i i j ntre care
exist un drum elementar de la nodul i la nodul j, dar i de la nodul j la nodul i. Se
IC

folosete un vector cu n elemente, pentru a memora nodurile care au fost deja nregistrate
ntr-o component tare conex. Iniial, elementele vectorului au valoarea 0 (nici un nod nu a
fost nregistrat ntr-o component conex), iar dac un nod i va fi adugat la o component
CT

conex, valoarea elementului i din vector va fi 1. Pentru a verifica dac exist un drum
elementar de la nodul i la nodul j, se pot folosi dou variante ale algoritmului:
Varianta 1. Se folosee metoda backtracking.
DA

Implementarea algoritmului. Se citete din fiierul graf20.txt matricea de adiacen a unui


graf orientat i se determin dac graful este tare conex. Dac nu este, se afieaz compo-
nentele tare conexe. Variabila este1 se folosete pentru a verifica dac s-a gsit un drum
elementar de la nodul i la nodul j (are valoarea 0 False, dac nu s-a gsit un drum ele-
DI

mentar), variabila este2 se folosete pentru a verifica dac s-a gsit un drum elementar de
la nodul j la nodul i (are valoarea 0 False, dac nu s-a gsit un drum elementar), iar
variabila este se folosete pentru a verifica dac s-a gsit un drum elementar de la nodul x
RA

la nodul y (are valoarea 0 False, dac nu s-a gsit un drum elementar). n vectorul v se
memoreaz nodurile care au fost deja nregistrate ntr-o component tare conex. Variabila m
se folosete pentru a numra componentele conexe identificate. Funcia citeste() se folo-
sete pentru a citi matricea de adiacen din fiier. Funcia componente() se folosete pen-
TU

tru a afia componentele tare conexe ale grafului: pentru fiecare nod i (1in) care nu a fost
afiat ntr-o component conex (v[i]=0), se caut toate nodurile j (1jn i ji) care sunt
legate cu un drum elementar care pornete din nodul i, dar i de la care pornete un drum
care ajunge n nodul i. Pentru un nod j gsit, se marcheaz n vectorul v faptul c a fost
I

adugat la o component tare conex (v[j]=1). Pentru testarea programului se folosete


ED

graful orientat G22.


Informatic 233

C
#include <fstream.h>
typedef stiva[100];
int a[20][20],n,k,as,ev,x,y,v[20],este1,este2,este=0;

I
stiva st;

OG
fstream f("graf19.txt",ios::in);
void citeste(){//se citete matricea de adiacen din fiier}
void init() {//identic cu cea de la afiarea drumurilor elementare}
int succesor() {//identic cu cea de la afiarea drumurilor elementare}
int valid() {//identic cu cea de la afiarea drumurilor elementare}

AG
int solutie() {return st[k]==y;}
//se obine soluia atunci cnd ultimul nod adugat n stiv este y
void tipar() {este=1;}
//dac exist soluie (un drum ntre nodurile x i y),
//variabila este va avea valoarea 1

ED
void bt() {//identic cu cea de la afiarea drumurilor elementare }
void componente()
{int i,j,m=0;
for(i=1;i<=n;i++)

P
if (v[i]==0)
{m++; v[i]=1; cout<<"Componenta conexa "<<m<<": "<<i<<" ";
for(j=1;j<=n;j++)
I
if (j!=i)
{x=i; y=j; st[1]=x; este=0; bt(); este1=este;
x=j; y=i; st[1]=x; este=0; bt(); este2=este;
if (este1 && este2) {v[j]=1; cout<<j<<" ";}}

cout<<endl;}}
void main() {citeste(); componente();}
IC

Varianta 2. Se folosete matricea drumurilor. Se determin dou matrice ale drumurilor:


una corespunztoare grafului G i alta corespunztoare unui graf n care toate arcele au
CT

sensul invers dect n graful G (Gt graful transpus al grafului G). Din intersecia celor
dou matrice, se va obine o matrice n care vor fi evideniate numai drumurile care exist
n ambele sensuri, ntre oricare dou noduri i i j.
Pentru graful G22 din figura 26, prin inversarea arcelor se obine G
G
G222222ttt
DA

graful transpus G22t din figura 31. Matricele de adiacen i matri-


cele drumurilor pentru cele dou grafuri i matricea intersecie sunt
prezentate mai jos.
Matricea de adiacen G22 Matricea drumurilor G22 Fig. 31
DI

1 2 3 4 5 1 2 3 4 5
1 0 1 0 0 0 1 1 1 1 1 1
2 0 0 1 0 0 2 1 1 1 1 1
3 1 0 0 1 0 3 1 1 1 1 1
RA

Matricea intersecie
4 0 0 0 0 1 4 0 0 0 1 1
1 2 3 4 5
5 0 0 0 1 0 5 0 0 0 1 1
1 1 1 1 0 0
2 1 1 1 0 0
Matricea drumurilor G22t
TU

Matricea de adiacen G22t 3 1 1 1 0 0


1 2 3 4 5 1 2 3 4 5 4 0 0 0 1 1
1 0 0 1 0 0 1 1 1 1 0 0 5 0 0 0 1 1
2 1 0 0 0 0 2 1 1 1 0 0
3 0 1 0 0 0 3 1 1 1 0 0
I
ED

4 0 0 1 0 1 4 1 1 1 1 1
5 0 0 0 1 0 5 1 1 1 1 1
234 Implementarea structurilor de date

C
Interpretarea datelor din matricea intersecie se face astfel: dou noduri i i j fac parte
din aceeai component tare conex dac exist drum de la nodul i la nodul j
(a[i][j]=1). Pe matricea intersecie se pot identifica cele dou componente conexe:

I
C1={1,2,3} i C2={4,5}.

OG
Implementarea algoritmului. Se citete din fiierul graf20.txt matricea de adiacen a a
unui graf orientat. Se folosete matricea ap n care se memoreaz arcele n sens invers i
matricea drumurilor obinut din aceasta. Pentru a identifica nodurile i i j ntre care exist
un drum att de la nodul i la nodul j, ct i de la nodul j la nodul i, se obine matricea b

AG
care este intersecia celor dou matrice ale drumurilor: a i ap. Funcia citeste() se folo-
sete pentru a citi matricea de adiacen din fiier. Funcia transforma_s() se folosete
pentru a transforma matricea de adiacen a n matricea drumurilor, iar funcia
transforma_p() pentru a transforma matricea de adiacen ap n matricea drumurilor.

ED
Funcia intersectie() se folosete pentru a obine intersecia celor dou matrice ale
drumurilor. Funcia componente() se folosete pentru a afia componentele conexe ale
grafului: pentru fiecare nod i (1in) care nu a fost afiat ntr-o component conex
(v[i]=0), se caut n matricea intersecie a drumurilor b toate nodurile j (1jn i ji) la

P
care ajunge un drum ce pornete din nodul i. Pentru un nod j gsit, se marcheaz n
vectorul v faptul c a fost adugat la o component tare conex (v[j]=1). Pentru testarea
programului se folosete graful orientat G22.
I
#include <fstream.h>
typedef stiva[100];
int a[20][20],n,v[20],ap[10][10],b[10][10],nr;

fstream f("graf19.txt",ios::in);
void citeste() {//se citete matricea de adiacen din fiier}
IC

void predecesor()
{for(int i=1;i<=n;i++)
for (int j=1;j<=n;j++) ap[i][j]=a[j][i];}
void transforma_s()
CT

{for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(a[i][j]==0 && i!=k && j!=k) a[i][j]=a[i][k]*a[k][j];}
DA

void transforma p()


{for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
DI

if(ap[i][j]==0 && i!=k && j!=k) ap[i][j]=ap[i][k]*ap[k][j];}


void intersectie()
{for(int i=1;i<=n;i++)
for (int j=1;j<=n;j++) b[i][j]= as[i][j]*ap[i][j];}
RA

void componente()
{for(int i=1;i<=n;i++)
if (v[i]==0)
{nr++; v[i]=1; cout<<endl<<"Componenta "<<nr<<": "<<i<<" ";
TU

for (int j=1;j<=n;j++)


if (b[i][j]==1 && i!=j) {cout<<j<<" "; v[j]=1;}}}
void main()
{citeste(); predecesor(); transforma_s(); transforma_p();
intersectie(); componente();}
I
ED
Informatic 235

C
1. Scriei un program care citete din fiierul text graf3.txt (graf4.txt)
lista muchiilor (arcelor) unui graf neorientat (orientat) i care
Tem verific dac graful este conex i afieaz un mesaj de informare.

I
2. Scriei un program care citete din fiierul text graf14.txt lista de

OG
adiacen a unui graf orientat i care verific dac graful este tare conex i afieaz
un mesaj de informare.
3. Comparai, din punct de vedere al eficienei, cei doi algoritmi de determinare a compo-
nentelor tare conexe dintr-un graf orientat.

AG
4. Scriei un program care citete din fiierul text graf2.txt matricea de adiacen a unui
graf orientat i care determin graful componentelor tare conexe i numrul minim
de arce care trebuie adugate pentru ca graful s devin tare conex. Soluiile pentru
arcele care trebuie adugate se vor salva n fiierul text graf_comp.txt. Indicaie: Cele
p componente tare conexe vor fi noduri n noul graf i vor fi reprezentate printr-un

ED
vector cu p elemente de tip nregistrare:
struct comp {int n;
int v[10];};
comp c[10];

P
iar arcele vor fi reprezenate prin matrice de adiacen. O component conex, c[i]
are c[i].n noduri; un nod j al componentei i fiind c[i].v[j].
I
2.7.7.7. Aplicaii practice
1. Din grupul de n persoane ntre care s-au stabilit relaii de prietenie i de vecintate,

determinai grupurile de prieteni, grupurile de vecini i grupurile de vecini prieteni.


(Indicaie. Se determin componentele conexe pentru fiecare graf.)
IC

2. Folosind informaiile din graful judeelor determinai numrul minim, respectiv numrul
maxim, de judee prin care trebuie s treac un turist care tranziteaz prin Romnia,
tiind c vine din Ungaria i trebuie s ajung n Bulgaria. (Indicaie. Se determin un
CT

lan de lungime minim, respectiv maxim, ntre dou judee limitrofe, care sunt la
grania cu cele dou ri.)
3. Din graful grotelor stabilii grotele care vor fi inundate de un pru subteran care izvorte
dintr-o grot a crei etichet se citete de la tastatur. Precizai tunelul (sau tunelurile) prin
DA

care prul va ajunge n exteriorul muntelui. (Indicaie. O grot este inundat dac se
gsete la acelai nivel sau la un nivel mai jos dect o grot n care exist ap. Se
transform graful neorientat ntr-un graf orientat, n care arcele vor pune n eviden
relaia: grota x este n relaie cu grota y dac apa curge de la grota x la grota y. n acest
DI

graf determinai toate drumurile care pornesc din grota din care izvorte prul).
4. n reeaua de strzi a oraului, patru strzi se nchid pentru a fi reparate. Etichetele
interseciilor care sunt legate de aceste strzi se citesc de la tastatur. S se verifice
RA

dac prin nchiderea acestor strzi nu se izoleaz unele zone ale oraului de alte zone.
(Indicaie. Se genereaz graful parial al traficului, prin eliminarea arcelor dintre nodurile
precizate i se verific dac graful obinut este tare conex.)
TU

2.7.8. Parcurgerea grafului


Parcurgerea grafului reprezint operaia prin care sunt examinate n mod sistematic
nodurile sale, pornind de la un nod dat i, astfel nct fiecare nod accesibil din nodul i pe
I

muchiile (arcele) adiacente s fie atins o singur dat. Vecinii unui nod sunt reprezentai
ED

de toate nodurile adiacente lui i accesibile din el.


236 Implementarea structurilor de date

C
Vizitarea sau traversarea unui graf este operaia prin care se parcurge graful trecndu-se
de la un nod i (nodul curent) la nodurile vecine lui, ntr-o anumit ordine, n vederea
prelucrrii informaiilor asociate nodurilor. Pentru parcurgerea grafurilor, exist urmtoa-

I
rele dou metode:

OG
1. Metoda de parcurgere n lime" Breadth First (BF). Se viziteaz mai nti un nod
iniial i, apoi vecinii acestuia, apoi vecinii nevizitai ai acestora, i aa mai departe
pn cnd se parcurg toate nodurile grafului.
2. Metoda de parcurgere n adncime" Depth First (DF). Se viziteaz mai nti un

AG
nod iniial i, dup care se parcurge primul dintre vecinii si nevizitai, de exemplu j, dup
care se trece la primul vecin nevizitat al lul j, i aa mai departe pn cnd se parcurge
n adncime ramura respectiv. Cnd s-a ajuns la captul ei, se revine la nodul din care
s-a plecat ultima dat, i se parcurge urmtorul su vecin nevizitat.

ED
G
G
G222666 Exemplu pentru graful neorientat G26 = (X26,U26) figura 32 definit astfel:
mulimea nodurilor este X26={1,2,3,4,5,6,7,8,9}.
mulimea muchiilor este U26={[1,2], [1,3], [1,4], [2,5], [3,5], [3,6],
[3,7], [4,7], [5,8], [6,8], [6,9]}.

P
Graful G26 poate fi parcurs astfel, pornind din nodul 1:
1. n cazul metodei de parcurgere BF n lime", vor fi parcurse pe rnd Fig. 32
I
nodurile:
1, 2, 3, 4, 5, 6, 7, 8, 9
2. n cazul metodei de parcurgere DF n adncime", vor fi parcurse pe rnd nodurile:

1, 2, 5, 3, 6, 8, 9, 7, 4
IC

2.7.8.1. Parcurgerea n lime Breadth First


Pentru aceast metod de parcurgere a unui graf cu n noduri, se folosesc urmtoarele
structuri de date i date elementare:
CT

1. Variabilele de memorie: n pentru numrul de noduri ale grafului, k pentru nodul care
se prelucreaz, i i j pentru parcurgerea matricei de adiacen i a vectorilor.
2. Matricea de adiacen a grafului a.
3. Vectorul de vizitare vizitat. El conine n elemente n care se nregistreaz nodu-
DA

rile vizitate. Elementele vectorului vizitat[i] sunt definite astfel:


1, dac nodul i a fost vizitat
vizitat [i]
0, dac nodul i nu a fost vizitat nc
DI

4. Coada de ateptare c a nodurilor parcurse. Coada de ateptare c gestioneaz nodurile


prelucrate. Pentru coada de ateptare se folosete implementarea static cu un vector c
cu n elemente. Pentru gestionarea cozii de ateptare se folosesc dou variabile de
RA

memorie prim i ultim care joac rolul de indicatori pentru a memora adresa primului
element din list (capul cozii) i, respectiv, adresa ultimului element din list (coada cozii).
n aceast coad de ateptare vor fi nregistrate nodurile vizitate, n ordinea n care au fost
vizitate. Iniial, coada de ateptare conine un singur element care corespunde nodului cu
TU

care ncepe parcurgerea grafului, iar valoarea indicatorilor prim i ultim este 1. Pe
msur ce se parcurge graful, se completeaz urmtoarele elemente ale vectorului c.
Atunci cnd se prelucreaz un nod k de la capul cozii de ateptare, prin coada cozii de
ateptare se introduc toate nodurile i vecine cu nodul k care nu au fost vizitate nc.
I

Algoritmul pentru parcurgerea grafului este urmtorul:


ED

PAS1. Se citesc din fiier, valoarea pentru variabila n i matricea de adiacen a grafului.
Informatic 237

C
PAS2. Se iniializeaz cu 0 elementele vectorului de vizitare vizitat, deoarece iniial
nici unul dintre noduri nu a fost vizitat.
PAS3. Se introduce de la tastatur valoarea variabilei de memorie k, corespunztoare

I
primului nod cu care ncepe parcurgerea grafului.

OG
PAS4. Se iniializeaz coada de ateptare c (indicatorii i coninutul primului element intro-
dus n coada de ateptare), astfel: prim1, ultim1 i c[prim]k, deoarece,
n coada de ateptare c este nregistrat doar nodul k cu care ncepe parcurgerea.
PAS5. Se actualizeaz vectorul vizitat atribuind elementului k al vectorului

AG
valoarea 1, deoarece a fost vizitat (vizitat[k]1).
PAS6. Ct timp coada nu este vid (prim<=ultim) execut
PAS7. Se extrage urmtorul element din coada de ateptare, corespunztor
nodului cruia i se vor vizita vecinii (kc[prim];).
PAS8. Pentru toate nodurile i vecine ale vrfului k, nevizitate nc, execut

ED
PAS9. Se incrementeaz valoarea indicatorului ultim, pentru a nregis-
tra urmtorul nod care va trebui vizitat prin adugare la coada
cozii de ateptare (ultimultim+1;).
PAS10. Se adaug la sfritul cozii de ateptare c, nodul i vecin nodului

P
k care nu a fost nc vizitat (c[ultim] i;).
PAS11. Prin adugarea nodului j la coada de ateptare c se consider c
I
acest nod a fost vizitat i se actualizeaz elementul din vectorul
de vizitare care corespunde acestui nod (vizitat[i]1;). Se
revine la Pasul 6.
PAS12. Se pregtete indicatorul prim pentru a se extrage urmtorul nod din

coada de ateptare, ai crui vecini vor fi vizitai (primprim+1;). Se


revine la Pasul 7.
IC

PAS13. Se afieaz lista nodurilor vizitate, n ordinea n care au fost vizitate, prin extrage-
rea lor din vectorul c, pornind de la elementul 1 i pn la elementul n.
CT

Pentru graful G26, pornind din nodul 1, nodurile n coada de ateptare sunt adugate astfel:
vizitat 1 0 0 0 0 0 0 0 0
1 2 3 4 5 6 7 8 9 10
c 1
DA

Iniializarea cozii de ateptare cu primul nod: prim=1; ultim=1.


vizitat 1 1 1 1 0 0 0 0 0
1 2 3 4 5 6 7 8 9 10
DI

c 1 2 3 4
Prelucrarea nodului: prim=1 ultim=4.
vizitat 1 1 1 1 1 0 0 0 0
RA

1 2 3 4 5 6 7 8 9 10
c 1 2 3 4 5
Prelucrarea nodului: prim=2 ultim=5.
vizitat 1 1 1 1 1 1 1 0 0
TU

1 2 3 4 5 6 7 8 9 10
c 1 2 3 4 5 6 7
Prelucrarea nodului: prim=3 ultim=7.
I
ED
238 Implementarea structurilor de date

C
vizitat 1 1 1 1 1 1 1 0 0
1 2 3 4 5 6 7 8 9 10
c 1 2 3 4 5 6 7

I
Prelucrarea nodului: prim=4 ultim=7.

OG
vizitat 1 1 1 1 1 1 1 1 0
1 2 3 4 5 6 7 8 9 10
c 1 2 3 4 5 6 7 8
Prelucrarea nodului: prim=5 ultim=8.

AG
vizitat 1 1 1 1 1 1 1 1 1
1 2 3 4 5 6 7 8 9 10
c 1 2 3 4 5 6 7 8 9

ED
Prelucrarea nodului: prim=6 ultim=9.
vizitat 1 1 1 1 1 1 1 1 1
1 2 3 4 5 6 7 8 9 10

P
c 1 2 3 4 5 6 7 8 9
Prelucrarea nodului: prim=7 ultim=9.
vizitat 1 1 1 1 1 1 1 1 1
I
1 2 3 4 5 6 7 8 9 10
c 1 2 3 4 5 6 7 8 9
Prelucrarea nodului: prim=8 ultim=9.

vizitat 1 1 1 1 1 1 1 1 1
IC

1 2 3 4 5 6 7 8 9 10
c 1 2 3 4 5 6 7 8 9
Prelucrarea nodului: prim=9 ultim=9.
CT

vizitat 1 1 1 1 1 1 1 1 1
1 2 3 4 5 6 7 8 9 10
c 1 2 3 4 5 6 7 8 9
DA

Prelucrarea nodului: prim=10 ultim=9. Terminare: prim>ultim


Pentru implementarea algoritmului se folosesc subprogramele:
funcia procedural citeste creeaz matricea de adiacen, prin preluarea infor-
maiilor din fiierul f (dimensiunea matricei de adiacen i matricea);
DI

funcia procedural init iniializeaz coada de ateptare cu primul nod vizitat;


funcia operand este_vida testeaz coada de ateptare dac este vid;
funcia procedural adauga adaug un nod la coada de atepare;
RA

funcia procedural elimina elimin nodul prelucrat din coada de ateptare;


funcia procedural prelucrare prelucreaz primul nod din coad: adaug la coada de
ateptare toi vecinii nevizitai ai acestui nod i apoi l elimin din coada de ateptare;
funcia procedural afisare afieaz nodurile grafului n ordinea prelucrrii.
TU

Pentru testarea programului, se folosete graful neorientat G26, a crui matrice de adia-
cen se citete din fiierul text graf21.txt.
int n,a[10][10],vizitat[20],c[20],prim,ultim,k;
fstream f("graf21.txt",ios::in);
I

void citeste() {//se citete matricea de adiacen din fiier}


ED

void init(int k) {prim=ultim=1; c[ultim]=k; vizitat[k]=1;}


Informatic 239

C
int este_vida() {return ultim<prim;}
void adauga(int i) {ultim++; c[ultim]=i; vizitat[i]=1;}
void elimina() {prim++;}

I
void prelucrare()

OG
{int i; k=c[prim];
for (i=1;i<=n;i++) if (a[k][i]==1 && vizitat[i]==0) adauga(i);
elimina();}
void afisare()

AG
{for (int i=1;i<=n;i++) cout<<c[i]<<" ";}
void main()
{citeste(); cout<<"nod de pornire: "; cin>>k; init(k);
while (!este vida()) prelucrare();
cout<<"Nodurile vizitate prin metoda BF sunt: "<<endl; afisare();}

ED
Atenie Prin parcurgerea n lime a unui graf, determinai lanurile, res-
pectiv drumurile de lungime minim.

P
Complexitatea algoritmului de parcurgere n lime
Algoritmul const n eliminarea unui nod din coada de ateptare i adugarea vecinilor
I
(succesorilor) si n coada de ateptare. Fiecare nod va fi adugat n coada de ateptare
o dat i, prin urmare, va fi eliminat din coada de atepare o singur dat. Complexitatea
operaiilor de eliminare a celor n noduri din coada de ateptare este O(n). Pentru a

aduga noduri la coada de ateptare, sunt examinai vecinii (succesorii) nodului curent.
Vecinii (succesorii) unui nod sunt examinai o singur dat, atunci cnd nodul este
IC

eliminat din coada de ateptare. Numrul total de vecini examinai este egal cu m
numrul de muchii (arce) ale grafului. Complexitatea operaiilor de adugare de noduri
este O(m). Complexitatea algoritmului este liniar O(m+n).
CT

Determinarea drumurilor de lungime minim, ntre oricare dou noduri din


graf, cu ajutorul algoritmului de parcurgere n lime
DA

Algoritmul. Pentru a gsi drumurile de lungime minim care pornesc din fiecare nod, se
va parcurge graful n lime de n ori (parcurgerea se va face pornind din fiecare dintre cele
n noduri ale grafului). Pentru a putea reconstitui drumul, se folosete un vector (p) pentru
a memora predecesorul unui nod n parcurgerea n lime:
DI

Implementarea algoritmului. Se citete, din fiierul graf21.txt, matricea de adiacen a a


grafului neorientat G26. Se afieaz drumurile de lungime minim dintre noduri. Se folo-
sete variabila global x, pentru nodul din care pormete drumul, i implicit, parcurgerea n
lime a grafului. Funcia zero() se folosete pentru a iniiaiza cu valoarea 0 vectorii
RA

vizitat i p nainte de a ncepe o nou parcurgere a grafului, pornind din nodul x.


Funcia adaug() a fost modificat prin adugarea instruciunii de actualizare a vectorului p
la adugarea unui nod n coada de ateptare (n elementul corespunztor nodului vizitat i
se memoreaz predecesorul su n parcurgerea n lime nodul k). Funcia afiseaza()
TU

se folosete pentru a afia drumurile de lungime minim de la nodul x pn la fiecare dintre


celelalte noduri ale grafului. n aceast funcie se folosesc urmtoarele variabile locale: i
pentru a parcurge coada de ateptare i vectorul d; j pentru a parcurge nodurile grafului
I

(aceste noduri sunt nodurile destinaie ale drumurilor care pornesc din nodul x); d un
ED

vector n care se memoreaz nodurile drumului (nodurile sunt nregistrate n ordine invers:
240 Implementarea structurilor de date

C
de la predecesorul nodului j pn la nodul x); y pentru predecesorul unui nod i este
o variabil de tip logic, pentru a verifica dac exist drum de la nodul x la nodul j.
Vectorul p

I
nod 1 2 3 4 5 6 7 8 9

OG
p 0 1 1 1 2 3 4 6 6
#include <fstream.h>
typedef stiva[100];
int a[10][10],vizitat[10],c[10],p[10],n,prim,ultim,k,x;

AG
fstream f("graf21.txt",ios::in);
void citeste() {//se citete matricea de adiacen din fiier}
void zero(){for (int i=1;i<=n;i++) {vizitat[i]=0; p[i]=0;}}
void init(int k) {prim=ultim=1; c[ultim]=k; vizitat[k]=1; p[k]=0;}

ED
int este vida() {return ultim<prim;}
void adaug(int i, int k) {ultim++; c[ultim]=i; vizitat[i]=1; p[i]=k;}
void prelucrare()
{int i; k=c[prim];
for (i=1;i<=n;i++) if (a[k][i]==1 && vizitat[i]==0) adaug(i,k);

P
prim++;}
void afisare()
{int i,j,este,y,d[10];
I
cout<<"Drumul minim care porneste din nodul "<<x<<": "<<endl;
for (j=1;j<=n;j++)
if (j!=x)
{cout<<"pana la nodul "<<j<<": ";

for (i=1,este=0;i<=ultim && !este;i++) if (c[i]==j) este=1;


if (este==1) {y=p[j]; i=0;
IC

while (y) {i++; d[i]=y; y=p[y];}


for (;i>=1;i--) cout<<d[i]<<" "<<j<<" ";}
else cout<<"nu exista drum";
CT

cout<<endl;}
cout<<endl;}
void main()
{citeste();
DA

cout<<"Drumurile de lungime minima intre doua noduri sunt: "<<endl;


for (x=1;x<=n;x++) {zero(); init(x);
while (!este_vida()) prelucrare();
afisare();}}
DI

2.7.8.2. Parcurgerea n adncime Depth First


Pentru aceast metod de parcurgere a unui graf cu n noduri se folosesc urmtoarele
RA

structuri de date i date elementare:


1. Variabilele de memorie. n pentru numrul de noduri ale grafului, k pentru nodul
care se prelucreaz, i i j pentru parcurgerea matricei de adiacen i a vectorilor.
2. Matricea de adiacen a grafului a.
TU

3. Vectorul de vizitare vizitat. El conine n elemente n care se nregistreaz


nodurile vizitate. Elementele vectorului vizitat[i] sunt definite ca i n metoda
precedent de parcurgere.
4. Stiva st a nodurilor parcurse. Stiva st gestioneaz nodurile vecine parcurse n
I

adncime. Pentru gestionarea stivei se folosete variabila de memorie vf pentru a


ED

identifica ultimul nod intrat n stiv. Pentru stiv se folosete implementarea static cu
Informatic 241

C
un vector st cu n elemente. n stiv vor fi nregistrate, n ordine, nodurile vizitate n
adncime, pe o direcie. Iniial, stiva conine un singur element care corespunde
nodului cu care ncepe parcurgerea grafului, iar valoarea variabilei vf este 1. Pe

I
msur ce se parcurge graful, se completeaz urmtoarele elemente ale vectorului

OG
st. Atunci cnd se prelucreaz un nod k, pe la vrful stivei se introduc n stiv toate
nodurile i vecine cu nodul k care nu au fost vizitate nc.
Algoritmul pentru parcurgerea grafului este urmtorul:
PAS1. Se citesc din fiier valoarea pentru n i matricea de adiacen a grafului.

AG
PAS2. Se iniializeaz cu 0 elementele vectorului de vizitare vizitat, deoarece nici
unul dintre noduri nu a fost vizitat.
PAS3. Se introduce de la tastatur valoarea variabilei de memorie k, corespunztoare
primului nod cu care ncepe parcurgerea grafului, i se afieaz eticheta lui.

ED
PAS4. Se iniializeaz stiva st (vrful i coninutul vrfului stivei), astfel: vf1;
st[vf]k; deoarece iniial n stiva st este nregistrat doar nodul k cu care
ncepe parcurgerea.
PAS5. Se actualizeaz vectorul vizitat atribuind elementului k al vectorului valoarea

P
1, deoarece a fost vizitat (vizitat[k]1).
PAS6. Ct timp stiva nu este vid (vf<>0) execut
PAS7. Se extrage din vrful stivei, elementul corespunztor nodului cruia i se
I
vor vizita vecinii (kst[vf];).
PAS8. Se inializeaz nodul i cu care ncepe cutarea (i1;).
PAS9. Ct timp nu s-a gsit un nod i vecin nodului k, nevizitat nc (i<=n i

(a[i][k]=0 sau (a[i][k]=1 i vizitat[i]=1))) execut


PAS10. Se trece la urmtorul nod, n vederea verificrii (ii+1;), i se
IC

revine la Pasul 9.
PAS11. Dac nu s-a mai gsit un nod i vecin nodului k nevizitat nc, atunci se
elimin nodul k din stiv, prin coborrea vrfului stivei (vfvf-1), altfel se
CT

afieaz nodul gsit i, se adaug n vrful stivei (vfvf+1; st[vf]i;)


i se actualizeaz elementul din vectorul de vizitare care corespunde acestui
nod, deoarece prin adugarea nodului i la stiva st se consider c acest
nod a fost vizitat (vizitat[i]1;) i se revine la Pasul 6.
DA

Pentru graful G26, pornind din nodul 1, nodurile n stiv sunt adugate astfel:
vizitat 1 0 0 0 0 0 0 0 0
1 2 3 4 5 6 7 8 9 10
st 1
DI

Iniializarea stivei cu primul nod: vf=1.


vizitat 1 1 0 0 0 0 0 0 0
1 2 3 4 5 6 7 8 9 10
RA

st 1 2
Prelucrarea nodului: vf=1 vf=2.
vizitat 1 1 0 0 1 0 0 0 0
1 2 3 4 5 6 7 8 9 10
TU

st 1 2 5
Prelucrarea nodului: vf=2 vf=3.
vizitat 1 1 1 0 1 0 0 0 0
1 2 3 4 5 6 7 8 9 10
I

st 1 2 5 3
ED

Prelucrarea nodului: vf=3 vf=4.


242 Implementarea structurilor de date

C
vizitat 1 1 1 0 1 1 0 0 0
1 2 3 4 5 6 7 8 9 10
st 1 2 5 3 6
Prelucrarea nodului: vf=4 vf=5.

I
OG
vizitat 1 1 1 0 1 1 0 1 0
1 2 3 4 5 6 7 8 9 10
st 1 2 5 3 6 8
Prelucrarea nodului: vf=5 vf=6.

AG
vizitat 1 1 1 0 1 1 0 1 0
1 2 3 4 5 6 7 8 9 10
st 1 2 5 3 6 8
Prelucrarea nodului: vf=6 vf=5.

ED
vizitat 1 1 1 0 1 1 0 1 1
1 2 3 4 5 6 7 8 9 10
st 1 2 5 3 6 9
Prelucrarea nodului: vf=5 vf=6.

P
vizitat 1 1 1 0 1 1 0 1 1
1 2 3 4 5 6 7 8 9 10
st 1 2 5 3 6 9
I
Prelucrarea nodului: vf=6 vf=5.
vizitat 1 1 1 0 1 1 0 1 1
1 2 3 4 5 6 7 8 9 10

st 1 2 5 3 6
Prelucrarea nodului: vf=5 vf=4.
IC

vizitat 1 1 1 0 1 1 1 1 1
1 2 3 4 5 6 7 8 9 10
st 1 2 5 3 7
CT

Prelucrarea nodului: vf=4 vf=5.


vizitat 1 1 1 1 1 1 1 1 1
1 2 3 4 5 6 7 8 9 10
st 1 2 5 3 7 4
DA

Prelucrarea nodului: vf=5 vf=6.


vizitat 1 1 1 1 1 1 1 1 1
1 2 3 4 5 6 7 8 9 10
DI

st 1 2 5 3 7 4
Prelucrarea nodului: vf=6 vf=5.
vizitat 1 1 1 1 1 1 1 1 1
1 2 3 4 5 6 7 8 9 10
RA

st 1 2 5 3 7
Prelucrarea nodului: vf=5 vf=4.
vizitat 1 1 1 1 1 1 1 1 1
1 2 3 4 5 6 7 8 9 10
TU

st 1 2 5 3
Prelucrarea nodului: vf=4 vf=3.
vizitat 1 1 1 1 1 1 1 1 1
I

1 2 3 4 5 6 7 8 9 10
ED

st 1 2 5
Prelucrarea nodului: vf=3 vf=2.
Informatic 243

C
vizitat 1 1 1 1 1 1 1 1 1
1 2 3 4 5 6 7 8 9 10
st 1 2
Prelucrarea nodului: vf=2 vf=1.

I
OG
vizitat 1 1 1 1 1 1 1 1 1
1 2 3 4 5 6 7 8 9 10
st 1
Prelucrarea nodului: vf=1 vf=0. Terminare: vf=0

AG
Pentru implementarea algoritmului se folosesc subprogramele:
funcia procedural citeste creeaz matricea de adiacen prin preluarea informa-
iilor din fiierul text f ;
funcia procedural init iniializeaz stiva cu primul nod vizitat;

ED
funcia operand este_vida testeaz stiva dac este vid;
funcia procedural adauga adaug un nod la stiv;
funcia procedural elimina elimin nodul din vrful stivei;
funcia procedural prelucrare prelucreaz nodul din vrful stivei: caut primul

P
vecin nevizitat i dac gsete un astfel de nod, l afieaz i l adaug n stiv;
altfel, nodul din vrful stivei este eliminat (nu mai are vecini nevizitai);
Pentru testarea programului se folosete graful neorientat G26 a crui matrice de adia-
I
cen se citete din fiierul text graf21.txt.
Observaie. Pentru grafurile orientate, n funcia prelucrare() condiia structurii repetitive
while este: i<=n && ((a[k][i]==0 || a[i][k]==0) || ((a[k][i]==1 ||

a[i][k]==1) && vizitat[i]==1))


int n,a[10][10],vizitat[20],st[20],vf,k;
IC

fstream f("graf21.txt",ios::in);
void citeste() {//se citete matricea de adiacen din fiier}
void init (int k) {vf=1; st[vf]=k; vizitat[k]=1;}
CT

int este vida() {return vf==0;}


void adauga(int i) {vf++; st[vf]=i; vizitat[i]=1;}
void elimina() {vf--;}
DA

void prelucrare()
{int i=1; k=st[vf];
while (i<=n && (a[k][i]==0 || (a[k][i]==1 && vizitat[i]==1))) i++;
if (i==n+1) elimina(); else {cout<<i<<" "; adauga(i);}}
DI

void main()
{citeste(); cout<<"nodul de pornire: "; cin>>k;
cout<<"Nodurile vizitate prin metoda DF sunt: "<<endl;
cout<<k<<" "; init(k);
RA

while (!este vida()) prelucrare();}


Prin parcurgerea n adncime a unui graf determinai nodurile
Atenie care aparin aceleiai componente conexe, respectiv subrafului
de succesori ai unui nod.
TU

Complexitatea algoritmului de parcurgere n adncime


Algoritmul const n extragerea unui nod din stiv i adugarea vecinilor (succesorilor) si
I

n stiv, iar dac nu mai are vecini, nodul este eliminat din stiv. Fiecare nod va fi adugat
ED

n stiv o dat i, prin urmare, va fi eliminat din stiv o singur dat. Complexitatea
244 Implementarea structurilor de date

C
operaiilor de eliminare a celor n noduri din stiv este O(n). Pentru a aduga noduri n stiv
sunt examinai vecinii (succesorii) nodului din vrful stivei. Vecinii (succesorii) unui nod sunt
examinai o singur dat, atunci cnd nodul este extras din stiv. Numrul total de vecini

I
examinai este egal cu m numrul de muchii (arce) ale grafului. Complexitatea operaiilor

OG
de adugare de noduri este O(m). Complexitatea algoritmului este liniar O(m+n).

Determinarea conexitii grafurilor cu ajutorul algoritmului de parcurgere n


adncime

AG
1. Afiarea componentelor conexe dintr-un graf.
Algoritmul. Identificarea mulimii de noduri care formeaz o component conex se face
parcurgnd n adncime graful pornind de la un nod iniial. Nodul cu care ncepe parcurgerea
n adncime pentru o component conex se caut printre nodurile nevizitate nc. Graful se

ED
va parcurge n adncime pn cnd vor fi vizitate toate nodurile. Dac graful este conex, se
va afia o singur component conex care va fi format din toate nodurile grafului.
Implementarea algoritmului. Se citete din fiierul graf21.txt matricea de adiacen a a
grafului neorientat G26 i se afieaz toate componentele conexe ale grafului. Pe lng

P
variabilele i structurile de date folosite de algoritmul de parcurgere n adncime se mai
folosete variabila global m, pentru a numra componentele conexe. Pentru a gsi nodul cu
care se iniializeaz parcurgerea se folosete funcia cauta() care caut primul nod
I
nevizitat, n ordinea etichetelor nodurilor.
int n,a[10][10],vizitat[20],st[20],vf,k,m;
fstream f("graf21.txt",ios::in);

void citeste() {//se citete matricea de adiacen din fiier}


int cauta()
IC

{for (int i=1; i<=n; i++) if (vizitat[i]==0) return i;


return 0;}
void init(int k) {vf=1; st[vf]=k; vizitat[k]=1;}
CT

int este vida() {return vf==0;}


void adaug(int i) {vf++; st[vf]=i; vizitat[i]=1;}
void elimin() {vf--;}
DA

void prelucrare()
{int i=1; k=st[vf];
while (i<=n && (a[k][i]==0 || (a[i][k]==1 && vizitat[i]==1))) i++;
if (i==n+1) elimin(); else {cout<<i<<" "; adaug(i);}}
DI

void main()
{citeste(); k=cauta();
while (k)
{m++; init(k); cout<<endl<<"Componenta conexa "<<m<<": "<<k<<" ";
RA

while (!este vida()) prelucrare();


k=cauta();}}
2. Afiarea componentelor tare conexe dintr-un graf orientat.
TU

Algoritmul. Nodul cu care ncepe parcurgerea n adncime pentru o component tare


conex se caut printre nodurile nevizitate nc. Pentru acest nod se determin mulimea
nodurilor care formeaz subgraful succesorilor i mulimea nodurilor care formeaz
subgraful predecesorilor. Prin intersecia celor dou subgrafuri (mulimi de noduri) se obine
I

componenta tare conex. Identificarea celor dou mulimi de noduri se face parcurgnd n
ED

adncime graful pentru fiecare mulime, pornind de la un nod iniial. Un nod se consider
Informatic 245

C
vizitat numai dac a fost adugat la o component tare conex. Prelucrarea componen-
telor tare conexe prin parcurgerea n adncime a grafului se va face pn cnd vor fi
vizitate toate nodurile. Dac graful este tare conex, se va afia o singur component

I
tare conex care va fi format din toate nodurile grafului.

OG
Implementarea algoritmului. Se citete din fiierul graf20.txt matricea de adiacen a a
grafului orientat G22 i se afieaz toate componentele tare conexe ale grafului. Vectorii
pred i succ se folosesc pentru a determina subgraful predecesorilor, respectiv
subgraful succesorilor nodului care se prelucreaz. Vectorii au n elemente. Fiecare

AG
element i are valoarea 1 dac nodul i aparine subgrafului predecesorilor, respectiv
subgrafului succesorilor; altfel, are valoarea 0. Funcia zero() se folosete pentru a
iniializa cu valoarea 0 vectorii pred i succ nainte de prelucrarea unei componente tare
conexe. Pentru a gsi nodul cu care se iniializeaz o component tare conex, se

ED
folosete funcia cauta() care caut primul nod nevizitat, n ordinea etichetelor nodu-
rilor. Funciile prelucrare1() i prelucrare2()se folosesc pentru a parcurge graful
n adncime n vederea determinrii subgrafului predecesorilor, respectiv subgrafului
succesorilor nodului care se prelucreaz. Funcia comp() se folosete pentru a deter-

P
mina nodurile unei componente tare conexe prin intersecia vectorilor pred i succ.
int n,a[10][10],vizitat[20],st[20],vf, m;
fstream f("graf20.txt",ios::in);
I
void citeste(){//se citete matricea de adiacen din fiier}
int cauta() {//este identic cu cea de la exemplul anterior}
void zero(int x[]) {for(int i=1;i<=n;i++) x[i]=0;}

void init(int k) {vf=1; st[vf]=k;}


int este vida() {return vf==0;}
IC

void adaug(int i,int x[]) {vf++; st[vf]=i; x[i]=1;}


void elimin() {vf--;}
void prelucrare1(int x[])
CT

{int i=1,k=st[vf]; x[k]=1;


while (i<=n && (a[i][k]==0 || (a[i][k]==1 && x[i]==1))) i++;
if (i==n+1) elimin(); else adaug(i,x);}
void prelucrare2(int x[])
DA

{int i=1,k=st[vf]; x[k]=1;


while (i<=n && (a[k][i]==0 || (a[k][i]==1 && x[i]==1))) i++;
if (i==n+1) elimin(); else adaug(i,x);}
void comp(int x[], int y[])
DI

{for(int i=1;i<=n;i++)
if(x[i]==1 && y[i]==1) {cout<<i<<" "; vizitat[i]=1;}}
void main()
{int k,pred[10],succ[10];
RA

citeste(); k=cauta(); m++; cout<<"componentele tare conexe: "<<endl;


while (k)
{cout<<endl<<m<<": "; init(k); zero(pred);
while (!este vida()) prelucrare1(pred);
TU

init(k); zero(succ);
while (!este vida()) prelucrare2(succ);
comp(pred,succ); k=cauta(); m++;}}
I
ED
246 Implementarea structurilor de date

C
1. Scriei un program care citete din fiierul text graf4.txt lista arcelor
unui graf orientat i care, folosind algoritmul corespunztor de par-
Tem curgere a unui graf orientat, realizeaz:

I
a. Afieaz lanurile de lungime minim dintre noduri.

OG
b. Verific dac dou noduri x i y aparin aceleiai componente conexe (i varianta, apar-
in aceleiai componente tare conexe). Etichetele nodurilor se citesc de la tastatur.
c. Verific dac graful este tare conex i afieaz un mesaj de informare.
2. n nodurile unui graf se pstreaz numere naturale. Graful pune n eviden divizorii unui

AG
numr, astfel: numrul x memorat n nodul i este n relaie cu numrul y memorat n nodul
j, dac numrul y este divizor al numrului x. S se verifice dac n graf se gsesc toi
divizorii unui numr p citit de la tastatur. (Indicaie. Se parcurge mai nti graful, pornind
de la nodul cu eticheta 1 pentru a gsi numrul i, n cazul n care se gsete, se reia

ED
parcurgerea grafului pornind cu nodul n care s-a gsit numrul i se verific dac au
fost gsii toi divizorii. Pentru testarea programului se va crea un graf al divizorilor care
conine urmtoarele numere: {2,3,4,5,6,9,12,15,18,20,38} i se vor cuta divizorii
numrului 36 i apoi ai numrului 20.

2.7.8.3. Aplicaii practice


P
1. Din grupul de n persoane ntre care s-au stabilit relaii de prietenie, afiai cel mai
I
mare grup de prieteni. (Indicaie. Se determin componenta conex care conine cele
mai multe noduri).
2. Din grupul de n persoane ntre care s-au stabilit relaii de cunotin, afiai grupul

format din cele mai multe persoane care se cunosc reciproc. (Indicaie. Se determin
componenta tare conex care conine cele mai multe noduri.)
IC

3. Din grafurile care pun n eviden relaiile de vecintate i de prietenie ale stenilor care
au fnee, obinei urmtoarele informaii:
a. Care sunt stenii cei mai ndeprtai de drumul stesc. (Indicaie. Gsii cel mai lung
CT

lan din lanurile de lungime minim din graful fneelor.)


b. Care sunt stenii izolai. (Indicaie. Stenii care nu se gsesc n graful de vecinta-
te ntr-o component conex n care se afl i un stean cu ieire la drumul stesc.)
4. Din grafurile care pun n eviden osele din zona turistic, stabilii cte localiti rmn
DA

izolate dac se distruge un pod pe care trece oseaua care leag dou localiti ale
cror etichete se citesc de la tastatur.
5. n reeaua de strzi a oraului, stabilii cel mai scurt drum ntre dou intersecii ale cror
etichete se citesc de la tastatur.
DI

2.7.9. Graful ponderat


2.7.9.1. Definiia grafului ponderat
RA

Considerm un graf G=(X,U) i o funcie f:UR+ care asociaz fiecrei muchii (arc) u un
numr real pozitiv (care poate avea semnificaia de cost, distan, timp, durat), numit n
general costul muchiei. Funca f se numete funcia cost.
TU

Un graf G = (X,U) pentru care s-a definit o funcie cost se numete graf ponderat.
Observaii:
1. Graful ponderat se mai numete i graf cu costuri.
I

2. Grafurile ponderate se folosesc n aplicaii n care trebuie determinat valoarea


ED

minim sau valoarea maxim a unei mrimi asociate grafului, adic a funciei cost.
Informatic 247

C
3. Se definete costul unui drum de la nodul x la nodul y ca fiind suma costurilor
muchiilor (arcelor) care formeaz acel drum.
4. Metoda cea mai adecvat pentru reprezentarea unui graf ponderat

I
este matricea costurilor.

OG
Exemplu Graful G27 din figura 32. G
G
G222777

Fig. 32

AG
Scop: exemplificarea unei aplicaii n care pentru reprezentarea datelor se folosete un
graf ponderat.
Exemplul 1. O firm deine depozite de marf n mai multe localiti. O reea de osele
leag direct unele dintre aceste localiti. Distana dintre dou locaiti este msurat n

ED
kilometri. S se determine traseul pe care trebuie s-l parcurg o main pentru a
transporta marf de la depozitul din oraul A la depozitul din oraul B astfel nct distana
parcurs n kilometri s fie minim.
Localitile fomeaz nodurile unui graf neorientat n care fiecare muchie reprezint o legtur

P
direct pe osea ntre dou localiti. Fiecare muchie are asociat o mrime distana.
Aceast mrime este costul muchiei, iar graful este un graf ponderat. Cerina problemei este
I
de a determina un drum cu lungime minim (cu costul minim) ntre dou noduri ale grafului.
Exemplul 2. O persoan trebuie s se deplaseze cu autoturismul ct mai repede ntre dou
intersecii din ora. Traficul ntre dou intersecii nu este ntotdeauna n ambele sensuri. Cu-
noscnd timpul mediu de deplasare ntre dou intersecii, s se determine care este traseul

pe care trebuie s-l aleag pentru a ajunge de la intersecia A la intersecia B ct mai repede.
IC

Interseciile fomeaz nodurile unui graf orientat n care fiecare arc reprezint sensul de
circulaie pe o strad care leag direct dou intersecii. Fiecare arc are asociat o mrime
timpul mediu de parcurgere. Aceast mrime este costul muchiei, iar graful este un graf
CT

ponderat. Cerina problemei este de a determina un drum cu timpul de parcurgere minim


(cu costul minim) ntre dou noduri ale grafului.
Observae. Orice problem la care soluia este de a gsi drumul cu costul minim (sau
maxim) dintre dou puncte se rezolv reprezentnd datele printr-un graf ponderat
DA

i folosind un algoritm de determinare a drumului cu costul minim (respectiv


maxim) dintre dou noduri ale grafului.

2.7.9.2. Matricea costurilor


DI

Matricea costurilor unui graf este o matrice ptratic de dimensiune n (An,n),


ale crei elemente ai,j sunt definite astfel nct s pun n eviden
costul asociat fiecrei muchii (arc).
RA

n funcie de cerina aplicaiei, exist dou forme de reprezentare a matricei costurilor:


matricea costurilor minime pentru a determina valoarea minim a funciei cost;
matricea costurilor maxime pentru a determina valoarea maxim a funciei cost.
TU

a) Matricea costurilor minime. Elementele ai,j ale matricei sunt definite astfel:
c, dac exist o muchie (un arc) cu costul c 0 ntre nodurile i i j, cu i j

ai, j 0, dac i j
I

, dac nu exist o muchie (un arc) ntre nodurile i i j, cu i j


ED


248 Implementarea structurilor de date

C
Fiecrei muchii (arc) care nu exist n graf i se asociaz o valoare foarte mare, deoarece,
cutndu-se costul minim, aceast muchie (arc) nu va mai
fi selectat. Deoarece pentru implementarea matricei nu 1 2 3 4 5

I
1 0 4 3
se poate folosi simbolul , n locul lui se va folosi cea mai

OG
mare valoare ce se poate reprezenta n calculator pentru 2 0 7 8
tipul de dat asociat costului. 3 0
Exemplu. Pentru graful ponderat G27 din figura 32 matri- 4 4 0
cea costurilor minime este prezentat alturat. 5 2 2 0

AG
b) Matricea costurilor maxime. Elementele ai,j ale matricei sunt definite astfel:
c, dac exist o muchie (un arc) cu costul c 0 ntre nodurile i i j, cu i j

ED
ai, j 0, dac i j
, dac nu exist o muchie (un arc) ntre nodurile i i j, cu i j

Fiecrei muchii (arc) care nu exist n graf i se asociaz o valoare foarte mic, deoarece,
cutndu-se costul maxim, aceast muchie (arc) nu va mai fi selectat. Deoarece pentru

P
implementarea matricei nu se poate folosi simbolul -, n locul lui se va folosi cea mai
mic valoare ce se poate reprezenta n calculator pentru tipul de dat asociat costului.
I
Tem Scriei matricea costurilor maxime pentru graful din figura 32.

Algoritmul pentru crearea matricei costurilor


IC

Pentru a crea matricea costurilor trebuie s se citeasc pentru fiecare muchie (arc)
nodurile de la extremiti i costul asociat fiecrei muchii (arc). Aceste informaii se pot citi
de la tastatur sau dintr-un fiier. Algoritmul pentru crearea matricei costurilor este:
CT

PAS1. Se iniializeaz matricea astfel: toate elementele de pe diagonala principal cu


valoarea 0, iar restul elementelor cu valoarea corespunztoare pentru (-).
PAS2. Se actualizeaz matricea cu informaiile despre costurile asociate muchiilor (ar-
celor) astfel: pentru fiecare muchie (arc) [i,j] cu costul c, elementului a[i][j] i se va
DA

atribui valoarea costului c.


Implementarea algoritmului pentru matricea costurilor minime a unui graf orientat. Pentru
iniializarea matricei costurilor se folosete funcia init(), iar pentru actualizarea ei funcia
citire(). Elementele matricei fiind de tip int nu se poate folosi pentru simbolul
DI

constanta de sistem MAXINT, deoarece n algoritmii de determinare a drumului cu costul


minim prin adunrile repetate ale elementelor matricei (care pot avea i valoarea MAXINT)
se depete capacitatea de reprezentare a tipului int. Exist dou soluii:
RA

a. pentru elementele matricei se alege tipul long, chiar dac acest tip de dat nu este
justificat de valorile foarte mici ale costurilor (i se obine o utilizare ineficient a
memoriei interne);
b. se definete o constant cu o valoare foarte mare n comparaie cu celelalte costuri.
TU

n implementarea agoritmului s-a ales varianta unei constante definite MAX. Datele se
citesc din fiierul text cost.txt n care pe prima linie exist un numr care reprezint
numrul de noduri ale grafului, iar pe urmtoarele rnduri cte trei valori numerice
separate prin spaiu, care reprezint nodurile de la extremitatea unui arc i i j i
I
ED

costul asociat arcului c. Pentru testarea programului se folosete graful G27.


Informatic 249

C
#include <fstream.h>
int a[100][100],n;
int const MAX=5000;

I
fstream f("cost.txt",ios::in);

OG
void init() //se initializeaza matricea costurilor
{int i,j; f>>n;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) if (i==j) a[i][j]=0;
else a[i][j]=MAX;}

AG
void citire() //se actualizeaza matricea costurilor cu datele din fiier
{int i,j,c;
while (f>>i>>j>>c) a[i][j]=c; f.close();}
void main() {... }

ED
Scriei un program care creeaz matricea costurilor maxime pentru graf
Tem neorientat. Pentru testare considerai n graful din figura 32 c arcele
sunt muchii.

P
2.7.9.3. Algoritmi pentru determinarea costului minim (maxim)
Pentru determinarea drumului cu costul minim (maxim) ntre dou noduri ale unui graf se
I
poate folosi:
algoritmul Roy-Floyd;
algoritmul Dijkstra.
Drumul optim

Ambii algoritmi folosesc principiul enunat prin teorema lui Bellman: dru- c2+c3 c1
mul optim (cu costul minim, respectiv maxim) ntre dou noduri oarecare
IC

i i j conine numai drumuri pariale optime (cu costuri minime,


respectiv maxime) care trec prin alte noduri ale grafului. Altfel spus, dac
drumul optim dintre dou noduri oarecare i i j trece printr-un nod k,
CT

atunci i drumurile de la i la k i de la k la j sunt optime. Cei doi algoritmi


Fig. 33
difer prin modul n care se identific nodurile intermediare k.

a) Algoritmul Roy-Floyd
DA

Algoritmul folosete un principiu asemntor cu cel care a fost utilizat pentru determina-
rea matricei drumurilor: gsirea drumului optim ntre dou noduri oarecare i i j prin
descoperirea drumurilor optime care l compun i care trec prin nodurile k se face prin
transformarea matricei costurilor. Matricea trece prin n transformri, n urma crora
DI

fiecare element a[i][j] va memora costul drumului minim dintre nodurile i i j.


PAS1. Pentru etichete ale nodului k de la 1 la n (adic pentru orice nod al grafului)
execut:
RA

PAS2. Pentru orice pereche de noduri din graf i i j (cu 1in i 1jn) execut:
PAS3. Dac suma dintre costul drumului de la i la k i costul drumului de la k
la j (a[i][k]+a[k][j]) este mai mic dect costul drumului de la i
la j (a[i][j]), atunci n matricea costurilor costul drumului direct de
TU

la i la j este nlocuit cu costul drumului care trece prin nodul k


(a[i][j]= a[i][k]+a[k][j]).
Pentru graful din figura 32 matricea costurilor sufer urmtoarele cinci transformri. La
fiecare transformare, dac drumul de la nodul i la nodul j are costul mai mare dect
I
ED

costul drumurilor care trec prin nodul intermediar k (de la nodul i la nodul k i de la nodul
k la nodul j), atunci elementului a[i][j] i se va atribui valoarea a[i][k]+a[k][j].
250 Implementarea structurilor de date

C
k=1 k=2 k=3
1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
1 0 4 3 1 0 4 3 11 12 1 0 4 3 11 12

I
2 0 7 8 2 0 7 8 2 0 7 8

OG
3 5 0 3 5 0 12 13 3 5 0 12 13
4 4 0 4 4 0 4 9 4 0 17
5 2 6 5 2 0 5 2 6 5 2 0 5 2 6 5 2 0
k=4 k=5
1 2 3 4 5 1 2 3 4 5

AG
1 0 4 3 11 12 1 0 4 3 11 12
2 0 11 7 8 2 10 0 11 7 8
3 5 0 12 13 3 15 5 0 12 13
4 9 4 0 17 4 19 9 4 0 17

ED
5 2 6 5 2 0 5 2 6 5 2 0
Interpretarea datelor din matricea obinut n urma transformrilor se face astfel: drumul
de la nodul i la nodul j are costul minim a[i][j]. De exemplu, drumul cu costul minim
de la nodul 2 la nodul la nodul 4 are costul minim 7. Matricea nu furnizeaz informaii

P
despre etichetele drumului cu costul minim.
Pentru implementarea algoritmului se folosesc subprogramele:
I
funcia procedural init iniializeaz matricea costurilor;
funcia procedural citire actualizeaz matricea costurilor cu datele din fiier;
funcia procedural transformare transform matricea costurilor;
funcia procedural afiare afieaz lungimea drumurilor minime ntre toate nodurile

grafului.
IC

#include <fstream.h>
int a[100][100],n;
int const MAX=5000;
CT

fstream f("cost.txt",ios::in);
void init() {//se initializeaza matricea costurilor}
void citire() {//se actualizeaza matricea costurilor cu datele din fiier}
void transformare() //se transform matricea costurilor
{for(int k=1;k<=n;k++)
DA

for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(a[i][k]+a[k][j]<a[i][j]) a[i][j]=a[i][k]+a[k][j];}
void afisare()
DI

{cout<<"costul drumurilor minime intre nodurile: "<<endl;


for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(a[i][j]<MAX && i!=j) cout<<"("<<i<<","<<j<<")-"<<a[i][j]<<endl;}
RA

void main()
{init(); citire(); transformare(); afisare();}
Informaiile din matricea costurilor transformat prin algoritmul Roy Floyd se pot
folosi pentru a verifica dac exist drum cu costul minim ntre dou noduri ale gra-
TU

fului, iar n caz afirmativ, se poate afia lungimea lui i se poate descoperi drumul.
Algoritmul de descoperire a drumului cu costul minim pornind de la matricea costurilor
transformat folosete acelai raionament ca la transformarea ei: dac lungimea drumului
I

minim dintre nodurile i i j este egal cu suma dintre lungimile minime a dou drumuri care
ED

trec printr-un nod intermediar k (a[i][k]+a[k][j]=a[i][j]), atunci nodul k face parte


Informatic 251

C
din drumul de lungime minim de la i la j. Deoarece problema pentru determinarea nodurilor
care formeaz drumul de lungime minim se descompune n dou subprobleme: determina-
rea drumului minim de la nodul i la nodul k (cu ki) i determinarea drumului minim de la no-

I
dul k la nodul j (cu kj), n implementarea algoritmului se folosete strategia divide et impera.

OG
Pentru implementarea algoritmului prin care se determin drumul minim dintre dou
noduri x i y (a cror etichet se citete de la tastatur) se folosesc subprogramele:
funcia procedural init iniializeaz matricea costurilor;
funcia procedural citire actualizeaz matricea costurilor cu datele din fiier;

AG
funcia procedural transformare transform matricea costurilor;
funcia procedural drum determin nodurile drumului cu cost minim;
funcia procedural afiare afieaz costul drumului minim i nodurile care formeaz
drumul;

ED
#include <fstream.h>
int a[100][100],n;
int const MAX=5000;
fstream f("cost.txt",ios::in);

P
void init() {//se initializeaza matricea costurilor}
void citire() {//se actualizeaza matricea costurilor cu datele din fiier}
void transformare() {//se transforma matricea costurilor }
I
void drum(int i, int j) //se determin nodurile drumului minim
{int k,gasit;
for (k=1,gasit=0; k<=n && !gasit; k++)
if (i!=k && j!=k) && a[i][j]==a[i][k]+a[k][j])

{drum(i,k); drum(k,j); gasit=1;}


if (!gasit) cout<<j<<" ";}
IC

void afisare(int x, int y)


{if (a[x][y]<MAX)
{cout<<"drumul minim de la nodul "<<x<<" la nodul "<<y;
CT

cout<<" are costul "<<a[x][y]<<endl;


cout<<x<<" "; drum(x,y);}
else cout<<"Nu exista drum";}
void main()
{int x,y; cout<<"x= "; cin>>x; cout<<"y= "; cin>>y;
DA

init(); citire(); transformare(); afisare(x,y); }


Complexitatea algoritmului Roy-Floyd
3
Algoritmul de transformare a matricei costurilor are ordinul de complexitate O(nnn)= O(n )
DI

deoarece fiecare structur repetitiv for se execut de n ori, iar structurile for sunt imbricate.
Algoritmul de determinare a drumurilor cu costul minim din matricea costurilor transformat
are ordinul de complexitate al algoritmului divide et impera: O(nlg2n). Ordinul algoritmului
3 3 3
este O(n )+ O(nlg2n) = O(n + nlg2n) = O(n ).
RA

Modificai programele care implementeaz algoritmul Roy Floyd astfel


Tem nct s se determine drumurile cu costul maxim.
TU

b) Algoritmul Dijkstra
Algoritmul lui Dijkstra construiete drumurile cu costul minim care pornesc de la un nod
oarecare x nodul surs pn la fiecare nod din graful G=(X,U) nodul destinaie.
I

Algoritmul ntreine o mulime cu nodurile care au fost deja selectate S, i o coad de


ED

prioriti Q cu nodurile care nu au fost selectate nc: Q=X-S, astfel:


252 Implementarea structurilor de date

C
Un nod y este declarat selectat atunci cnd s-a determinat costul final al drumului cu
costul minim de la nodul surs x la el. Selectarea unui nod nu este echivalent cu
gsirea drumului cu costul minim deoarece este posibil ca n urma calculrii costului s

I
rezulte c nu exist drum de la nodul x la acel nod.

OG
n coada Q prioritatea cea mai mare o are nodul pentru care costul drumului are
valoarea cea mai mic dintre toate costurile de drumuri care pornesc de la nodul x la
celelalte noduri neselectate nc. La fiecare extragere a unui nod din coada de prioriti
Q, nodul este adugat la mulimea S, iar coada de prioriti este reorganizat n funcie

AG
de acest nod (se recalculeaz costul drumurilor de la nodul x la nodurile rmase n
coad, considernd c unele drumuri, dac trec i prin nodul extras, pot s-i micoreze
costul). Pentru calcularea drumurilor de lungime minim se x = nod surs
ntreine o mulime D n care se memoreaz costul drumurilor de
la nodul x la nodurile neselectate, costuri care se recalculeaz la 3

ED
fiecare extragere de nod.
Drumul cu costul minim care pornete din nodul x este format din
nodul iniial x i crete pn cnd coada de prioriti Q nu mai conine

P
noduri. Deoarece, cele dou mulimi S i Q sunt disjuncte, iar
reuniunea lor este mulimea nodurilor X, este suficient s se ntrein zQ (nod neselectat)
numai mulimea S. Algoritmul folosete strategia greedy, deoarece (1) d3d1+d2 : x y
I
ntotdeauna alege nodul cel mai apropiat de nodul surs x. (2) d3>d1+d2 : x yz
PAS1. Se iniializeaz: S=, se citete nodul iniial x i se atribuie Fig. 34
mulimii S.

PAS2. Se iniializeaz mulimea D cu costurile drumurilor de la nodul x la toate celelalte


noduri ale grafului (sunt preluate din matricea costurilor elementele a[x][i]).
IC

PAS3. Ct timp coada de prioriti Q nu este vid (mai exist noduri neselectate) execut
PAS4. Se caut printre nodurile neselectate nodul y cu cel mai mic cost al drumului
(reprezint elementul care trebuie eliminat din coada de prioritii Q).
CT

PAS5. Se adaug nodul y la mulimea S: S=S{y} (nseamn extragerea nodului y


din coada de prioriti Q i declararea lui ca nod selectat).
PAS6. Pentru fiecare nod neselectat (nod din coada de prioriti) execut
PAS7. Se recalculeaz costul drumului de la nodul x la acest nod folosind ca
DA

nod intermediar nodul extras.


PAS8. Dac acest cost este mai mic dect cel din mulimea D, atunci el va fi
noul cost.
Implementarea algoritmului. Se folosesc trei vectori:
DI

Vectorul s pentru mulimea nodurilor selectate, definit astfel:


0, dac nodul i nu a fost selectat
s(i )
1, dac nodul i a fost selectat
RA

Iniial, elementele vectorului s au valoarea 0, cu excepia elementului s[x] care are valoa-
rea 1. La terminarea execuiei algoritmului, toate elementele din vectorul s vor avea valoarea
1. Nodurile i pentru care s[i]=0 se consider c fac parte din coada de prioriti Q.
Vectorul d conine costul drumurilor, astfel: d[i]= costul drumului minim gsit la un
TU

moment dat de la nodul x la nodul i (cu 1in). Iniial d[i]=a[x][i]. La terminarea


algoritmului, d[i]= costul minim al drumului de la nodul x la nodul i.
Vectorul t memoreaz drumurile gsite ntre nodul x i celelalte noduri i ale grafului.
Memorarea drumului se face prin legtura cu predecesorul care este definit astfel:
I
ED

p[i] memoreaz nodul j care este predecesorul nodului i pe drumul de la x, cu


Informatic 253

C
excepia nodului surs pentru care p[x]=0. Iniial, pentru toate nodurile i care nu au
costul infinit (pentru care exist un arc de la nodul x la nodul i), p[i]=x; altfel p[i]=0.
Nodul i care se extrage din coada de prioriti Q trebuie s ndeplineasc urmtoarele condiii:

I
s[i]=0.

OG
d[i]= min{d[j] | 1jn; s[j]=0}.
d[i] reprezint costul minim al drumului de la nodul x la nodul i.
Pentru reorganizarea cozii de prioriti se procedeaz astfel: pentru fiecare nod j cu
s[j]=0 se calculeaz costul drumului de la nodul x la nodul j care trece prin nodul i:

AG
d[i]+a[i][j]. Dac acest cost este mai mic dect d[j], atunci aceasta va fi noua
valoare a lui d[j] i se actualizeaz vectorul p: p[j]=i.
Pentru graful din figura 32, considernd x=1, algoritmul se excut astfel:

ED
Iniial:
Vectorii 1 2 3 4 5
s 1 0 0 0 0
d 0 4 3

P
p 0 1 1 0 0
Drumul cu costul cel mai mic este cu nodul 3: d[3]=3. Nodul 3 se va extrage din coada Q.
Se analizeaz nodurile care rmn n coada de prioriti:
I
Nodul 2. d[3]+a[3][2] = 3+5 = 8 4. Nu se modific nimic.
Nodul 4. d[3]+a[3][4] = 3+ = 4. Nu se modific nimic.
Nodul 5. d[3]+a[3][5] = 3+ = 4. Nu se modific nimic.

Vectorii 1 2 3 4 5
s 1 0 1 0 0
IC

d 0 4 3
p 0 1 1 0 0
Drumul cu costul cel mai mic este cu nodul 2: d[2]=4. Nodul 2 se va extrage din coada Q.
CT

Se analizeaz nodurile care rmn n coada de prioriti:


Nodul 4. d[2]+a[2][4] = 4+7 = 11 < . Se modific: d[4]=11 i p[4]=2.
Nodul 5. d[2]+a[2][5] = 4+8 = 12 < . Se modific: d[5]=12 i p[5]=2.
Vectorii 1 2 3 4 5
DA

s 1 1 1 0 0
d 0 4 3 11 12
p 0 1 1 2 2
Drumul cu costul cel mai mic este cu nodul 4: d[4]=11. Nodul 4 se va extrage din coada Q.
DI

Se analizeaz nodurile care rmn n coada de prioriti:


Nodul 5. d[4]+a[4][5] = 11+ = 12. Nu se modific nimic.
Vectorii 1 2 3 4 5
RA

s 1 1 1 1 0
d 0 4 3 11 12
p 0 1 1 2 2
Drumul cu costul cel mai mic este cu nodul 5: d[5]=15. Nodul 5 se va extrage din coada Q.
TU

Coada este vid i se termin execuia algoritmului.


Final:
Vectorii 1 2 3 4 5
s 1 1 1 1 1
I

d 0 4 3 11 12
ED

p 0 1 1 2 2
254 Implementarea structurilor de date

C
Din datele care se gsesc n vectorii d i p la terminarea algoritmului se obin urmtoa-
rele informaii:
d[i] reprezint costul minim al drumului de la nodul x la nodul i. De exemplu, pentru

I
nodul 4 costul minim este 11.

OG
Din vectorul predecesorilor se reconstituie drumul cu costul minim de la nodul x la nodul
i. De exemplu, pentru nodul 4: p[4]=2, iar p[2]=1. Drumul este 1 2 4.
Pentru implementarea algoritmului n care se determin drumul cu costul minim dintre
dou noduri x i y (a cror etichet se citete de la tastatur) se folosesc subprogramele:

AG
funcia procedural init iniializeaz matricea costurilor;
funcia procedural citire actualizeaz matricea costurilor cu datele din fiier;
funcia procedural generare_drum transform vectorii d i p conform algoritmului
pentru a obine drumurile cu costul minim de la nodul x la oricare alt nod i din graf;

ED
funcia procedural drum determin nodurile drumului cu cost minim de la nodul x
pn la un nod i din graf folosind informaiile din vectorull p;
funcia procedural afiare afieaz lungimea drumurilor minime care pornesc din
nodul x pn la fiecare nod i din graf i nodurile care formeaz drumul;

P
#include <fstream.h>
int a[100][100],d[100],s[100],p[100],n;
int const MAX=5000;
I
fstream f("cost.txt",ios::in);
void init() {//se initializeaza matricea costurilor}
void citire() {//se actualizeaza matricea costurilor cu datele din fiier}
void generare_drum(int x) //se genereaza drumurile

{int i,j,min,y; s[x]=1;


for(i=1;i<=n;i++)
IC

{d[i]=a[x][i];
if (i!=x && d[i]<MAX) p[i]=x;}
for(i=1;i<=n-1;i++)
CT

{for(j=1,min=MAX; j<=n; j++)


if (s[j]==0 && d[j]<min) {min=d[j]; y=j;}
s[y]=1;
for(j=1;j<=n;j++)
DA

if (s[j]==0 && d[j]>d[y]+a[y][j]) {d[j]=d[y]+a[y][j]; p[j]=y;}}}


void drum(int i)
{if (p[i]!=0) drum(p[i]); cout<<i<<" "; }
void afisare(int x)
{for(int i=1;i<=n;i++)
DI

if (i!=x)
if (p[i]!=0)
{cout<<"drumul cu costul minim de la nodul "<<x;
cout<<" la nodul "<<i<<" are costul "<<d[i]<<endl;
RA

drum(i); cout<<endl;}
else cout<<"Nu exista drum de la "<<x<<" la "<<i<<endl;}
void main()
{int x; cout<<"x= "; cin>>x;
TU

init(); citire(); generare drum(x); afisare(x);}


Complexitatea algoritmului lui Dijkstra
Pentru determinarea drumului cu costul minim se execut paii algoritmului. Pasul 2 are
I

ordinul de complexitate O(n). Pasul 3 se execut pentru fiecare nod din graf, mai puin
ED

nodul surs, deoarece fiecare nod trebuie selectat o dat (se execut de n-1 ori). Pentru
Informatic 255

C
fiecare nod selectat se analizeaz celelalte noduri, executndu-se: Pasul 4 de n ori (se
caut printre toate cele n noduri dac mai exist n coada de prioriti, iar printre cele care
mai sunt n coada de prioriti se caut nodul cu costul drumului cel mai mic), iar Pasul 6 de

I
n ori deoarece trebuie identificate printre cele n noduri care mai sunt n coada de prioriti.

OG
Ordinul de complexitate al algoritmului pentru determinarea drumului cu costul minim va fi:
2 2
O(n)+O(n(n+n)) = O(n)+O(n ) = O(n ). n algoritmul pentru afiarea drumului sunt anali-
zate toate cele n noduri ale grafului, iar pentru fiecare nod i se determin recursiv drumul.
2
Complexitatea algoritmului de afiare va fi O(n) O(nlg2n) = O(n lg2n).

AG
Modificai programul care implementeaz algoritmul Dijkstra astfel
Tem nct s se determine drumurile cu costul maxim.

2.7.9.4. Aplicaii practice

ED
1. O persoan oficial trebuie s se deplaseze ntr-un ora ntre dou puncte situate
fiecare ntr-o intersecie. Traficul ntre dou intersecii nu este ntotdeauna n ambele
sensuri, dar ntre oricare dou intersecii exist trafic prin intermediul altor intersecii. Pe

P
fiecare strad a traseului trebuie s existe un anumit numr de ageni care s asigure
securitatea persoanei oficiale. Scriei un program care s determine traseul astfel nct
numrul de ageni s fie minim. Datele se citesc dintr-un fiier, astfel: de pe primul rnd,
I
numrul de intersecii, iar de pe urmtoarele rnduri, triplete de numere x, y, z care
semnific faptul c pentru traficul de la intersecia x pn la intersecia y sunt necesari z
ageni (cele dou intersecii sunt legate direct).

2. O firm are mai multe puncte de lucru ntr-o zon geografic. O reea de osele leag
direct unele dintre aceste puncte de lucru i ntre oricare dou puncte de lucru exist o
IC

legtur prin intermediul reelei de osele. Distana dintre dou puncte de lucru ntre care
exist legtur direct este msurat n kilometri. Firma trebuie s-i stabileasc ntr-unul
din punctele de lucru sediul central. Criteriul de alegere este ca suma distanelor la
CT

celelalte puncte de lucru s fie minim. Scriei un program care s stabileasc punctul de
lucru care va fi ales ca sediu. Datele se citesc dintr-un fiier, astfel: de pe primul rnd,
numrul de puncte de lucru, iar de pe urmtoarele rnduri, triplete de numere x, y, d care
DA

semnific faptul c punctele de lucru x i y sunt legate direct de o osea cu lungimea d.


Indicaie. Pentru fiecare punct de lucru se determin suma distanelor minime la toate
celelalte puncte de lucru, dup care se determin suma minim.
3. O firm trebuie s colecteze ambalaje din mai multe puncte de lucru din ora, fiecare
DI

punct de lucru gsindu-se pe o anumit strad. O reea de intersecii leag direct unele
dintre aceste puncte de lucru i ntre oricare dou puncte de lucru exist o legtur prin
intermediul traficului pe strzi. Traficul ntre dou intersecii nu este ntotdeauna n ambele
sensuri, dar ntre oricare dou intersecii exist trafic prin intermediul altor intersecii.
RA

Cantitatea de ambalaje care poate fi colectat ntre dou intersecii ntre care exist trafic
direct este msurat n kilograme. Scriei un program care s gseasc un traseu optim
ntre dou intersecii A i B astfel nct o main care pleac din intersecia A i trebuie s
ajung n intersecia B s colecteze o cantitate ct mai mare de ambalaje. Datele se citesc
TU

dintr-un fiier, astfel: de pe primul rnd, numrul de intersecii, iar de pe urmtoarele


rnduri, triplete de numere x, y, c care semnific faptul c intersecia x este legat direct
de intersecia y prin traficul de pe o strad de pe care se poate colecta cantitatea c de
I

ambalaje. Etichetele interseciilor A i B se citesc de la tastatur.


ED
256 Implementarea structurilor de date

C
4. O firm se poate aproviziona cu trei sortimente de materiale de la mai multe depozite
situate n localiti rspndite ntr-o zon geografic. ntr-un depozit nu este obligatoriu
s existe toate cele trei sortimente. O reea de osele leag direct unele dintre aceste

I
localiti i ntre oricare dou localiti exist o legtur prin intermediul reelei de osele.

OG
Distana dintre dou localiti ntre care exist legtur direct este msurat n
kilometri. Firma trebuie s se aprovizioneze cu unul dintre sortimentele de materiale.
Scriei un program care s stabileasc depozitul de la care s se aprovizioneze firma
astfel nct drumul care trebuie parcurs pentru aprovizionare s aib lungimea minim.

AG
Fiecrui sortiment de material i se atribuie un numr: 1, 2 i 3. Datele se citesc dintr-un
fiier text. De pe primul rnd se citesc numrul de localiti n n care se gsesc depozite
i numrul de legturi directe ntre localiti, m. De pe urmtoarele m rnduri se citesc
triplete de numere x, y, d care semnific faptul c localitile x i y sunt legate direct de
o osea cu lungimea d. De pe fiecare dintre ultimele trei rnduri, n ordinea etichetelor

ED
sortimentelor de materiale, se citete cte un ir de numere desprite prin spaiu cu
informaii despre locaiile depozitelor unde se gsete acel sortiment de material: primul
numr reprezint numrul de depozite, iar urmtoarele numere etichetele localitilor n
care se gsesc aceste depozite. Numrul sortimentului de materiale p se comunic de

P
la tastatur. Indicaie. Se determin distana minim de la localitatea n care se gsete
firma la localitile n care se gsesc depozitele i se alege dintre aceste distane cea
I
mai mic distan care corespunde unui depozit ce conine sortimentul de material p.

2.7.10. Grafuri speciale


Exist urmtoarele grafuri speciale:


grafuri bipartite;
IC

grafuri hamiltoniene:
grafuri euleriene:
grafuri turneu.
CT

2.7.10.1. Graful bipartit


Graful G = (X,U) se numete graf bipartit dac exist dou mulimi nevide de noduri
A i B care au urmtoarele proprieti: AB=X i AB= i
DA

orice muchie (arc) din mulimea U are o extremitate n mulimea de noduri A


i o alt extremitate n mulimea de noduri B.
Exemple:
DI

1. Graful neorientat G4 definit anterior este un graf bipartit, deoarece exist


mulimile A i B care s ndeplineasc condiiile din definiie: A = {1, 3,
6, 7, 8, 10} i B = {2, 4, 5, 9,11}. Se observ c: AB = {1, 2 ,3, 4, 5, 6,
RA

7, 8, 9, 10, 11} = X4 i AB= i c fiecare muchie uU4={[1,2], [1,4],


[2,3], [3,4], [3,5], [5,6], [5,7], [5,8], [7,9]} are o extremite n mulimea A i
cealalt extremitate n mulimea B:
[1,2] 1A i 2B [1,4] 1A i 4B [2,3] 2B i 3A
TU

[3,4] 3A i 4B [3,5] 3A i 5B [5,6] 5B i 6A


[5,7] 5B i 7A [5,8] 5B i 8A [7,9] 7A i 9B
Observaie. Nodurile izolate pot face parte din oricare dintre cele dou
Fig. 35
mulimi.
I
ED
Informatic 257

C
2. Graful orientat G9 definit anterior este un graf bipartit deoarece exist
mulimile A i B care s ndeplineasc condiiile din definiie: A = A = {1,
3, 4, 6} i B = {2, 5}. Se observ c: AB = {1, 2, 3, 4, 5, 6} = X9 i

I
AB= i c fiecare muchie uU9={[1,2], [2,1], [2,3], [2,4], [3,5], [4,2],

OG
[4,5], [5,3], [5,6], [6,5]} are o extremite n mulimea A i cealalt extre-
mitate n mulimea B:
[1,2] 1A i 2B [2,1] 2B i 1A [2,3] 2B i 3A
[2,4] 2B i 4A [3,5] 3A i 5B [4,2] 4A i 2B

AG
[4,5] 4A i 5B [5,3] 5B i 3A [5,6] 5B i 6A
[6,5] 6A i 5B Fig. 36
Graful bipartit G = (X,U) se numete graf bipartit complet dac pentru
orice nod xiA i orice nod xjB exist o muchie (un arc) format din cele

ED
dou noduri care aparine mulimii U: [xi, xj]U.
Exemple:
1. Graful neorientat G28=(X28,U28) definit astfel: X28={1, 2, 3, 4} i U28={[1,2],
G
G
G222888

P
[1,4], [2,3], [2,3]} este un graf bipartit complet. deoarece exist mulimile A i B
care ndeplineasc condiiile din definiie: A={1, 3} i B={2, 4}. Se observ c:
AB= {1,2,3,4}=Xx i AB= i c fiecare nod din mulimea A este legat cu o Fig. 37
I
muchie de fiecare nod din mulimea B.
2. Graful orientat G29 =(X29,U29) definit astfel: X29={1, 2, 3, 4} i U29={[1,2],
[1,4], [2,1], [2,3], [3,2], [4,3]} este un graf bipartit complet, deoarece exist G
G
G222999

mulimile A i B care s ndeplineasc condiiile din definiie: A={1, 3} i


B={2, 4}. Se observ c: AB={1, 2, 3, 4}=Xx i AB= i c fiecare nod
Fig. 38
IC

din mulimea A este legat cu cel puin un arc de fiecare nod din mulimea B.
Observaie. Graful neorientat bipartit complet se noteaz cu Ka,b i are ab
muchii, unde a=card(A) i b=card(B). De exemplu, dac graful neorientat are 3 noduri,
CT

se obin urmtoarele variante de grafuri bipartite complete:


Elementele mulimii Muchiile Numrul de
A B grafului muchii ale grafului
DA

1 2,3 [1,2], [1,3] 12=2


2 1,3 [2,1], [2,3] 12=2
3 1,2 [3,1], [3,2] 12=2
1,2 3 [1,3], [2,3] 21=2
1,3 2 [1,2], [3,2] 21=2
DI

2,3 1 [2,1], [3,1] 21=2


1,2,3 nu exist, deoarece B= 30=0
1,2,3 nu exist, deoarece A= 03=0
RA

Algoritmi pentru prelucrarea grafurilor bipartite


1. Generarea tuturor grafurile neorientate bipartite complete cu n noduri.
Algoritmul. Problema se reduce la a genera toate submulimile care se pot obine din
TU

cele n elemente (exceptnd mulimea iniial i mulimea vid). Numrul total de submul-
n
imi obinute este 2 2. Soluia este de a genera ntr-un vector nodurile care aparin
mulimilor A i B, astfel: dac un element are valoarea 1, nodul care are eticheta cores-
punztoare indicelui elementului aparine mulimii A; altfel, aparine mulimii B.
I
ED

Implementarea algoritmului. Funcia generare()genereaz grafurile bipartite complete.


n vectorul a se genereaz nodurile mulimilor A i B. Iniial elementele vectorului au
258 Implementarea structurilor de date

C
valoarea 0. Variabila posibil se folosete pentru a verifica dac mai exist posibiliti
de generare de submulimi (are valoarea 1 true, atunci cnd mai este posibil s se
genereze submulimi).

I
#include<iostream.h>

OG
#include<math.h>
void generare (int n)
{int a[10]={0},i,j,k=0,posibil=1;
while (posibil)

AG
{j=n;
while (j>0 && a[j]==1) {a[j]=0; j--;}
if (j==0) posibil=0;
else {a[j]=1;k++;
if (k<=pow(2,n)-2)

ED
{cout<<"Graful "<<k<<endl<<"Multimea A: ";
for (i=1;i<=n;i++) if (a[i]) cout<<i<<" ";
cout<<"Multimea B: ";
for (i=1;i<=n;i++) if (!a[i]) cout<<i<<" ";

P
cout<<endl;
cout<<"Muchiile sunt: ";
for (i=1;i<=n;i++)
I
if (a[i]==1)
for (j=1;j<=n;j++)
if (a[j]==0 && i!=j) cout<<"["<<i<<","<<j<<"] ";
cout<<endl;}}}}

void main() {int n; cout<<"numar de noduri= "; cin>>n; generare(n);}


2. Verificarea unui graf dac este graf bipartit.
IC

Algoritmul. Pentru a verifica dac graful este bipartit, se genereaz mulimile de noduri A
i B pn cnd aceste mulimi ndeplinesc condiia unui graf bipartit, sau pn cnd s-au
CT

generat toate mulimile i nici una dintre variante nu a ndeplinit condiia pentru graful
bipartit. Graful este bipartit dac ntre orice pereche de elemente din cele dou mulimi
(x,y), cu xA i yB exist muchie care s le lege n graf ([x,y]U). Pentru generarea
mulimilor de noduri A i B se pot folosi dou variante:
DA

Varianta 1. Ca i n algoritmul precedent, se genereaz ntr-un vector toate submulimi-


le care se pot obine din cele n etichete de noduri (exceptnd mulimea iniial i muli-
mea vid) i se verific dac nodurile aparinnd celor dou mulimi generate pot fi
mulimile unui graf bipartit.
DI

Implementarea algoritmului. Se citesc din fiierul text gb.txt informaii despre un graf
neorientat (numrul de noduri i matricea de adiacen). Funcia bipartit() verific
dac graful este bipartit furniznd un rezultat logic. Elementele vectorului x n care se
RA

genereaz mulimile A i B sunt iniial 0. Variabila gasit se folosete pentru a verifica


dac s-au gsit cele dou mulimi de noduri corespunztoare unui graf bipartit (are
valoarea 1 true, atunci cnd s-au gsit).
#include<fstream.h>
TU

#include<math.h>
fstream f("gb.txt",ios::in);
int a[10][10],n;
void citeste(){//citete matricea de adiacen din fiier}
I

int bipartit()
ED

{int x[10]={0},i,j,m,k=0,posibil=1,gasit=0;
while (posibil && !gasit)
Informatica 259

C
{m=n;
while (m>0 && x[m]==1) {x[m]=0; m--;}
if (m==0) posibil=0;

I
else

OG
{x[m]=1;k++;
if (k<=pow(2,n)-2)
for (i=1,gasit=1;i<=n && gasit;i++)
for (j=1;j<=n && gasit;j++)
if (a[i][j]==1)

AG
if ((x[i]==1 && x[j]==1) || (x[i]==0 && x[j]==0)) gasit=0;}}
return gasit;}
void main() {citeste();
if (bipartit()) cout<<"Este bipartit";
else cout<<"Nu este bipartit";}

ED
Varianta 2. Elementele mulimilor A i B se genereaz separat, n doi vectori. Pentru gene-
rarea mulimii A se folosete metoda backtracking (etichetele nodurilor mulimii A se
genereaz n stiv). Funcia bt() este apelat de n-1 ori pentru a genera n stiv cele p

P
elemente ale mulimii A (1pn-1). Mulimea B este format din nodurile grafului care nu se
gsesc n mulimea A.
Implementarea algoritmului. Matricea A este matricea de adiacen a grafului, iar n
I
vectorii a i b se genereaz elementele mulimilor A i B. n funcia tipar() se copiaz
coninutul stivei n vectorul a i se scriu n vectorul b etichetele nodurilor care nu sunt n
vectorul a. Pentru a identifica etichetele nodurilor care nu sunt n vectorul a se folosete

variabila logic gasit. Tot n aceast funcie se verific dac aceste mulimi corespund
unui graf bipartit, astfel: se verific, pentru toate elementele celor doi vectori, dac muchiile
IC

generate cu un nod din vectorul a i un nod din vectorul b sunt muchii n graf. n caz
afirmativ, se verific dac muchiile astfel generate sunt toate muchiile grafului. Variabila nr
se folosete pentru a numra muchiile formate cu nodurile din cei doi vectori, iar variabila
CT

logic este pentru a verifica dac graful este bipartit. (are valoarea 1 true, dac numrul
de muchii gsite este egal cu numrul total de muchii ale grafului m).
#include<fstream.h>
fstream f("gb.txt",ios::in);
DA

typedef int stiva[100];


int n,k,ev,as,A[10][10],b[10],a[10],m,este,p;
stiva st;
void citeste()
DI

{int i,j; f>>n;


for(i=1;i<=n;i++)
for (j=1;j<=n;j++){f>>A[i][j]; m=m+A[i][j];} f.close(); m=m/2;}
void init(){st[k]=0;}
RA

int succesor ()
{if (st[k]<n) {st[k]=st[k]+1; return 1;} else return 0;}
int valid()
{if (k>1 && st[k]<st[k-1]) return 0;
TU

for (int i=1;i<k;i++) if (st[k]==st[i]) return 0;


return 1;}
int solutie() {return k==p;}
void tipar()
{int i,j,q=0,gasit,nr=0;
I
ED

for (i=1;i<=p;i++) a[i]=st[i];


for (i=1; i<=n; i++)
260 Implementarea structurilor de date

C
{for (j=1,gasit=0; j<=p && !gasit; j++) if (a[j]==i) gasit=1;
if (!gasit) {q++; b[q]=i;}}
for (i=1; i<=p; i++)

I
for (j=1; j<=q; j++) if (A[a[i]][b[j]]==1) nr++;

OG
if (nr==m) este=1;}
void bt() {//partea fixa a algoritmului backtracking}
void main() {citeste();
for (p=1; p<=n-1 && !este; p++) bt();
if (este) cout<<"Este bipartit";

AG
else cout<<"Nu este bipartit";}
1. Scriei un program care citete din fiierul graf_b1.txt matricea de
Tem adiacen a unui graf neorientat i, de la tastatur, dou iruri de
numere ce reprezint noduri din graf i care verific dac cele dou

ED
iruri de numere pot reprezenta pentru graf cele dou mulimi ale unui graf bipartit.
2. Comparai din punct de vedere al eficienei cei doi algoritmi prin care se determin
dac un graf neorientat este bipartit.
3. Scriei un program care citete din fiierul graf_b2.txt matricea de adiacen a unui

P
graf orientat i care verific dac graful este bipartit. n caz afirmativ, se afieaz
mulimile de noduri A i B.
I
2.7.10.2. Graful hamiltonian
ntr-un graf G=(X,U), se numete lan hamiltonian lanul elementar
care conine toate nodurile grafului.

Altfel spus, un lan este hamiltonian dac pornete de la un nod oarecare i parcurge o
IC

singur dat toate nodurile grafului.


Lanul hamiltonian n care nodul iniial coincide cu nodul final se
numete ciclu hamiltonian.
CT

Ca ntr-un graf s existe un ciclu hamiltonian este necesar ca pe lng un lan hamiltonian
s mai existe i o muchie care s lege primul nod al lanului de ultimul nod al lanului.
Un graf care conine un ciclu hamiltonian se numete graf hamiltonian.
DA

Altfel spus, un graf hamiltonian este un graf n care pornind de la un nod oarecare
se pot parcurge o singur dat toate nodurile grafului, revenind la nodul iniial.
G
G
G333000 Graful G30 din figura 39 conine ciclul hamiltonian C= {1, 2, 3, 6, 4, 5, 1}.
DI

Observaie. Un graf hamiltonian nu poate conine noduri izolate.


Propoziia 10
Graful complet Kn este hamiltonian.
RA

Demonstraie. Graful complet Kn poate fi privit ca un poligon cu n laturi, n care Fig. 39


fiecare vrf al poligonului este legat de celelalte vrfuri prin diagonale, iar vrfurile
poligonului parcurse pe laturi formeaz un ciclu hamiltonian.
TU

Scop: exemplificarea unei aplicaii n care soluia problemei este un graf hamiltonian.
Problema voiajorului comercial. Un voiajor comercial trebuie s cltoreasc n mai
I

multe orae pentru a-i prezenta produsele. Se cunoate costul deplasrii ntre localiti.
ED

Trebuie s se stabileasc un traseu prin care s se ajung n toate localitile, astfel nct
Informatica 261

C
costul deplasrii s fie minim. Voiajorul va trece o singur dat prin fiecare localitate i se
va ntoarce n localitatea de pornire.
Localitile formeaz nodurile unui graf, iar traseul voiajorului trebuie s fie un ciclu hamilto-

I
nian n acest graf. Dac exist mai multe cicluri hamiltoniene, se va alege cel cu costul

OG
minim (ciclul n care suma costurilor asociate muchiilor este minim).
Observae. Orice problem la care soluia este de a gsi un traseu care pornete dintr-un
anumit punct, trebuie s treac prin puncte precizate, cu revenire la punctul de pornire se
rezolv prin gsirea unui ciclu hamiltonian. De exemplu:

AG
O firm de mesagerie trebuie s distribuie zilnic colete la mai multe adrese. Maina care
distribuie aceste colete pleac de la sediul firmei, ajunge la mai multe puncte din ora i
revine la sediul firmei. Legtura direct dintre dou puncte este caracterizat prin
distana msurat n kilometri (costul asociat fiecrei muchii). Trebuie s se gseasc

ED
traseul de lungime minim pe care trebuie s-l parcurg maina.
O persoan dorete s fac un circuit prin ar i s viziteze mai multe puncte turistice,
plecnd din localitatea de domiciliu i ntorcndu-se n aceeai localitate. Legtura direct
dintre dou puncte turistice este caracterizat prin distana msurat n kilometri (costul

P
asociat fiecrei muchii). Trebuie s se gseasc circuitul turistic de lungime minim.
O persoan dorete s viziteze mai multe cabane, ntorcndu-se la locul de plecare.
Legtura direct dintre dou cabane este caracterizat prin timpul necesar parcurgerii
I
traseului de munte (costul asociat fiecrei muchii). Trebuie s se gseasc
circuitul de vizitare a cabanelor care s se fac n timp minim.
Teorema 18

Dac graful G=(X,U) este un graf cu mai mult de dou noduri (n3) i gradul
IC

fiecrui nod xX satisface condiia d(x)n/2, atunci graful G este hamiltonian.


Observaie. Aceast teorem precizeaz numai condiia suficient ca un graf s fie
hamiltonian. Aceast condiie nu este ns i necesar. Astfel, este posibil ca un graf s nu
CT

ndeplineasc aceast condiie i s fie totui hamiltonian. Din aceast cauz, teorema nu
poate fi folosit pentru a construi un algoritm care s verifice dac un graf este hamiltonian.
Demonstraie. Notm cele dou propoziii, astfel:
DA

(1) Graful G are mai mult de dou noduri i gradul fiecrui nod xX satisface condiia d(x)n/2.
(2) Graful G este hamiltonian.
Trebuie s demonstrm c (1)(2) prin reducere la absurd. Presupunem c graful G nu este hamil-
tonian. Adugm muchii la acest graf pn se obine un graf hamiltonian (n cel mai ru caz se ajunge
la un graf complet, care sigur este hamiltonian). Prin adugarea de noi muchii, gradul unor noduri
DI

crete, ceea ce nseamn c se pstreaz inegalitatea din propoziia (1). Adugarea acestor muchii
se face pn cnd se obine graful G1 care nu este hamiltonian, dar care. prin adugarea unei singure
muchii devine hamiltonian. Acest graf nu este sigur un graf complet i nseamn c exist cel puin
dou noduri neadiacente. Lum dintre aceste noduri dou noduri x i y i [x,y]U1 care au propri-
RA

etatea c, prin adugarea muchiei [x,y] la graful G1, se obine un ciclu hamiltonian C = {x, x1, , xk-1,
xk, y, x}. nseamn c n graful G1 exist un lan elementar L(x,y) care conine toate nodurile grafului.
Deoarece d(x)n/2, rezult c n graful G1 mai exist un nod xi cu care este adiacent. Acest nod face
parte din lanul L(x,y). Fie xi-1 nodul care precede nodul xi n lanul L(x,y). Dac nodurile xi-1 i y
TU

formeaz o muchie ([xi-1,y]U1), nseamn c graful G1 conine un ciclu hamiltonian C1 = {x, x1, ,
xi-1, y, xk, xk-1, , xi, x}, ceea ce contrazice presupunerea c graful G1 nu este hamiltonian. Rezult
c nodul y nu formeaz muchie cu nici unul dintre nodurile care l preced n lanul L(x,y) i care sunt
adiacente cu nodul xi. nseamn c nodul y nu poate fi adiacent dect cu cel mult n-1-d(xi) noduri, adic
I

d(y) n-1-d(xi). Dar, d(xi)n/2. Rezult c d(y) n-1-n/2=n/2-1, adic d(y)n/2, ceea ce contrazice
ED

ipoteza. Contradicia a aprut din presupunerea c graful G nu este hamiltonian.


262 Implementarea structurilor de date

C
1. Verificai dac graful hamiltonian G30 din figura 39 ndeplinete
Tem condiiile precizate n teorem.
2. Desenai toate grafurile hamiltoniene cu 4 noduri.

I
G
G
G333111 3. Verificai dac este hamiltonian graful G31=(X31,U31) cu X31={1,2,3,4,5,6,7} i U31={[1,2],

OG
[1,5], [1,6], [1,7], [2,3], [2,7], [3,4], [3,5], [3,7], [4,5], [4,6], [5,6]}. Dac este graf hamiltonian,
gsii un ciclu hamiltonian i verificai dac graful ndeplinete condiiile precizate n teorem.
4. Demonstrai c un graf bipartit cu numr impar de noduri nu poate fi graf hamiltonian.
(n 1)!
5. Demonstrai c numrul ciclurilor hamiltoniene din graful complet cu n noduri este .

AG
2
Algoritmul pentru parcurgerea unui graf hamiltonian
Algoritmul. Pentru a determina dac un graf este hamiltonian se verific dac exist un ciclu
hamiltonian. Este suficient s se caute lanurile elementare care pornesc din nodul cu eticheta

ED
1 i se nchid n acest nod. Se poate folosi fie metoda backtracking, fie metoda parcurgerii
n lime a grafului. Prin aceste metode se pot determina i toate ciclurile hamiltoniene, dac
exist, astfel: se caut toate ciclurile elementare care, pornind dintr-un nod, parcurg toate
celelalte noduri ale grafului i se nchid printr-o muchie cu nodul de pornire.

P
Implementarea algoritmului. Se citete din fiierul graf_h.txt matricea de adiacen a unui
graf neorientat. Dac graful este hamiltonian, se afieaz ciclurile hamiltoniene gsite. Dac
I
nu exist nici o soluie, se afieaz un mesaj de informare. Pentru generarea lanurilor
elementare se folosete metoda backtracking. Nodurile lanului elementar vor fi generate n
stiv. Funcia citeste() se folosete pentru a citi matricea de adiacen n fiier. Variabila
este se folosete pentru a verifica dac s-a gsit un ciclu hamiltonian pornind din nodul cu

eticheta 1 (are valoarea 0 False, dac nu s-a gsit un ciclu hamiltonian).


IC

#include<fstream.h>
typedef stiva[100];
int a[20][20],n,k,as,ev,este=0;
stiva st;
CT

fstream f("graf_h.txt",ios::in);
void citeste() {//se citete matricea de adiacen}
void init() {st[k]=0;}
int succesor()
DA

{if (st[k]<n) {st[k]=st[k]+1; return 1;} else return 0;}


int valid()
{if(k>1 && a[st[k-1]][st[k]]==0) return 0;
for (int i=1;i<k;i++) if (st[k]==st[i]) return 0;
DI

return 1;}
int solutie() {return a[st[k]][1]==1 && k==n;}
void tipar()
{for (int i=1,este=1;i<=n;i++) cout<<st[i]<<", "; cout<<st[1]<<endl;}
RA

void bt() {//identic cu cea de la generarea lanurilor elementare}


void main() {citeste(); st[1]=1; bt();
if (!este) cout<<"Graful nu este hamiltonian";}
1. Scriei un program care citete din fiierul text graf_h1.txt matricea de
TU

Tem adiacen a unui graf hamiltonian, verific dac graful ndeplinete


condiia precizat n teorem pentru un graf hamiltonian i verific dac
este hamiltonian folosind metoda parcurgerii n lime a grafului.
2. Scriei un program care citete din fiierul text graf_h2.txt matricea de adiacen a unui
I
ED

graf hamiltonian i, de pe ultimul rnd, un ir de n+1 numere care reprezint etichete de


noduri i care s verific dac irul de etichete reprezint un ciclu hamiltonian.
Informatica 263

C
2.7.10.3. Graful eulerian
ntr-un graf G=(X,U), se numete lan eulerian lanul care conine

I
toate muchiile grafului, fiecare muchie fiind prezent o singur dat.

OG
Un lan este eulerian dac pornete de la un nod oarecare i parcurge o singur dat toate
muchiile grafului (este un lan simplu care parcurge toate muchiile grafului).
Lanul eulerian n care nodul iniial coincide cu nodul final se numete ciclu
eulerian.

AG
Ca ntr-un graf s existe un ciclu eulerian este necesar ca, pe lng un lan eulerian, s mai
existe i o muchie care s lege primul nod al lanului de ultimul nod al lanului, i acea
muchie s nu mai fi fost parcurs.

ED
Un graf care conine un ciclu eulerian se numete graf eulerian.
Altfel spus, un graf eulerian este un graf n care, pornind de la un nod oarecare se pot
parcurge o singur dat toate muchiile grafului, revenind la nodul iniial.
Graful G32 din figura 40 conine ciclul eulerian C= {1, 4, 6, 7, 4, 5, 7, 8, 3, 2, 8, 5, 2, 1}. G
G
G333222

P
Observaii
1. Un graf eulerian poate conine noduri izolate.
I
2. Pentru ca un graf s poat fi fcut eulerian prin adugarea muchiilor
trebuie s fie ndeplinite urmtoarele condiii:
dac numrul de noduri este par, s nu existe noduri cu gradul maxim;
numrul de noduri cu grad impar s fie par.

Numrul minim de muchii care trebuie adugate este egal cu jumtate Fig. 40
din numrul de noduri cu grad impar.
IC
CT

Scop: exemplificarea aplicaiei n care soluia problemei este un graf eulerian.


Problema podurilor din oraul Knigsberg.
n acest ora exist apte poduri peste delta
DA

rului Pregel care leag cele patru sectoare ale c d


oraului (figura 41). Problema const n a stabili
un traseu prin care un vizitator s parcurg toate e
g
cele patru sectoare ale oraului (A, B, C i D),
DI

ntorcndu-se n punctul de unde a plecat, a b


trecnd peste fiecare pod o singur dat. f
Cele patru zone (notate Fig. 41
cu A, B, C i D) i cele
RA

apte poduri (notate cu a, b, c, d, e, i f) reprezint nodurile unui


graf neorientat G33 (figura 42), iar muchiile reprezint posibilitatea de G
G
G333333
a trece pe un pod dintr-o zon, n alt zon. Problema const n a
gsi n acest graf un ciclu care s parcurg toate muchiile o singur
TU

dat, adic un ciclu eulerian. Matematicianul Euler a demonstrat


matematic, n anul 1736, c aceast problem nu are soluii
Fig. 42
(c acest graf nu este eulerian).
I
ED
264 Implementarea structurilor de date

C
Teorema 19
Un graf G=(X,U), care nu conine noduri izolate, este eulerian dac i numai
dac este conex i gradele tuturor nodurilor sunt numere pare.

I
OG
Demonstraie. Notm cele dou propoziii, astfel:
(1) Graful G nu conine noduri izolate i este eulerian.
(2) Graful G este conex i gradele tuturor nodurilor sunt numere pare.
Trebuie s demonstrm c (1)(2) i (2)(1).
(1)(2)

AG
a. Graful este conex. Trebuie s demonstrm c, oricare ar fi nodurile x i y din graf, exist un lan
L(x,y) care le leag. Pentru cele dou noduri poate s apar una dintre urmtoarele situaii:
Sunt adiacente ([x,y]U). nseamn c exist lanul L(x,y).
Nu sunt adiacente ([x,y]U). Deoarece graful nu are noduri izolate, nseamn c exist alte dou
noduri z i w din graf care sunt adiacente cu cte unul dintre ele ([x,z]U i [y,w]U). Deoarece

ED
graful este eulerian, exist un ciclu care conine toate muchiile grafului, inclusiv muchiile [x,z] i
[y,w]. Fie acest ciclu C = { x1, , x, , y, , xk}. Acest ciclu conine un lan L(x,y).
Deoarece n ambele situaii exist un lan L(x,y), nseamn c graful este conex.
b. Gradele tuturor nodurilor sunt numere pare. Trebuie s demonstrm c pentru un nod oarecare

P
xX, d(x) este un numr par. Ciclul eulerian coninnd toate muchiile grafului, conine i toate
nodurile grafului. Acest ciclu se poate reorganiza astfel nct nodul x s nu fie primul nod: C = { y, ,
x, , y}. Nodul x poate s apar n acest ciclu de p ori. Fiecare apariie a nodului x n acest ciclu
I
nseamn existena a dou muchii diferite incidente cu el. Rezult c d(x)=2p, adic un numr par.
(2)(1) prin reducere la absurd.
Presupunem c graful G nu este eulerian. Graful fiind conex, nu conine noduri izolate. Fie dou noduri

oarecare x i y ntre care exist o muchie ([x,y]U). Nodul y avnd gradul un numr par, nseamn
c exist un nod z cu care formeaz o muchie ([y,z]U). Continund n acest mod, se ajunge la un
nod w care formeaz muchie cu nodul x ([w,x]U), deoarece i gradul nodului x este un numr par.
IC

Rezult c n graful G exist un ciclu. Vom considera, dintre ciclurile care exist n acest graf, ciclu C
de lungime maxim, dar care, conform presupunerii fcute, nu conine toate muchiile grafului. Pentru
fiecare nod din acest ciclu se consum dou uniti din gradul lui. Cutm o muchie care nu face
CT

parte din ciclul C, dar este incident cu un nod din ciclul C. Aceast muchie exist deoarece dac nu
ar fi, ciclul C ar forma o component conex, ceea ce contrazice ipoteza c graful G este conex. Fie
muchia [x,y]U, cu xC. Pornind de la aceast muchie, pe muchii care nu aparin ciclului C, trecnd
prin noduri ale cror grade nu au fost epuizate, se obine, dup un numr finit de pai, un nou ciclul C1
DA

care se nchide n nodul x. Prin concatenarea celor dou cicluri care au un nod comun (x), se obine
un ciclu de lungime mai mare dect ciclul C, ceea ce contrazice presupunerea c ciclu C are cea mai
mare lungime. nseamn c el conine toate muchiile grafului i graful este eulerian.
Observaie. Aceast teorem, preciznd condiiile necesare i suficiente ca un graf s
DI

fie eulerian, poate fi folosit pentru a construi un algoritm care s verifice dac un graf este
eulerian.
1. Verificai condiiile din teorem pentru graful eulerian G32 din figura 40.
G
G Tem
RA

G333444 2. Verificai dac graful G34=(X34,U34) cu X34={1,2,3,4,5,6.7} i U34={[1,2],


[1,3], [2,3], [2,4], [2,5], [3,5], [3,7], [4,5], [4,6], [4,7], [5,6]} este eulerian.
Dac graful este eulerian, gsii un ciclu eulerian i verificai dac graful ndeplinete condi-
iile precizate n teorem.
TU

3. Demonstrai c ntr-un graf conex G exist dou noduri diferite x i y legate printr-un lan
eulerian dac i numai dac ele sunt singurele noduri cu grad impar din graf.
4. Desenai toate grafurile euleriene cu 4 noduri.
G
G
G333555 5. Verificai dac graful conex G35=(X35,U35) cu X35={1,2,3,4,5,6.7,8} i U35={[1,2], [1,4], [2,3],
I

[2,4], [2,5], [3,6], [4,5], [4,7], [5,6], [5,7], [5,8], [6,8], [7,8]} poate fi fcut eulerian prin adugare
ED

de muchii. n caz afirmativ, precizai cte muchii trebuie adugate i care sunt aceste muchii.
Informatica 265

C
6. Verificai dac graful neconex G36=(X36,U36) cu X36={1,2,3,4,5,6.7,8,9,10,11} i U36={[1,2], G G
G333666
[2,4], [3,4], [4,5], [4,6], [5,6], [5,7], [6,7], [8,9], [8,11], [9,10], [9,11], [10,11] } poate fi fcut
eulerian prin adugare de muchii. n caz afirmativ, precizai cte muchii trebuie adugate

I
i care sunt aceste muchii. Gsii un algoritm pentru generalizarea problemei.

OG
7. S se dea exemple de urmtoarele grafuri:
a. s nu fie hamiltonian i nici eulerian;
b. s fie hamiltonian, dar nu eulerian:
c. s nu fie hamiltonian, dar s fie eulerian:

AG
d. s fie hamiltonian i eulerian.

Algoritmul pentru parcurgerea unui graf eulerian


Pentru a implementa graful se folosete matricea de adiacen a i vectorul g n care se

ED
memoreaz gradul fiecrui nod, care se calculeaz cu funcia grad(). Algoritmul care
determin dac un graf este eulerian verific dac graful ndeplinete condiiile precizate
n teorem:
Nodurile izolate. Se verific dac graful are sau nu noduri izolate. Dac are noduri izo-

P
late se consider c graful nu este eulerian. n implementarea algoritmului se folosete
funcia izolat() care testeaz gradul nodurilor i furnizeaz un rezultat logic: true (1)
dac cel puin un nod are gradul 0 i false (1) dac nici un nod nu are gradul 0.
I
Gradul nodurilor. Se verific dac gradul fiecrui nod este par. n implementarea algorit-
mului se folosete funcia grad par() care furnizeaz un rezultat logic: false (0) dac cel
puin un nod are gradul impar i true (1) dac nici un nod nu are gradul impar.

Conexitatea. Se verific dac graful este conex. Pentru aceasta se va parcurge graful
IC

n adncime i se verific dac rmn noduri care nu au fost vizitate. n implementarea


algoritmului se folosete vectorul vizitat pentru a ine evidena nodurilor vizitate.
Conexitatea se verific prin funcia conex()care furnizeaz un rezultat logic: false (0)
CT

dac cel puin un nod nu a fost vizitat i true (1) dac toate nodurile au fost vizitate.
Pentru testarea condiiilor necesare ca un graf s fie eulerian se folosete variabila eulerian
care are valoarea logic: false (0) dac graful nu este eulerian i true (1) dac graful este
eulerian.
DA

Dac graful este eulerian se poate determina un ciclu eulerian. Acest algoritm folosete
demonstraia de la teorema precedent. Construirea ciclului eulerian se face astfel:
PAS1. Se pornete dintr-un nod oarecare din graf i se construiete din aproape n aproape
DI

ciclul C, pe muchii incidente care exist n graf, scznd gradele nodurilor prin care
trece i eliminnd muchiile.
PAS2. Ct timp mai exist muchii care nu fac parte din ciclul C execut: se alege un nod
din ciclul C pentru care mai exist muchii incidente care nu fac parte din ciclul C, se
RA

construiete ciclul C1 i se concateneaz ciclul C1 la ciclul C.


Soluia se va obine ntr-un vector c care conine nodurile parcurse care au fost adugate la
ciclul eulerian. Vectorul c1 se folosete pentru extinderea ciclului eulerian. Se mai folosesc
TU

urmtoarele variabile de memorie:


n numrul de noduri i m numrul de muchii;
i, j, k contori pentru parcurgerea matricei de adiacen i a vectorilor folosii;
q variabil n care se pstreaz nodul de la care ncepe ciclul c1;
I

p variabil n care se pstreaz lungimea logic a vectorului c1.


ED
266 Implementarea structurilor de date

C
Algoritmul pentru determinarea ciclului eulerian este urmtorul:
PAS1. Se citesc valorile pentru variabilele de memorie n i m i matricea de adiacen a.
PAS2. Se verific dac graful este eulerian, adic dac ndeplinete condiia s nu aib

I
noduri izolate, nodurile s aib grade pare i s fie conex: (n implementarea

OG
algoritmului: eulerian=!v_izolat()&&grad_par()&& conex()).
PAS3. Dac graful nu este eulerian (variabila eulerian are valoarea false), atunci se afi-
eaz mesajul 'Graful nu este eulerian' i se termin algoritmul; altfel, se scrie mesa-
jul 'Graful este eulerian' i se trece la Pasul 4 pentru a determina un ciclu eulerian.

AG
PAS4. Se pleac dintr-un nod oarecare (de exemplu, nodul 1: c[1]=1).
PAS5. Execut urmtorii pai pentru a construi n vectorul c un prim ciclu prin parcur-
gerea din aproape n aproape a muchiilor grafului, pornind de la nodul cu eticheta j
egal cu 1: j=1 (acest ciclu exist, deoarece gradul nodului de pornire este par,

ED
ceea ce nseamn c oricare ar fi muchia pe care se pornete, mai exist cel
puin o muchie care sosete n acest nod).
PAS6. Ct timp nu s-a gsit o muchie ntre nodul curent k din coada c (c[k]) i
un alt nod j din graf (j<=n) execut:

P
PAS7. Dac exist o muchie ntre nodul curent k din coada c (c[k]) i un alt
nod j din graf (a[c[k]][j]==1), atunci se trece la Pasul 8; altfel, se
trece la Pasul 11.
I
PAS8. Se adaug nodul j la coada c (k=k+1;c[k]=j;).
PAS9. Se micoreaz cu o unitate gradul celor dou noduri parcurse (g[j]--;
g[c[k-1]]--;).
PAS10. Se terge din matricea de adiacen muchia parcurs (a[c[k]][j]=0;

a[j][c[k]]=0;).
IC

PAS11. Se trece la urmtorul nod prin incrementarea lui j (j=j+1) i se


revine la Pasul 6.
Pn cnd nodul curent din coada c (c[k]) este diferit de nodul de pornire.
CT

PAS12. Ct timp mai exist muchii care nu au fost incluse n ciclu (k-1<m) execut
PAS13. Se caut n coada c un nod i de plecare pentru ciclul c1, adic un nod
pentru care mai exist muchii incidente cu el care nu au fost parcurse
(grad[c[i]]>0).
DA

PAS14. Se iniializeaz cu acest nod ciclul c1 (c1[1]= c[i]) i se memoreaz


acest nod n variabila q.
PAS15. Se construiete un nou ciclu parcurgnd din algoritm pentru coada c1,
de la Pasul 5 pn la Pasul 11. Acest ciclu va avea p elemente.
DI

PAS16. Se concateneaz ciclul c1 cu ciclul c astfel: mai nti se deplaseaz elementele


din vectorul c, ncepnd din poziia q, cu p poziii spre dreapta, dup care se
intercaleaz, ntre poziia q i poziia q+p, elementele vectorului c1.
PAS17. Se afieaz elementele vectorului c.
RA

#include<fstream.h>
typedef stiva[20];
int n,a[20][20],vizitat[20],vf,k,m,g[20],p=1,c[20],c1[20];
stiva st;
TU

fstream f("graf e.txt",ios::in);


void citeste() {//se citete matricea de adiacen}
void init(int i) {vf=1; st[vf]=i; vizitat[i]=1;}
int este_vida() {return vf==0;}
I

void adaug(int i) {vf++; st[vf]=i; vizitat[i]=1;}


ED

void elimin() {vf--;}


Informatica 267

C
void prelucrare()
{int i=1; k=st[vf];
while (i<=n && (a[i][k]==0 || (a[i][k]==1 && vizitat[i]==1))) i++;

I
if (i==n+1) elimin(); else {p++; adaug(i);}}

OG
int conex()
{k=1; init(k);
while (!este_vida()) prelucrare();
return (p==n);}
void grad()

AG
{for(int i=1;i<=n;i++)
for (int j=1;j<=n;j++) if (a[i][j]==1) {g[i]++;m++;} m=m/2;}
int izolat()
{for(int i=1;i<=n;i++) if (g[i]==0) return 1;
return 0;}

ED
int grad_par()
{for(int i=1;i<=n;i++) if (g[i]%2==1) return 0;
return 1;}
void ciclu()

P
{int i,j,k=1,p,q,gasit;
c[1]=1;
do for(j=1,gasit=0;j<=n && !gasit;j++)
I
if (a[c[k]][j]==1)
{k=k+1; c[k]=j; a[c[k-1]][j]=0; a[j][c[k-1]]=0;
g[j]--; g[c[k-1]]--; gasit=1;}
while(c[k]!=1);

while (k-1<m)
{for(i=1,q=0;i<=k-1 && q==0;i++)
IC

if (g[c[i]]>0) {c1[1]=c[i]; q=i;}


p=1;
do for(j=1,gasit=0;j<=n && !gasit;j++)
CT

if (a[c1[p]][j]==1)
{p=p+1; c1[p]=j; a[c1[p-1]][j]=0; a[j][c1[p-1]]=0;
g[j]--; g[c1[p-1]]--; gasit=1;}
while(c1[p]!=c1[1]);
DA

for(j=k;j>=q;j--) c[j+p-1]=c[j];
for(j=1;j<=p-1;j++) c[j+q]=c1[j+1];
k=k+p-1;}}
void main()
{int eulerian; citeste(); grad();
DI

eulerian=!(izolat()) && grad par() && conex();


if (!eulerian) cout<<"graful nu este eulerian ";
else {cout<<"graful este eulerian"<<endl;
ciclu(); cout<<"ciclul eulerian este: ";
RA

for(int i=1;i<=m+1;i++) cout<<c[i]<<" ";}}


Observaie. Dac graful conine noduri izolate, algoritmii anteriori se pot aplica pe subgra-
ful conex care se obine dup nlturarea nodurilor izolate.
TU

1. Determinai complexitatea algoritmului de gsire a unui ciclu eulerian.


Tem 2. Scriei un program care citete din fiierul text graf_e1.txt matricea de
adiacen a unui graf eulerian i, de pe ultimul rnd, un ir de numere
care reprezint etichete de noduri i care verific dac irul de etichete reprezint un
I
ED

ciclu eulerian.
268 Implementarea structurilor de date

C
3. Scriei un program care citete din fiierul text graf_e2.txt matricea de adiacen a unui
graf neorientat care poate conine noduri izolate i care verific dac graful este un graf
eulerian, iar dac este graf eulerian, afieaz ciclul eulerian.

I
4. Scriei un program care citete din fiierul text graf_e3.txt matricea de adiacen unui graf

OG
neorientat conex i care verific dac graful este un graf eulerian, iar dac nu este, verific
dac poate fi fcut eulerian n acest caz, se precizeaz numrul de muchii care trebuie
adugate i care sunt aceste muchii.

2.7.10.4. Graful turneu

AG
Un graf orientat n care, ntre oricare dou noduri exist un singur arc
i numai unul, se numete graf turneu.
G
G
G333777 Exemplu Graful G37 din figura 43

ED
Observaii
1. Arcul dintre dou noduri poate avea oricare dintre cele dou orientri.
2. Graful turneu este un graf complet.

P
Teorema 20 Fig. 43
Orice graf turneu conine un drum elementar care trece prin toate nodurile grafului.
I
Demonstraie prin reducere la absurd. Presupunem c nu exist un drum elementar care trece
prin toate nodurile grafului. Considerm D(xi,xj) un drum de lungime maxim din graf i un nod
xD(xi,xj). Graful turneu fiind un graf complet, nseamn c nodul x este adiacent cu orice nod din

drumul D(xi,xj), inclusiv cu nodurile xi i xj. Pot s apar urmtoarele situaii:


Exist arcul [x,xi]. n acest caz, nseamn c exist drumul D(x,xj) mai lung dect drumul
IC

D(xi,xj), ceea ce contrazice ipoteza.


Exist arcul [xj,x]. n acest caz, nseamn c exist drumul D(xi,x) mai lung dect drumul
D(xi,xj), ceea ce contrazice ipoteza.
CT

Nu exist arcele [x,xi] i [xj,x]. Deoarece graful este complet, nseamn c exist arcele [xi,x]
i [x,xj]. Dac pentru orice nod xkD(xi,xj) exist arce numai cu sensul [xk,x], nseamn c
exist drumul D1(xi,xj) mai lung dect drumul D(xi,xj), deoarece conine n plus muchiile [xj-1,x]
i [x,xj]. Dac pentru orice nod xkD(xi,xj) exist arce numai cu sensul [x,xk], nseamn c
DA

exist drumul D2(xi,xj) mai lung dect drumul D(xi,xj), deoarece conine n plus muchiile [xi,x] i
[x,xi+1]. Dac exist dou noduri adiacente xk i xk+1, care aparin drumului D(xi,xj) pentru care
arcele incidente cu nodul x au sensuri contrare, se obine un drum D3(xi,xj) mai lung dect
drumul D(xi,xj), deoarece conine i arcele [xk,x] i [x,xk+1], ceea ce contrazice ipoteza.
Rezult c drumul D(xi,xj) conine toate nodurile din graf.
DI

Propoziia 10
Pentru orice graf turneu, exist un nod x, astfel nct toate nodurile yx sunt
accesibile din x pe un drum care conine un arc sau dou arce.
RA

Demonstraie prin reducere la absurd. Considerm nodul x cu gradul extern maxim p.


nseamn c ntre nodul x i celelalte p noduri exist un drum format dintr-un singur arc. S
presupunem c printre celelalte noduri exist un nod y care nu este accesibil din nodul x prin dou
TU

arce. nseamn c din acest nod pleac p arce ctre nodurile care sunt accesibile printr-un singur
arc din nodul x i un arc ctre nodul x. nseamn c nodul y are gradul p+1, mai mare dect gradul
nodului y, ceea ce contrazice ipoteza.

Propoziia 11
I
ED

+
Pentru orice nod xi dintr-un graf turneu cu n noduri, d ( xi) + d (xi) = n-1.
Informatica 269

C
Demonstraie. n graful turneu, fiecare nod xi fiind legat de celelalte n-1 noduri xj din graf printr-un
arc i numai unul, nseamn c orice nod xi este incident cu n-1 arce i suma dintre gradul intern i
gradul extern este egal cu n-1.

I
OG
Propoziia 12
n n
ntr-un graf turneu cu n noduri d ( x i ) d ( x i ) C n2 , unde xi este un nod din graf.
i 1 i 1

Demonstraie. n orice graf neorientat suma dintre gradele interne i gradele externe este egal cu

AG
numrul de arce m; iar numrul de arce ntr-un graf turneu se determin la fel ca i n cazul unui graf
complet neorientat Kn.
Propoziia 13

ED
n n
ntr-un graf turneu d ( x i ) 2 d ( x i ) 2 , unde xi este un nod din graf.
i 1 i 1
+ 2 + + 2 +
Demonstraie. d (xi) + d (xi)d (xi) = (n-1)d (xi) i d (xi) + d (xi)d (xi) = (n-1)d (xi). Scznd
+ 2 2 +

P
cele dou identiti, obinem d (xi) - d (xi) = (n-1)(d (xi) - d (xi)). Adunnd aceast identitate
pentru toate nodurile xi obinem:
n n n n
d ( x i ) 2 d ( x i ) 2 (n 1) ( d ( x i ) d ( x i )) (n 1) (m m ) 0
I
i 1 i 1 i 1 i 1

1. Demonstrai c un graf turneu este tare conex, dac i numai dac


Tem conine un ciclu elementar care trece prin toate nodurile grafului.

2. Scriei un program care citete din fiierul text graf_t.txt matricea de


adiacen a unui graf orientat i care verific dac graful este un graf turneu.
IC

2
3. Demonstrai c numrul de grafuri turneu care se pot construi cu n noduri este 2Cn .
CT

Scop: exemplificarea unei aplicaii n care soluia problemei este un graf turneu.
Enunul problemei. Pentru un concurs hipic s-au montat n obstacole. Pentru a parcurge
DA

traseul concursului, clreii pot ncepe cu orice obstacol, trebuie s treac peste toate
obstacolele, iar de la un obstacol la altul pot circula ntr-un singur sens, stabilit naintea
concursului. S se precizeze ce trasee poate urma un clre.
Obstacolele formeaz nodurile unui graf orientat, n care fiecare dou noduri sunt legate de
DI

un arc. Deoarece drumul dintre dou obstacole nu poate fi parcurs dect ntr-un singur
sens, nseamn c graful concursului este un graf turneu. A determina un traseu
pentru parcurgerea obstacolelor, nseamn a determina n graful turneu un drum
elementar care trece prin toate nodurile grafului.
RA

Algoritmul pentru parcurgerea grafului turneu


Pentru a determina drumul elementar care trece prin toate nodurile grafului se poate folosi
fie metoda backtracking, fie urmtorul algoritm, prin care se extrag cele n noduril ale
TU

drumului ntr-un vector D. n acest algoritm, se iniializeaz vectorul cu nodurile cu etiche-


tele 1 i 2 sau 2 i 1, n funcie de arcul care exist [1,2], respectiv [2,1], dup care se
insereaz n vectorul drumului i celelalte noduri, n funcie de arcele care exist n graf:
I

PAS1. Dac exist arcul [1,2], atunci D[1]=1 i D[2]=2; altfel, D[1]=2 i D[2]=1.
ED

PAS2. Se iniializeaz lungimea drumului, m, cu 2.


270 Implementarea structurilor de date

C
PAS3. Pentru nodurile cu eticheta i de la 3 pn la n execut:
PAS4. Dac exist arcul [i,1], atunci poziia de inserare k a nodului i este 1 i
se trece la Pasul 7; altfel, pentru a parcurge nodurile din drum se iniiali-

I
zeaz indicele j cu valoarea 1 i se trece la Pasul 5.

OG
PAS5. Ct timp nu s-a ajuns la captul vectorului D (indicele j nu are valoarea m) i
nu s-a gsit poziia de inserare a nodului i, execut:
PAS6. Dac exist arcul ntre nodul cu indicele j din drum i nodul i i
exist i arcul ntre nodul i i nodul cu indicele j+1 din drum, atunci

AG
poziia de inserare k este j+1; altfel, se trece la urmtorul nod din
drum prin incrementarea variabilei j i se revine la Pasul 6.
PAS7. Se deplaseaz elementele vectorului din poziia k (de inserare) spre
dreapta.
PAS8. Se insereaz nodul i n poziia k.

ED
PAS9. Se incrementeaz lungimea m a drumului D i revine la Pasul 3.
Implementarea algoritmului. Informaiile despre graful neorientat se gsesc n fiierul
graf_t.txt: pe prima linie numrul de noduri, apoi matricea de adiacen. Nodurile drumului

P
elementar vor fi generate n vectorul D. Se folosesc urmtoarele funcii: citeste()pentru
a citi matricea de adiacen din fiier, generare()pentru a genera vectorul D i
afiare()pentru a afia drumul elementar gsit. n funcia generare() se folosesc
I
urmtoarele variabile locale: i pentru eticheta nodului care se adaug la drum, j pentru
a cuta eticheta nodului dup care se insereaz n drum nodul cu eticheta i, k pentru
poziia n care se insereaz n vectorul drumului nodul cu eticheta i, m pentru lungimea

drumului la un moment dat (numrul de noduri adugate la drum) i gasit pentru a ti


dac s-a gsit poziia de inserare a nodului i n vector (este o variabil logic pentru
IC

fiecare nod i este iniializat cu valoarea False 0 , cu semnificaia c nu s-a gsit nc


poziia de inserare). Pentru testarea programului se folosete graful G37.
#include<fstream.h>
CT

int n,a[10][10],D[10];
fstream f("graf t.txt",ios::in);
void citeste() {//se citete matricea de adiacen }
void generare()
DA

{int i,j,k,m=2,gasit;
if (a[1][2]==1){D[1]=1; D[2]=2;}
else {D[1]=2; D[2]=1;}
for (i=3;i<=n;i++)
DI

{if (a[i][D[1]]==1) k=1;


else
{for (j=1,gasit=0;j<=n && !gasit;j++)
RA

if (a[D[j]][i]==1 && a[i][D[j+1]]==1) gasit=1;


k=j+1;}
for (j=m+1;j>k;j--) D[j]=D[j-1];
D[k]=i; m++;}}
TU

void afisare()
{for (int i=1;i<=n;i++) cout<<D[i]<<" ";}
void main() {citeste(); generare(); afisare();}

Dac graful G37 din figura 43 este graful unui concurs hipic, determinai
I

Tem
ED

traseul pe care trebuie s-l parcurg un clre.


Informatica 271

C
2.7.10.5. Aplicaii practice
1. Graful migraiei psrilor cltoare este un graf bipartit, cele dou mulimi fiind formate
din locaiile din zona rece i locaiile din zona cald. Verificai dac acest graf este un

I
OG
graf bipartit complet. n caz afirmativ, ce concluzie tragei despre migraia speciei de
psri studiate?
2. Considerai c graful din figura 39 reprezint graful oraelor prin care trebuie s treac
voiajorul comercial. Adugai fiecrei muchii distana n kilometri ntre orae. Scriei un
program care s rezolve problema voiajorului comercial care s gseasc traseul cu

AG
costul minim. Indicaie. Fiecare ciclu hamiltonian gsit (nodurile depuse n stiv), va fi
memorat ntr-o matrice cu n coloane, numrul de linii fiind egal cu numrul de cicluri
gsite. Alegei din ciclurile gsite pe cel cu costul minim.
3. Jocul icosian a fost inventat de William Hamilton n anul 1857. Era un dodecaedru regu-

ED
lat confecionat din lemn (un poliedru cu 12 fee sub form de pentagoane regulate) i
care avea n fiecare vrf cte un cui care era marcat cu numele unui ora (figura 44). Cu
ajutorul unei sfori, care trecea prin fiecare cui o singur dat, trebuia s
se gseasc un traseu care s parcurg toate oraele (s parcurg

P
toate muchiile dodecaedrului) cu revenire la oraul de plecare. Scriei
un program care s gseasc soluii pentru
I
acest joc, n trei variante: a) se cunoate ora-
ul de plecare; b) se cunosc primele dou
Fig. 44 orae prin care trebuie s treac traseul; c) se
cunosc primele trei orae prin care trebuie s

treac traseul. Etichetele oraelor iniiale se comunic de la


tastatur. Indicaie. Dodecaedrul poate fi reprezentat cu ajutorul
IC

unui graf neorientat, n care trebuie s se gseasc un circuit


hamiltonian. Nodurile sunt cele 20 de vrfuri ale poliedrului
(figura 45). Fig. 45
CT

4. Jocul de ah. S se gseasc un traseu de acoperire a tablei


de ah cu una dintre piese (piesa trebuie s treac o singur dat prin fiecare dintre
cele 64 de ptrate ale tablei de ah i s revin la punctul de plecare). Piesa poate fi:
DA

a. calul se deplaseaz n form de L (problema a fost studiat de Euler n anul 1759);


b. dama se deplaseaz n oricare dintre ptratele adiacente;
c. nebunul se deplaseaz numai n ptratele aflate pe diagonala ptratului n care se
gsete;
DI

d. tura se deplaseaz numai n ptratele aflate pe vertical sau pe orizontal fa de


ptratul n care se gsete.
Indicaie. Tabla de ah poate fi reprezentat cu ajutorul unui graf neorientat n care tre-
buie s se gseasc un circuit hamiltonian. Nodurile sunt cele 64 de ptrate ale tablei
RA

de ah, iar ntre dou noduri exist muchie numai dac piesa poate s se deplaseze
ntre cele dou ptrate, conform regulilor jocului.
5. Scriei un program care s demonstreze c problema podurilor din oraul Knigs-
berg nu are soluii.
TU

6. O persoan dorete s viziteze mai multe cabane, legate prin trasee turistice, astfel
nct s parcurg fiecare traseu o singur dat i s se rentoarc la locul de plecare.
Legtura direct dintre dou cabane este caracterizat prin timpul necesar parcurgerii
I

traseului de munte (costul asociat fiecrei muchii). Scriei un program care s gseasc
ED

traseul turistic i care s determine timpul necesar parcurgerii lui.


272 Implementarea structurilor de date

C
7. Masa rotund a regelui Arthur. Scriei un program care s afieze soluia aranjrii la
masa rotund a regelui Arthur a celor 2n cavaleri, tiind c fiecare dintre cavaleri are n-1
dumani i c la mas nici un cavaler nu trebuie s stea lng dumanul lui. Indicaie.

I
Relaiile dintre cavaleri pot fi reprezentate cu ajutorul unui graf neorientat n care nodu-

OG
rile sunt cavalerii, iar muchiile leag numai cavaleri care nu sunt dumani. Demonstrai
c acest graf este un graf eulerian i gsii un ciclu eulerian.
8. Scriei un program care s gseasc soluia de a desena figura 46
fr a ridica creionul de pe hrtie i fr a trece cu creionul pe o

AG
latur deja desenat. Indicaie. Figura geometric poate fi repre-
zentat printr-un graf neorientat, n care nodurile sunt vrfurile
figurii, iar muchiile, laturile. Problema const n a gsi n acest graf,
Fig. 46
care nu este eulerin, un lan eulerian.

ED
9. O competiie sportiv se desfoar prin meciuri directe ntre doi participani. Nu exist
meciuri nule i nici meciuri eliminatorii (trebuie s existe cte un meci ntre fiecare doi
participani). Scriei un program care s afieze o soluie de organizare a competiie
sportive (ordinea de desfurare a meciurilor). Indicaie. Deoarece doi participani nu

P
joac mpreun dect un singur meci, meciul va fi definit prin relaia nesimetric
sportivul x joac cu sportivul y (adic, dac sportivul x joac cu sportivul y, atunci
sportivul y nu mai joac cu sportivul x). Graful campionatului este un graf orientat, n
I
care nodurile reprezint sportivii, iar muchiile, meciurile. Prin modul de organizare a
competiiei, el este un graf turneu.

Adevrat sau Fals:


IC

1. Nodul x este incident cu nodul y dac formeaz mpreun o muchie.


2. Gradul intern al unui nod dintr-un graf orientat este egal cu numrul de arce care ies
CT

din nod.
3. ntr-un graf orientat, mulimea predecesorilor unui nod este format din mulimea
nodurilor de la care ajung arce care intr n nod.
4. ntr-un graf orientat, suma gradelor interne i a gradelor externe ale tuturor nodurilor
DA

este egal cu dublul numrului de muchii.


5. Matricea de inciden a unui graf orientat este o matrice binar.
6. ntr-un graf orientat, numrul de vecini ai unui nod este egal cu suma dintre gradul
intern i gradul extern ale nodului.
DI

7. Lista de adiacen a unui graf orientat este format din listele vecinilor fiecrui nod
din graf.
8. Graful nul conine numai noduri izolate.
9. Un graf neorientat cu 5 noduri poate conine maxim 10 muchii.
RA

10. Un graf orientat cu 4 noduri poate conine maxim 12 arce.


11. Un subgraf se obine prin eliminarea unor muchii (arce) din graf.
12. ntr-un lan elementar fiecare muchie se parcurge o singur dat.
13. ntr-un ciclu elementar o muchie poate fi parcurs de mai multe ori.
TU

14. Un drum este un lan ntr-un graf orientat.


15. n matricea drumurilor elementul a[i][j] are valoarea 1 numai dac exist un drum de
la nodul i la nodul j i un drum de la nodul j la nodul i.
I

16. O component conex a unui graf este un graf parial conex al acestuia.
ED

17. Prin parcurgerea n lime a unui graf se pot determina componentele conexe ale grafului.
Informatica 273

C
18. Un graf conex cu n noduri i n-1 muchii conine cel puin un ciclu.
19. Un graf tare conex este un graf orientat conex.
20. Un graf bipartit complet este un graf complet care este bipartit.

I
21. Cu patru noduri se pot genera 14 grafuri bipartite complete.

OG
22. Un graf hamiltonian poate conine noduri izolate.
23. Dac ntr-un graf cu n noduri (n3) gradul fiecrui nod este mai mic dect n/2, atunci
graful nu este hamiltonian.
24. Lanul eulerian este un lan elementar care parcurge toate muchiile grafului.

AG
25. Un graf eulerian poate conine p componente conexe, cu condiia ca p-1 componente
conexe s fie formate numai din noduri izolate.
26. ntr-un graf turneu cu n noduri, suma dintre gradul intern i gradul extern ale oricrui
nod este n.

ED
27. Numrul de arce dintr-un graf turneu cu n noduri este n(n-1)/2.
Alegei:
1. Determinai numrul total de grafuri neorientate distincte cu 3 noduri. Dou grafuri se

P
consider distincte dac matricea lor de adiacen difer.
a. 4 b. 7 c. 64 d. 8
(Bacalaureat Sesiunea special 2003)
I
2. Numrul de grafuri orientate care se pot construi cu 3 noduri este:
a. 8 b. 9 c. 64 d. 16
3. Numrul maxim de arce ntr-un graf orientat cu 5 noduri este:

a. 5 b. 10 c. 20 d. 25
Urmtorii 12 itemi se refer la graful neorientat cu 8 noduri i avnd muchiile [1,2], [1,3],
IC

[1,4], [1,5], [2,3], [3,4], [3,7], [4,7], [4,5].


4. Numrul de noduri care au gradul maxim este:
a. 1 b. 2 c. 4 d. 3
CT

5. Numrul de noduri izolate este:


a. 1 b. 2 c. 0 d. 3
6. Numrul de elemente de 0 din matricea de adiacen este:
a. 9 b. 18 c. 20 d. 46
DA

7. Numrul de elemente de 0 din matricea de inciden este:


a. 18 b. 9 c. 36 d. 54
8. Suma elementelor de pe linia 1 din matricea de inciden este:
a. 8 b. 4 c. 2 d. 6
DI

9. Numrul de cicluri elementare de lungime 4 este:


a. 4 b. 3 c. 6 d. 5
10.Numrul de lanuri elementare de lungime 4 este:
a. 16 b. 8 c. 10 d. 22
RA

11.Numrul de lanuri elementare ntre nodul 1 i nodul 7 este:


a. 6 b. 3 c. 4 d. 8
12.Numrul de subgrafuri cu 3 noduri care se pot obine din graf este:
a. 10 b. 3 c. 20 d. 56
TU

13.Numrul de grafuri pariale cu 7 muchii care se pot obine din graf este:
a. 72 b. 18 c. 36 d. 9
14.Numrul minim de muchii care se pot elimina din componenta conex {1,2,3,4,5,7} a
I

grafului pentru a se obine un graf parial neconex este:


ED

a. 1 b. 4 c. 3 d. 2
274 Implementarea structurilor de date

C
15. Numrul maxim de muchii care se pot elimina din componenta conex {1,2,3,4,5,7} a
grafului pentru a se obine un graf parial conex este:
a. 5 b. 4 c. 3 d. 2

I
Urmtorii 11 itemi se refer la graful orientat cu 6 noduri i cu arcele [1,2], [1,3], [1,4],

OG
[1,5], [2,3], [3,1], [3,4], [3,6], [4,1], [4,5], [4,6], [6,4].
16.Numrul de noduri care au gradul intern egal cu gradul extern este:
a. 1 b. 2 c. 4 d. 3
17.Numrul de elemente de 0 din matricea de adiacen este:

AG
a. 9 b. 18 c. 26 d. 24
18.Numrul de elemente de 1 din matricea de inciden este:
a. 22 b. 11 c. 6 d. 8
19.Suma elementelor de pe linia 4 din matricea de inciden este:

ED
a. 8 b. 4 c. 0 d. 6
20.Suma gradelor externe i a gradelor interne ale tuturor nodurilor este:
a. 12 b. 24 c. 20 d. 14
21.Numrul de cicluri elementare de lungime 4 este:

P
a. 4 b. 3 c. 0 d. 6
22.Numrul de lanuri elementare de lungime 4 este:
a. 16 b. 8 c. 10 d. 22
I
23.Numrul de circuite elementare de lungime 4 este:
a. 2 b. 4 c. 3 d. 5
24.Numrul de lanuri elementare ntre nodul 1 i nodul 6 este:
a. 6 b. 3 c. 4 d. 8

25.Numrul de drumuri elementare ntre nodul 1 i nodul 6 este:


IC

a. 6 b. 3 c. 4 d. 5
26.Numrul de componente tare conexe este:
a. 1 b. 3 c. 2 d. 4
CT

27.Se consider graful neorientat dat prin matricea de adiacen alturat. n 0 1 0 1


graf, nodurile sunt numerotate de la 1 la 4, corespunztor liniilor tabloului. 1 0 1 0
S se determine cte perechi de noduri neadiacente exist n graf. Se con- 0 1 0 1
sider perechile neordonate (perechea 12 este aceeai cu perechea 21). 1 0 1 0
DA

a. 1 b. 2 c. 3 d. 4
(Bacalaureat Sesiunea august 2003)
28.Se consider graful neorientat din figura alturat. S se determine
care dintre urmtoarele liste reprezint lista de adiacen a nodului 3:
DI

a. 1 2 4 b. 3 1 2 4 c. 2 4 d. 1 3 4
(Bacalaureat Sesiunea iunie-iulie 2003) 0 1 0 1 0
29. Se consider un graf orientat avnd matricea de adiacen alturat. 0 0 0 0 1
0 1 0 0 0
RA

Stabilii care dintre nodurile grafului au gradul intern egal cu gradul extern.
0 1 1 0 0
a. 3 b. 1 c. 0 d. 2 0 1 0 1 0
(Bacalaureat Simulare 2003)
30.ntr-un graf neorientat cu n noduri numrul maxim de muchii ce pot exista este:
2
TU

a. n(n+1)/2 b. n(n-1)/2 c. n(n-1) d. n


(Bacalaureat Sesiunea iunie-iulie 2003)
31.Numrul maxim de muchii ntr-un graf neorientat cu 8 noduri care nu conine niciun
ciclu este:
I

a. 4 b. 8 c. 27 d. 7
ED

(Bacalaureat Simulare 2005)


Informatica 275

C
32.tiind c un graf neorientat fr noduri izolate are 7 muchii i 8 noduri, stabilii
numrul maxim de componente conexe din care poate fi format acesta.
a. 1 b. 2 c. 3 d. 4

I
(Bacalaureat Sesiunea august 2005)

OG
33.Se consider graful din figura alturat. Determinai matricea de
adiacen corespunztoare:
a) 0 1 1 1 b) 0 1 0 1 c) 1 1 0 1 d) 0 1 0 1
1 0 0 0 1 0 1 0 1 1 0 1 1 0 0 1

AG
1 0 1 0 0 1 0 1 0 0 1 1 0 0 0 1
1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 0

(Bacalaureat Simulare 2003)


34.Se consider graful neorientat din figura alturat. S se determine

ED
eticheta nodului care are lista de adiacen 2 3 5.
a. 5 b. 4 c. 3 d. 1
(Bacalaureat Sesiunea iunie-iulie 2003)
35.Se consider un graf orientat dat prin listele de adiacen: 1) 2 4 2) 4 3) 1 5 4) 4 2

P
3 5) 2 3 4. Stabilii numrul de noduri care au gradul intern egal cu gradul extern.
a. 3 b. 1 c. 3 d. 2
I
(Bacalaureat Sesiunea iunie-iulie 2003)
36.Numrul minim de noduri dintr-un graf neorientat cu 12 muchii, fr noduri izolate, graf
format din exact 3 componente conexe:
a. 7 b. 8 c. 9 d. 10

(Bacalaureat Sesiunea special 2005)


37.Numrul minim de componente conexe ale unui graf neorientat cu 9 muchii i 12
IC

noduri este::
a. 2 b. 3 c. 4 d. 5
(Bacalaureat Sesiunea iunie-iulie 2005)
CT

38.Care este numrul minim de muchii care pot fi plasate ntr-un graf neorientat cu 53 de
noduri, astfel nct s nu existe nici un nod izolat?
a. 27 b. 26 c. 53 d. 52
DA

39.Se consider un graf neorientat G cu 8 noduri i 16 muchii. Numrul de noduri izolate


din G este:
a. exact 1 b. exact 0 c. cel mult 1 d. cel mult 2
(Bacalaureat Sesiunea iunie-iulie 2003)
DI

40.Stabilii care dintre urmtoarele matrice de adiacen corespunde grafului


din figura alturat.
a) 0 1 1 0 b) 0 1 0 1 0 c) 0 0 0 1 1 d) 0 0 0 1
1 0 1 0 1 0 0 1 0 0 0 0 0 1 0 0 1 1
RA

1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 1
0 0 1 0 1 1 0 0 0 1 0 0 0 1 1 1 1 0
0 0 0 1 0 1 1 0 1 0
(Bacalaureat Sesiunea august 2003)
TU

41.ntr-un graf neorientat cu 20 de noduri numerotate de la 1 la 20 exist muchii numai


ntre perechile de noduri i i j cu proprietatea abs(i-j)>1. Numrul de valori egale cu 1
din matricea de adiacen corespunztoare grafului este:
a. 190 b. 362 c. 340 d. 171
I
ED

(Bacalaureat Sesiunea iunie-iulie 2003)


276 Implementarea structurilor de date

C
42.Care este matricea de adiacen a unui graf neorientat cu 4 noduri, 2 muchii i cel
puin un nod izolat?
a) 0 1 1 0 b) 0 0 1 c) 0 1 0 1 d) 0 0 0 0

I
1 0 0 0 0 0 1 1 0 0 0 0 0 1 1

OG
1 0 1 0 1 1 0 0 0 0 0 0 1 0 1
0 0 0 0 1 0 0 0 0 1 1 0
(Bacalaureat Simulare 2004)
43.Se consider un graf orientat cu 6 noduri etichetate cu numere de la 1 la 6 i 6 arce

AG
astfel nct exist un arc de la fiecare nod cu eticheta i ctre un nod cu eticheta i2
dac exist un astfel de nod sau ctre nodul cu eticheta i-1 n caz contrar. Care este
lungimea maxim a unui drum n graf?
a. 4 b. 3 c. d. 2

ED
(Bacalaureat Simulare 2003)
44.Stabilii care dintre urmtoarele variante este matricea de adia-
cen a unui subgraf al grafului din figura alturat:
a) 0 0 0 b) 0 1 0 c) 0 1 1 d) 0 1 1

P
0 0 0 1 0 1 1 0 1 1 0 1
0 0 0 0 1 1 1 0 1 1 1 0
I
(Bacalaureat Sesiunea special 2003)
45.n matricea de adiacen asociat grafului orientat din figura alturat
nodurile sunt numerotate de la 1 la 4 corespunztor liniilor matricei.

Numrul de elemente egale cu 1 aflate deasupra diagonalei principale


depete numrul de elemente egale cu 1 aflate sub diagonala
IC

principal cu
a. 2 b. 0 c. 3 d. 1
(Bacalaureat Sesiunea iunie-iulie 2004)
CT

46.Se consider un graf orientat cu nodurile numerotate cu 1, 2, 3, 4, 5, 0 0 0 0 0


corespunztor liniilor matricei de adiacen alturate. Stabilii dac 0 0 0 1 1
nodurile 1 i 3: 0 0 0 0 0
a. aparin aceleiai componente conexe b. sunt noduri izolate 0 1 0 0 1
DA

c. sunt conectate printr-un lan d. sunt noduri adiacente 0 1 0 1 0


(Bacalaureat Simulare 2003)
47.Care dintre urmtoarele secvene de noduri reprezint un lan n graful 0 1 0 1 0
1 0 0 1 0
neorientat dat prin matricea de adiacen alturat tiind c nodurile
DI

0 0 0 1 1
sunt numerotate de la 1 la 5 corespunztor liniilor tabloului? 1 1 1 0 1
a. 3 4 1 2 5 b. 1 5 3 4 2 4 c. 4 1 2 4 5 d. 2 1 3 4 0 0 1 1 0
(Bacalaureat Sesiunea iunie-iulie 2004)
48.Se consider graful neorientat dat prin matricea de adiacen alturat. n 0 1 0 1
RA

graf, nodurile sunt numerotate de la 1 la 4, corespunztor liniilor tabloului. 1 0 0 1


S se determine lungimea maxim a unui lan ce unete nodurile 1 i 3: 0 0 0 1
a. 1 b. 2 c. 3 d. 4 1 1 1 0
(Bacalaureat Sesiunea iunie-iulie 2003)
TU

49.Care dintre urmtoarele secvene reprezint un drum n graful orientat dat 0 1 0 0


prin matricea de adiacen alturat, tiind c nodurile sunt numerotate de 1 0 0 0
la 1 la 4 corespunztor liniilor i coloanelor tabloului? 1 1 0 1
0 0 1 0
I

a. 3 4 3 2 4 b. 3 1 2 3 c. 2 1 3 4 d. 4 3 1 2
ED

(Bacalaureat Sesiunea special 2004)


Informatica 277

C
50.Cel mai lung drum elementar n graful orientat din figura alturat are
lungimea
a. 2 b. 4 c. d. 1

I
(Bacalaureat Sesiunea iunie-iulie 2004)

OG
51.Se consider un graf neorientat cu 7 noduri i 3 muchii. Numrul de
componente conexe din care poate fi format graful este:
a. exact 4 b. 4 sau 5 c. 3 sau 4 d. cel puin 5
(Bacalaureat Simulare 2003)

AG
52.Dac ntr-un graf neorientat conex cu n noduri, lista de adiacen a fiecrui nod este
format din exact dou elemente, atunci n graful respectiv exist:
a. cel puin n/2 cicluri b. exact n/2 cicluri
c. exact un ciclu d. cel puin dou cicluri
(Bacalaureat Sesiunea special 2003)

ED
53.Numrul minim de muchii ce se pot alege pentru a fi eliminate din graful
neorientat din figura alturat astfel nct acesta s devin neconex este:
a. 2 b. 4 c. 3 d. 1
(Bacalaureat Sesiunea iunie-iulie 2003)

P
54.Numrul de grafuri conexe aciclice care se pot obine cu 4 noduri este:
a. 2 b. 4 c. 28 d. 24
I
55. Se consider un graf orientat tare conex. Stabilii numrul circuitelor care conin toate
nodurile grafului:
a. exact unul b. cel mult unul c. nici unul d. cel puin unul
(Bacalaureat Sesiunea iunie-iulie 2003)

56.Gradul maxim al unui nod ce se poate obine ntr-un graf neorientat conex cu n noduri
i n-1 muchii este (s-a notat cu [n/2] ctul mpririi ntregi a lui n la 2):
IC

a. n-1 b. [n/2] c. n d. 2
(Bacalaureat Sesiunea iunie-iulie 2003) 0 0 1 0 0
0 0 0 1 1
57.Se consider graful neorientat avnd nodurile notate cu 1, 2, 3, 4, 5
CT

1 0 0 0 0
corespunztor liniilor matricei de adiacen alturate. Stabilii care dintre 0 1 0 0 1
urmtoarele propoziii este adevrat. 0 1 0 1 0
a. graful este conex b. orice nou muchie s-ar aduga graful devine conex
DA

c. graful este aciclic d. orice muchie s-ar elimina graful devine aciclic
(Bacalaureat Simulare 2003)
58.n graful neorientat dat prin matricea de adiacen alturat numrul de 0 0 1 0
componente conexe este: 0 0 0 0
DI

a. 0 b. 2 c. 3 d. 1 1 0 0 0
(Bacalaureat Sesiunea iunie-iulie 2003) 0 0 0 0
59. Stabilii care dintre urmtoarele matrice de adiacen corespunde unui graf conex aciclic:
RA

a) 0 1 1 0 b) 0 1 0 c) 0 1 0 1 d) 0 0 1 0
1 0 1 0 1 0 1 1 0 1 0 0 0 0 1
1 1 0 1 0 1 0 0 1 0 1 1 0 0 0
0 0 1 0 1 0 1 0 0 1 0 0
TU

(Bacalaureat Sesiunea august 2003)


60. Cte grafuri hamiltoniene se pot crea cu 4 noduri?
a. 1 b. 2 c. 4 d. 5
I

61. Cte grafuri hamiltoniene se pot crea cu 4 noduri i 5 muchii?


ED

a. 1 b. 2 c. 4 d. 5
278 Implementarea structurilor de date

C
62. Cte grafuri euleriene se pot crea cu 4 noduri?
a. 1 b. 2 c. 4 d. 5
63.Numrul de cicluri hamiltoniene dintr-un graf complet cu 4 noduri este:

I
a. 1 b. 3 c. 4 d. 6

OG
64.Determinai numrul total de grafuri neorientate conexe cu 3 noduri, dou grafuri fiind
considerate distincte dac i numai dac matricele lor de adiacen difer prin cel
puin un element.
a. 7 b. 8 c. 4 d. 2

AG
(Bacalaureat Sesiunea august 2003)
65.Care dintre urmtoarele figuri reprezint un graf neorientat conex?
a. b. c. d.

ED
(Bacalaureat Sesiunea august 2004)
66.Considernd un graf neorientat avnd nodurile 1,2,3,4,5, 0 1 1 0 0 0 0 0 0
6,7,8,9 corespunztor liniilor matricei de adiacen alturate, 1 0 1 0 0 1 0 0 0

P
stabilii care dintre urmtoarele propoziii este adevrat: 1 1 0 1 1 0 0 0 0
a. este un graf bipartit b. este un graf conex 0 0 1 0 1 0 0 0 0
c. este un graf eulerian d. este un graf hamiltonian 0 0 1 1 0 0 0 0 0
I
67.Cte muchii are graful bipartit complet G=(X,U), cu 11 noduri 0 1 0 0 0 0 1 1 0
i cu mulimea nodurilor A i B definite astfel: AB=X, 0 0 0 0 0 1 0 1 0
AB= i card(A)=4? 0 0 0 0 0 1 1 0 1
0 0 0 0 0 0 0 1 0

a. 4 b. 10 c. 16 d. 28
68. Care dintre urmtoarele afirmaii sunt adevrate?
IC

a. un graf hamiltonian este un graf care conine un ciclu elementar care trece prin
toate nodurile;
b. un graf eulerian este un graf care conine un ciclu simplu care trece prin toate
CT

muchiile;
c. un graf fr noduri izolate este eulerian dac este conex i gradul fiecrui nod
este par;
d. un graf complet este hamiltonian.
DA

69. Stabilii care dintre urmtoarele proprieti ale unui graf turneu sunt adevrate:
a. graful turneu trebuie s fie un graf hamiltonian;
b. graful turneu trebuie s fie un graf eulerian;
c. graful turneu este un graf orientat n care, ntre oricare dou noduri, exist un arc
DI

i numai unul, care le leag;


d. graful turneu este un graf conex ciclic.
70.Stabilii cu care dintre urmtoarele valori este egal suma elementelor matricei de
RA

adiacen a grafului turneu:


a. n(n-1) b. n(n-1)/2 c. n d. n-1
71. Stabilii care dintre urmtoarele proprieti ale matricei de adiacen a grafului turneu
este adevrat:
TU

a. suma elementelor din linia i i coloana jeste egal cu n;


b. suma elementelor din linia i i coloana j este egal cu n-1;
c. suma elementelor din linia i i coloana j este egal cu n-1, oricare ar fi i i j;
d. suma elementelor din linia i i coloana j este egal cu n, oricare ar fi i i j.
I
ED
Informatica 279

C
72. Stabilii care dintre urmtoarele egaliti ntre elementele matricei de adiacen a
grafului turneu sunt adevrate:
a. a[i][j] =1- a[j][i], oricare ar fi i i j; b. a[i][j]+a[j][i]=1, oricare ar fi ij;

I
c. a[i][j]+a[j][i]=1, oricare ar fi i i j; d. a[i][j] =1- a[j][i], oricare ar fi ij;

OG
73. Un graf orientat avnd nodurile 1,2,3,4,5 corespunztor liniilor matricei 0 0 1 0 1
de adiacen alturate reprezint un graf turneu pentru un concurs 1 0 1 0 0
hipic, definit la Studiul de caz, n care nodurile sunt obstacolele. 0 0 0 1 1
Traseul pe care poate s-l urmeze un clre, ncepnd cu obstacolul 1 1 0 0 0

AG
1, este: 0 1 0 1 0
a. 1,3,2,4,5 b. 1,3,4,2,3,5 c. 1,3,5,4,2 d. 1,3,4,5,2
74. Se consider graful turneu care corespunde matricei de adicen de la problema
anterioar. Un clre care ncepe cu obstacolul 1 poate alege din n variante de

ED
trasee, unde n are valoarea:
a. 2 b. 3 c. 4 d. 5
75. Considerm un graf neorientat avnd nodurile 1,2,3,4,5 corespunztor 0 1 0 0 1
1 0 1 1 1

P
liniilor matricei de adiacen alturate. Cte muchii trebuie adugate
pentru ca graful s fie un graf eulerian i hamiltonian? 0 1 0 1 1
a. 1 b. 2 c. 3 d. imposibil 0 1 1 0 1
1 1 1 1 0
I
Miniproiecte:
1. Reeaua de strzi a unui ora este format din intersecii i strzi pe care se poate circula
n ambele sensuri sau ntr-un singur sens. Fiecare strad are o lungime msurat n metri.

Dou automobile pleac la acelai moment, unul din intersecia A i altul din intersecia B,
i trebuie s ajung fiecare n intersecia C, respectiv intersecia D. Cele dou automobile
IC

merg cu viteza medie v1, respectiv v2. Ambii automobiliti aleg traseul ntre cele dou
intersecii astfel nct distana parcurs s fie minim. Informaiile despre reeaua de strzi
(numrul de intersecii, traficul auto ntre intersecii i lungimea fiecrei strzi) se citesc
CT

dintr-un fiier text. Se citesc de la tastatur etichetele celor patru intersecii i vitezele
automobilelor. Scriei o aplicaie care s furnizeze urmtoarele informaii:
a. Care dintre automobiliti ajunge mai repede la destinaie?
DA

b. Dac exist intersecii prin care trec ambii automobiliti, s se afieze aceste intersecii.
c. Dac automobilitii se ntlnesc ntr-o intersecie, s se precizeze aceast intersecie.
d. Dac, dup ce au ajuns la destinaie, cei doi automobiliti pornesc unul ctre cellalt,
care este cel mai scurt drum pe care trebuie s mearg, i n ce intersecie i propun
DI

s se ntlneasc, astfel nct timpul de ateptare n intersecie a automobilistului care


ajunge primul s fie minim?
2. O reea de calculatoare are n servere. La calculatoarele server pot fi conectate mai
multe calculatoare client. Dou calculatoare server pot comunica prin legturi directe
RA

sau prin intermediul altor servere. Informaiile despre topologia reelei (numrul de
severe i legturile directe dintre servere) se citesc dintr-un fiier text. Scriei o aplicaie
care s furnizeze urmtoarele informaii:
a. Care este drumul cel mai scurt pe care un mesaj transmis de un client al serverului x
TU

s ajung la un client al serverului y (etichetele severelor se citesc de la tastatur)?


b. S se precizeze care sunt calculatoarele server care, dac se defecteaz, fac ca reea-
ua s nu mai fie funcional (unele severe din reea nu mai pot comunica ntre ele).
c. S se precizeze care este serverul cel mai solicitat. Serverul cel mai solicitat este
I
ED

serverul prin care este posibil s treac, la un moment dat, cele mai multe mesaje
(serverul prin care trec cele mai multe lanuri).
280 Implementarea structurilor de date

C
d. S se reproiecteze reeaua prin adugarea unui numr minim de legturi directe
ntre servere, astfel nct oricare dintre servere s-ar defecta, reeaua s rmn
funcional (cu excepia clienilor serverului defect, restul clienilor trebuie s aib

I
acces la resursele reelei).

OG
3. ntr-o fabric se realizeaz un tip de produs care este format din mai mullte subansam-
bluri. Fiecare subansamblu este produs de o secie. Un subansamblu poate fi, la rndul
su, compus din alte subansambluri. Exist o secie n care se asambleaz produsul
final i secii care, pentru a produce propriul subansamblu, nu au nevoie de subansam-

AG
bluri produse n seciile fabricii. Seciile fabricii i relaiile dintre secii pot fi reprezentate
printr-un graf orientat, astfel: seciile sunt nodurile grafului, iar arcul [x,y] nseamn c
subansamblul produs de secia x este folosit de secia y. Desenai o organigram ipote-
tic a seciilor fabricii. Informaiile despre organigrama fabricii se citesc dintr-un fiier

ED
text: de pe prima linie n numrul de secii i m numrul de arce ale grafului, de pe
urmtorul rnd un ir de n numere ntregi care reprezint stocul de subansambluri reali-
zate n fiecare secie, de pe urmtorul rnd un ir de n numere ntregi care reprezint
numrul de angajai din fiecare secie i apoi, de pe urmtoarele m rnduri, cte trei

P
valori numerice ntregi care reprezint etichetele nodurilor terminale ale unui arc (x i y)
i numrul de subansambluri pe care trebuie s le furnizeze secia x seciei y, pentru a
se putea obine o unitate din produsul final. Scriei o aplicaie care s furnizeze urmtoa-
I
rele informaii:
a. S verifice dac se poate realiza o unitate din produsul final folosind subansamblurile
care exist pe stoc n seciile fabricii. Dac nu se poate realiza o unitate din produsul

final, s se precizeze seciile care sunt vinovate c nu au produs suficiente subansam-


bluri.
IC

b. n fabric, se nchid dou dintre seciile care realizeaz subansambluri (subansamblu-


rile se vor cumpra de la ali productori). Etichetele nodurilor corespunztoare acestor
secii se citesc de la tastatur. Verificai dac, prin nchiderea acestor secii, alte secii
CT

ale fabricii nu devin inutile. O secie devine inutil atunci cnd prin nchiderea unei alte
secii, subansamblurile produse de ea nu mai sunt necesare. Dac apar secii inutile,
n urma nchiderii celor dou secii iniiale, afiai eticheta corespunztoare seciei i
nchidei i aceste secii. Reorganizai fabrica prin eliminare de secii pn cnd nu
DA

vor mai exista secii inutile. Afiai numrul de angajai care trebuie disponibilizai prin
nchiderea seciilor. Afiai organigrama fabricii dup reorganizare, prin etichetele
seciilor care au mai rmas, i arcele dintre acestea. (Indicaie. Generai subgraful
iniial, prin eliminarea nodurilor corespunztoare seciilor care se nchid. Generai apoi
DI

subgrafuri ale ultimului subgraf obinut prin eliminarea nodurilor care au gradul extern
egal cu 0. Subgraful final obinut va corespunde noii organigrame. Cnd eliminai un
nod, adunai la numrul angajailor disponibilizai angajaii din secia corespunztoare
nodului).
RA

4. Pentru realizarea unui proiect trebuie executate mai multe activiti (analiza, elaborarea
modulelor de program, testarea, elaborarea documentaiei etc.). Unele activiti sunt
condiionate de execuia altora (de exemplu, nu se poate scrie un modul de program fr
TU

s se fi fcut analiza aplicaiei), alte activiti se pot desfura independent unele de altele
(se pot scrie module de program sau se pot testa unele dintre module, independent unele
de altele). Fiecare activitate are un timp maxim de execuie. S se reprezinte sub forma
unui graf orientat activitile de realizare a fiecruia dintre miniproiectele anterioare i s
I

se determine timpul maxim de execuie al fiecruia dintre ele.


ED
Informatic 281

C
2.8. Arborele
2.8.1. Arborele liber

I
OG
2.8.1.1. Definiia arborelui liber
Se numete arbore liber A un graf neorientat conex i fr cicluri.
Observaie. De obicei se omite adjectivul liber, referirea la un graf conex aciclic fcndu-se

AG
numai cu numele arbore.
Se numete subarbore al arborelui A=(X,U), orice arbore S=(Y,V)
care are proprietatea: YX i VU.
Exemplu figura 47. Graful G38 cu 8 noduri este un arbore (un graf neorientat conex i G G
G333888

ED
aciclic), iar graful G39 este un subarbore al acestuia.
G
G
G333999
G38 G39

Fig. 47 P
I
2.8.1.2. Proprietile arborilor liberi
Teorema 21

Urmtoarele definiii sunt echivalente pentru un graf G cu n noduri i m muchii:


(1) G este un arbore.
IC

(2) G este un graf aciclic cu n-1 muchii.


(3) G este un graf conex cu n-1 muchii.
(4) G este un graf fr cicluri maximal (dac n graful fr cicluri G unim dou
CT

noduri oarecare neadiacente printr-o muchie, graful obinut conine un ciclu).


(5) G este un graf conex minimal (dac n graful conex G suprimm o muchie
oarecare, graful obinut nu mai este conex).
DA

(6) Orice pereche de noduri este legat printr-un lan i numai unul.
Demonstraie. Este suficient s se demonstreze implicaiile (1)(2), (2)(3), (3)(4), (4)(5),
(5)(6) i (6)(1). Prin tranzitivitatea acestor implicaii rezult implicaiile (2)(1), (3)(2), (4)(3),
(5)(4), (6)(5) i (1)(6). Din aceste implicaii rezult c (1)(2), (2)(3), (3)(4), (4)(5),
(5)(6) i (6) (1). Din tranzitivitatea relaiei de echivalen rezult oricare dou din cele 6 propoziii
DI

sunt echivalente.
(1)(2). Ipoteza: Graful G este conex i aciclic din definiia arborelui (1).
Concluzie: Graful G este aciclic i are n-1 muchii (2).
RA

Proprietatea c graful G este aciclic este comun ipotezei i concluziei. Trebuie demonstrat doar c
un graf conex aciclic are n-1 muchii. Dac G este conex aciclic, nu trebuie eliminat nici o muchie
pentru a se obine un graf parial conex aciclic. Cum numrul de muchii care trebuie eliminate dintr-un
graf conex pentru a obine un graf parial conex aciclic este egal cu m-n+1, nseamn c n acest caz,
m-n+1=0. Rezult c m=n-1.
TU

(2)(3). Ipoteza: Graful G este aciclic i are n-1 muchii din definiia arborelui (2).
Concluzie: Graful G este conex i are n-1 muchii (3).
Proprietatea c graful G are n-1 muchii este comun ipotezei i concluziei. Trebuie demonstrat doar
I

c un graful cu n-1 muchii fiind aciclic este i conex. Se tie c ntr-un graf cu p componente conexe,
ED

numrul de muchii care trebuie eliminate pentru a obine un graf parial aciclic este egal cu m-n+p.
282 Implementarea structurilor de date

C
Graful G este aciclic (m-n+p=0) i are n-1 muchii (m=n-1) i (n-1)-n+p=0. Rezult c p=1 (graful are o
singur component conex, deci este conex).
(3)(4). Ipoteza: Graful G este conex i are n-1 muchii (3).

I
Concluzie: Graful G este aciclic maximal (4).

OG
G fiind conex, numrul de componente conexe p este egal cu 1. Numrul de muchii m ale grafului G
este egal cu n-1. Rezult c numrul de muchii care trebuie eliminate din graful G ca s se obin un
graf parial aciclic este egal cu: m-n+p = (n-1)+n+1 = 0, adic nici o muchie. Rezult c graful G este
aciclic. Graful este maximal pentru aceast proprietate, deoarece fiind conex, orice muchie [xi,xj]
care se va aduga va forma un ciclu cu lanul L(xi,xj) existena acestui lan rezult din

AG
conexitatea grafului G.
(4)(5). Ipoteza: Graful G este aciclic maximal (4).
Concluzie: Graful G este conex minimal (5).
a. Presupunem c graful G nu este conex. El are cel puin dou componente conexe: C1 i C2.

ED
nseamn c exist dou noduri xC1 i yC2 pe care le putem lega cu muchia [x,y]. Dar, din
ipotez, rezult c orice muchie am aduga la graf, el va conine un ciclu. Rezult c prin
adugarea muchiei [x,y] graful va conine un ciclu i c, ntre nodurile x i y exist deja un
lan i ele aparin aceleiai componente conexe, ceea ce contrazice presupunerea fcut.
nseamn c graful G este conex.

P
b. Presupunem c graful G care este conex nu este minimal cu aceast proprietate. nseamn c prin
eliminarea unei muchii se obine graful parial H care are n noduri i m-1 muchii, este conex i aciclic.
I
Graful G fiind conex i aciclic, nseamn c numrul de muchii care trebuie eliminate pentru a obine
un graf parial conex aciclic este egal cu 0, adic m-n+1=0 i m=n-1. Numrul de muchii ale grafului H
este egal cu m-1=n-2. Fiind aciclic nseamn c numrul de muchii care trebuie eliminate pentru a
obine un graf parial aciclic este egal cu 0, adic (n-2)-n+p=0. Rezult c p=2, adic graful parial H

conine dou componente conexe, ceea ce contrazice presupunerea c el este conex.


(5)(6). Ipoteza: Graful G este conex minimal (5).
IC

Concluzie: Orice pereche de noduri este legat printr-un lan i numai unul (6).
Graful G fiind conex, nseamn c exist cel puin un lan care leag oricare dou noduri x i y.
Presupunem c exist cel puin dou lanuri ntre nodurile x i y: L1 i L2. nseamn c, suprimnd o
CT

muchie din lanul al doilea, graful rmne conex, deoarece nodurile x i y vor fi legate prin lanul L1,
ceea ce contrazice ipoteza c graful G este conex minimal. Rezult c cele dou noduri x i
y nu sunt legate dect printr.un singur lan.
(6)(5). Ipoteza: Orice pereche de noduri este legat printr-un lan i numai unul (6).
DA

Conciuzie: Graful G este conex i aciclic din definiia arborelui (1).


Deoarece n graful G, orice pereche de noduri x i y este legat printr-un lan, nseamn c graful G
este conex. Presupunem c graful G conine cel puin un ciclu. Considernd dou noduri oarecare x
i y care aparin acestui ciclu, nseamn c ntre cele dou noduri exist dou lanuri diferite, ceea ce
7contrazice ipoteza. Rezult c graful G este aciclic.
DI

Propoziia 14
Orice arbore cu n noduri are n-1 muchii.
RA

Demonstraie. Arborele fiind un graf conex minimal, nseamn c are n-1 muchii.
Propoziia 15. Orice arbore cu n>=2 noduri conine cel puin dou noduri terminale.
Demonstraie prin reducere la absurd. Presupunem c nu exist dect un singur nod terminal x.
TU

Oricare alt nod din arbore are cel puin gradul 2. Alegem din arbore, dintre lanurile elementare
care au o extremitate n nodul x, lanul de lungime maxim: L(x,y). Nodul y avnd gradul
mai mare dect 1, nseamn c mai exist, n afara nodului care l precede n lan, cel puin
un nod z care este adiacent cu el. Lanul fiind elementar, nseamn c nodul y nu exist n
lan dect la extremitatea lui, iar muchia [y,z] nu face parte din lan i putem aduga
I

aceast muchie la lan. Lanul fiind de lungime maxim, nseamn c nodul z aparine
ED
Informatic 283

C
lanului i prin adugarea acestei muchii la lan se nchide un ciclu, ceea ce contrazice
definiia arborelui (graf aciclic).
1. Precizai dac este arbore graful G40(X40, U40) definit astfel: G
GG444000

I
Tem X40={1,2,3,4,5,6,7,8,9,10}

OG
U40={[1,2], [1,3], [1,5], [2,6], [2,7], [3,4], [3,9], [4,8], [8,10] }.
2. Demonstrai c un arbore este un graf bipartit. Reciproca este adevrat?
3. Scriei un program care citete dintr-un fiier text informaii despre un graf neorientat
(de pe primul rnd, numrul de noduri ale grafului n, iar de pe urmtoarele n rnduri

AG
matricea de adiacen a grafului) i care:
a. verific dac graful este un arbore;
b. dac nu este arbore, verific dac prin eliminarea muchiilor poate fi fcut arbore; n caz
afirmativ s se specifice cte muchii trebuie eliminate i care sunt aceste muchii.

ED
c. dac nu este arbore, verific dac prin adugarea muchiilor poate fi fcut arbore; n
caz afirmativ s se specifice cte muchii trebuie adugate i care sunt aceste muchii.

2.8.2. Arborele parial


2.8.2.1. Definiia arborelui parial
P
I
Dac un graf parial al unui graf G este arbore, el se numete
arbore parial al grafului G.
G
G
G444111

IC

Fig. 48 Arbore parial al grafului G41


Graful G41
Teorema 22
CT

Un graf G conine un arbore parial dac i numai dac este un graf conex.
Demonstraie. Notm cele dou propoziii, astfel:
DA

(1) Graful G conine un arbore parial.


(2) Graful G este conex.
Trebuie s demonstrm c (1)(2) i (2)(1).
(1)(2). S considerm c graful G conine arborele parial H. Din definiia arborelui rezult c H este
un graf conex. Din definiia arborelui parial rezult c H este graf parial al grafului G. Deoarece graful
DI

G se obine prin adugarea de muchii la un graf conex (H), este i el un graf conex.
(2)(1). Dac G este un graf conex minimal, nseamn c este un arbore (din Teorema 21: (1) (5))
i H=G. Dac G nu este un graf conex minimal, nseamn c exist o muchie [x,y] pe care o putem
elimina astfel nct s obinem un graf parial conex G1. Dac graful parial G1 este un graf conex
RA

minimal, nseamn c H= G1; altfel se repet procesul de eliminare a cte unei muchii pn se obine
un graf parial conex minimal. Acesta va fi arborele parial H.

2.8.2.2. Definiia arborelui parial de cost minim


TU

Considerm un graf conex G=(X,U), o funcie c:UR+ care asociaz fiecrei muchii u un nu-
mr real pozitiv c(u), numit costul muchiei, i un graf H=(X,V) care este graf parial al
grafului G (VU). Funca c se numete funcia cost. Definim:
I

Costul grafului este suma costurilor muchiilor grafului.


ED
284 Implementarea structurilor de date

C
costul grafului G: c(G ) c(u )
U
costul grafului parial H: c( H ) c(u )

I
V

OG
Se numete graf parial de cost minim al unui graf G conex, cu funcia de cost c,
un graf parial conex H care are costul minim.
Teorema 23

AG
Graful parial de cost minim al unui graf conex G, cu funcia de cost c,
este un arbore.
Demonstraie prin reducere la absurd. Dac graful G este un arbore, atunci H=G, deoarece
orice muchie am elimina din G i-ar pierde proprietatea de conexitate. Dac graful G nu este un

ED
arbore, nseamn c el conine un numr finit de grafuri pariale conexe. Alegem dintre aceste grafuri
pariale graful H care este graful parial de cost minim. Presupunem c acest graf parial nu este
arbore. nseamn c el conine cel puin un ciclu i exist o muchie u=[x,y] pe care o putem suprima
astfel nct s obinem un alt graf parial conex H1. Rezult c:

P
c(H)=c(H1)-c(u)>c(H1)
Inegalitatea c(H)>c(H1) contrazice faptul c graful parial H este de cost minim. nseamn c graful
parial H este arbore.
I
Arborele care este un graf parial de cost minim al grafului conex G, cu
funcia de cost c, se numete arbore parial de cost minim (APM).

IC

Scop: identificarea aplicaiilor n care se folosete arborele parial de cost minim.


Enunul problemei. O reea de calculatoare este format din 7 calculatoare server conectate
ntre ele i calculatoare client conectate la servere. Unele servere pot fi legate direct, altele
CT

nu. Pentru ca reeaua s funcioneze trebuie s se asigure transportul datelor ntre oricare
dou calculatoare server (dou servere trebuie s comunice fie prin legtur direct, fie prin
intermediul altor servere). Fiecare legtur direct dintre dou
servere are asociat un cost de construcie. Legturile care se pot
DA

face ntre servere i costurile asociate acestor legturi sunt


prezentate n figura 49. S se gseasc o soluie de construire a
reelei de calculatoare (de a lega serverele ntre ele) astfel nct
costul de realizare a reelei s fie minim. Fig. 49
DI

G
G
G444222 O reea de servere este un graf neorientat G42 cu n noduri (n exemplu, n=7), n care
nodurile sunt serverele, iar leagturile directe dintre dou servere, muchiile gafului. Graful
este conex (oricare ar fi dou servere din reea, ntre ele trebuie s existe un lan care s
RA

le permit s comunice ntre ele). Gsirea soluiei optime de conectare a serverelor,


astfel nct costul financiar s fie minim, nseamn determinarea unui graf conex de cost
minim, adic gsirea arborelui parial de cost minim al grafului.
Observaie. Orice reea de transport (de calculatoare, rutier, de cale ferat, aerian, de
TU

telecomunicaii, de canalizare etc.) este un graf neorientat conex. Construirea cu


costuri financiare minime a unei astfel de reele se rezolv prin gsirea arborelui
parial de cost minim al grafului asociat reelei.
I
ED
Informatic 285

C
2.8.2.3. Algoritmi pentru determinare a arborelui parial de cost minim
Algoritmii pentru determinarea arborelui parial de cost minim folosesc strategia greedy:

I
PAS1. Se alege un subarbore al arborelui parial de cost minim Hinit.

OG
PAS2. Ct timp nu s-a format arborele parial de cost minim execut:
PAS3. Se alege o muchie sigur din mulimea muchiilor nealese (rmase).
PAS4. Se adaug muchia la subarbore.
Muchia sigur trebuie s ndeplineasc urmtoarele condiii:

AG
s aib costul minim;
s aparin arborelui parial de cost minim.
Determinarea arborelui parial de cost minim se poate face prin:
a) Algoritmul lui Kruskal;

ED
b) Algoritmul lui Prim.
Cei doi algoritmi difer prin:
modul n care se alege subarborele de la care se pornete;
modul n care este gsit o muchie sigur.

P
a) Algoritmul lui Kruskal
Graful parial al grafului G=(X,U) care nu conine nici o muchie (are numai noduri izolate)
I
este format din n arbori pariali disjunci:
H1=(X1,) cu X1={x1}
H2=(X2,) cu X2={x2}
Xi Xj=, i,j (1in, 1jn i ij)

.
Hk=(Xk,) cu Xk={xk} X1 X2 X3 Xn= X
.
IC

Hn=(Xn,) cu Xn={xn}
Se pornete de la doi arbori pariali disjunci Hi i Hj care se unific prin adugarea unei
CT

muchii sigure. Muchia sigur trebuie s ndeplineasc urmtoarele condiii:


s aib costul minim;
s nu formeze cicluri cu muchiile deja alese, adic extremitile sale s aparin celor
dou mulimi disjuncte Xi i Xj muchia este [xi,xj] cu xiXi i xjXj.
DA

Structura de date folosit pentru implementarea grafului este lista muchiilor. Pentru a
gsi mai uor muchia cu costul minim, lista muchiilor este sortat cresctor, dup cost.
Algoritmul pentru determinarea APM este urmtorul:
DI

PAS1. Pentru fiecare nod i din graf execut: se formeaz arborii pariali Hi.
PAS2. Se sorteaz muchiile din U n ordinea cresctoare a costului c.
PAS3. Se alege muchia u cu costul minim.
PAS4. Se iniializeaz APM cu muchia u.
RA

PAS5. Ct timp nu s-au selectat cele n-1 muchii execut:


PAS6. Se alege o muchie sigur din mulimea muchiilor nealese (rmase) i se
formeaz un arbore parial cu aceast muchie.
PAS7. Se unific APM cu arborele format cu muchia sigur.
TU

Pentru a ine evidena arborilor pariali Hi care se dezvolt, se folosete lista L n fiecare
element L(i) al listei se memoreaz numrul de ordine al arborelui parial din care face
parte nodul i. Iniial, existnd n arbori pariali Hi, fiecare dintre ei coninnd un nod al
grafului, elementele listei vor L(i)=i, pentru i1, 2, 3, ,n. Pe parcursul executrii algorit-
I
ED

mului, L(i)=j nseamn c nodul i aparine arborelui cu numrul de ordine j.


286 Implementarea structurilor de date

C
Pentru ca muchia [x,y] care se alege s fie o muchie sigur trebuie s ndeplineasc condiile:
s aib costul minim muchiile se aleg n ordine, din lista muchiilor, unde ele sunt aran-
jate n ordinea cresctoare a costului;

I
extremitile sale s aparin la doi arbori pariali diferii trebuie ca L(x)L(y).

OG
Dup ce s-a gsit o muchie sigur, unificarea arborilor se face astfel:
Dac L(x)<L(y), se adaug arborele parial din care face parte nodul y la arborele parial din
care face parte nodul x, adic se nlocuiesc toate elementele L(i)=L(y) cu valoarea L(x).
Dac L(x)>L(y), se adaug arborele parial din care face parte nodul x la arborele parial din

AG
care face parte nodul y, adic se nlocuiesc toate elementele L(i)=L(x) cu valoarea L(y).
Pentru graful G42 se obine arborele parial de cost minim din figura 50. Algoritmul se
excut astfel:
Lista muchiilor

ED
Muchia u [1,2] [1,3] [2,3] [2,4] [3,4] [3,6] [4,5] [4,6] [5,6] [5,7] [6,7]
Costul c 5 8 11 10 15 9 2 7 10 4 12
Lista muchiilor sortat cresctor dup cost
Muchia u [4,5] [5,7] [1,2] [4,6] [1,3] [3,6] [2,4] [5,6] [2,3] [6,7] [3,4]

P
Costul c 2 4 5 7 8 9 10 10 11 12 15

Lista arborilor pariali iniial este:


I
Nodul i 1 2 3 4 5 6 7 Arborii pariali
L[i] 1 2 3 4 5 6 7 Hi=({i},) cu 1in
Muchia cu costul minim este [4,5]

L[4]=4 45 L[4] L[5] Nodul i 1 2 3 4 5 6 7 m=1


L[5]=5 45 L[5] = L[4]=4 L[i] 1 2 3 4 4 6 7 mn-1=6
IC

Arborii pariali sunt: H4=({4,5},{[4,5]}) i Hi=({i},) cu i{1,2,3,6,7}


Urmtoarea muchie cu costul minim este [5,7]
CT

L[5]=4 47 L[5] L[7] Nodul i 1 2 3 4 5 6 7 m=2


L[7]=7 47 L[7] = L[5]=4 L[i] 1 2 3 4 4 6 4 mn-1=6
Arborii pariali sunt: H4=({4,5,7},{[4,5], [5,7]}) i Hi=(i,) cu i{1,2,3,6}
Urmtoarea muchie cu costul minim este [1,2]
DA

L[1]=1 12 L[1] L[2] Nodul i 1 2 3 4 5 6 7 m=3


L[2]=2 12 L[2] = L[1]=1 L[i] 1 1 3 4 4 6 4 mn-1=6
Arborii pariali sunt: H1=({1,2},{[1,2]}), H4=({4,5,7},{[4,5], [5,7]}) i Hi=({i},) cu i{3,6}
Urmtoarea muchie cu costul minim este [4,6]
DI

L[4]=4 46 L[4] L[6] Nodul i 1 2 3 4 5 6 7 m=4


L[6]=6 46 L[6] = L[4]=4 L[i] 1 1 3 4 4 4 4 mn-1=6
Arborii pariali sunt: H1=({1,2},{[1,2]}), H4=({4,5,6,7},{[4,5], [4,6], [5,7]}) i H3=({3},)
RA

Urmtoarea muchie cu costul minim este [1,3]


L[1]=1 13 L[1] L[3] Nodul i 1 2 3 4 5 6 7 m=5
L[3]=3 13 L[3] = L[1]=1 L[i] 1 1 1 4 4 4 4 mn-1=6
Arborii pariali sunt: H1=({1,2,3},{[1,2],[1,3]}) i H4=({4,5,6,7},{[4,5], [4,6], [5,7]})
TU

Urmtoarea muchie cu costul minim este [3,6]


L[3]=1 14 L[3] L[6] Nodul i 1 2 3 4 5 6 7 m=6
L[6]=4 14 L[6] = L[3]=1 L[i] 1 1 1 1 1 1 1 m=n-1=6
i L[7] = L[6] =L[5] = L[4] = L[3]=1
I
ED

Arborele parial de cost minim este: H1=({1,2,3,4,5,6,7}, {[1,2], [1,3], [3,6], [4,5], [4,6], [5,7]})
Informatic 287

C
Pentru implementarea algoritmului se folosesc urmtoarele variabile i structuri de date:
variabilele n i m pentru numrul de noduri, respectiv numrul de muchii ale grafului;
vectorul u, cu m elemente, pentru lista muchiilor; este un

I
vector de structuri de tip muchie;

OG
vectorul L, cu n elemente, pentru lista arborilor pariali;
variabila ct pentru a calcula costul total al arborelui;
variabila k pentru a numra muchiile adaugate la arborele Fig. 50
parial; iniial are valoarea 0 arborele nu conine nici o

AG
muchie valoarea sa final este n-1 (numrul de muchii ale unui arbore cu n noduri);
variabila i pentru indicele cu care se parcurge lista muchiilor;
variabilele x i y pentru pentru a memora nodurile de la extremitile unei muchii;
i subprogramele:

ED
funcia procedural citire creeaz lista muchiilor u prin preluarea datelor din fiier
n fiierul costapm.txt pe primul rnd se citete o valoare numeric ce reprezint
ordinul grafului, iar de pe urmtoarele rnduri trei valori numerice separate prin spaiu
care reprezint nodurile de la extremitile unei muchii i costul asociat muchiei;

P
funcia procedural init iniializeaz lista L a arborilor pariali Hi cu cei n arbori
formai din cele n noduri izolate (arborii care nu conin muchii);
funcia procedural sortare sorteaz lista muchiilor cresctor dup costul asociat;
I
#include <fstream.h>
fstream f("costapm.txt",ios::in);
int n,m,L[20];
struct muchie {int x,y,c;}; //x,y=noduri muchie; c=cost asociat muchiei

muchie u[20]; //u=lista muchiilor


void init() {for (int i=1;i<=n;i++) L[i]=i;}
IC

void citire()
{int i=0,x,y,c; f>>n;
while (f>>x>>y>>c) {i++; u[i].x=x; u[i].y=y; u[i].c=c;}
CT

f.close(); m=i;}
void sortare()
{int i,j; muchie aux;
for (i=1;i<m;i++)
DA

for (j=i+1;j<=m;j++)
if (u[i].c>u[j].c) {aux=u[i]; u[i]=u[j]; u[j]=aux;}}
void main()
{int i=1,j,k=0,x,y,ct=0; citire(); sortare(); init();
DI

cout<<"APM este format din muchiile: "<<endl;


while (k<n-1) //ct timp nu s-au gsit cele n-1 muchii ale APM
{if (L[u[i].x]!=L[u[i].y])
{k++; ct=ct+u[i].c; //se alege muchia i pentru a unifica doi arbori
RA

cout<<"["<<u[i].x<<","<<u[i].y<<"] ";
x=L[u[i].y]; //se unifica cei doi arbori prin muchia [x,y]
y=L[u[i].x];
for (j=1;j<=n;j++) if (L[j]==x) L[j]=y;}
i++;} //se trece la muchia urmtoare din lista muchiilor
TU

cout<<endl<<"costul total= "<<ct;}


Complexitatea algoritmului lui Kruskal
Pasul 1 are ordinul de complexitate O(n). Pasul 2 are ordinul de complexitate n funcie de
I

algoritmul de sortare ales. Algoritmii de sortare prin metoda seleciei directe sau metoda
ED
288 Implementarea structurilor de date

C
2
bulelor au ordinul de complexitate O(m ). Pasul 3 nu se poate
preciza de cte ori se execut. n cazul cel mai defavorabil, se
parcurg toate cele m muchii, deci se execut de m ori. n cazul

I
pasului 3, pentru fiecare muchie aleas, se parcurg toate cele n

OG
elemente ale listei L. Rezult c pasul 3 are ordinul de com-
plexitate O(nm). Ordinul de complexitate al algoritmului va fi:
2 2
O(n)+O(m )+O(nm) = O(max(m ,nm)). Dac graful are foarte Fig. 51
2
multe muchii, atunci ordinul su de complexitate este O(m ).

AG
G
G
G444333 Pentru graful G43(X43,U43) din figura 51, determinai APM executnd algorit-
Tem mul lui Kruskal. Verificai dac soluia obinut este corect executnd
programul pentru graful G43.
b) Algoritmul lui Prim

ED
Algoritmul lui Prim se aseamn cu algoritmul lui Dijkstra pentru determinarea drumurilor
de lungime minim ntr-un graf. n graful G=(X,U), subarborele de la care se pornete Hinit
este format dintr-un nod iniial numit rdcin (r care se comunic algoritmului mpreun

P
cu datele despre graf) i crete pn acoper toate nodurile din mulimea X. Dac arborele
parial care se dezvolt este H=(A,V), definim graful GA=(X-A,). Nodurile care fac parte
din GA sunt memorate ntr-o coad de prioriti Q. Coada de prioriti se deosebete de o
I
coad simpl, prin aceea c din ea nu se extrage primul element introdus, ci elementul cu
valoarea cea mai mic (sau cea mai mare, n funcie de prioritatea aleas).
n coada de prioriti Q se memoreaz pentru fiecare nod i, eticheta nodului jA cu care

formeaz muchia cu costul minim. La fiecare adugare a unui nou nod la arbore, acesta
trebuie eliminat din coada de prioriti, iar coada trebuie reactualizat pentru toate nodurile
IC

rmase, deoarece s-a modificat mulimea A, iar un nod din coada de ateptare poate s
aib muchia cu costul minim cu noul nod adugat la arborele parial. Arborele care se
CT

dezvolt este memorat n lista H, astfel: pentru fiecare nod i care se adaug la arborele
parial, se memoreaz nodul jA cu care este legat prin muchie. Iniial Hinit=({r},),
GA=(X-{r},), n lista H toate elementele au valoarea 0, iar n coada de prioriti Q, fiecrui
nod ir i se va atribui valoarea r (Q(i)=r).
DA

Muchia sigur trebuie s ndeplineasc urmtoarele condiii:


s aib costul minim;
s nu formeze cicluri cu muchiile deja alese, adic s uneasc un nod din H cu un nod
izolat din GA extremitile sale aparin celor dou mulimi disjuncte A i X-A (muchia
DI

este [xi,xj] cu xiA i xjX-A).


Structura de date folosit pentru implementarea grafului este matricea costurilor.
Algoritmul pentru determinarea APM este urmtorul:
RA

PAS1. Se iniializeaz APM cu nodul rdcin r.


PAS2. Se iniializeaz lista H. astfel: pentru fiecare nod i din graf execut: :H(i)0.
PAS3. Se iniializeaz coada de prioriti Q. astfel: Q(r) 0 i pentru fiecare nod ir
din graf execut: Q(i)r.
TU

PAS4. Ct timp nu s-au selectat cele n-1 muchii execut:


PAS5. Se alege o muchie sigur din mulimea muchiilor nealese muchia [i,j] cu
iA i jX-A
PAS6. Se adaug muchia la lista H: H(j)Q(j).
I
ED
Informatic 289

C
PAS7. Se elimin din coada de prioriti nodul j adugat la arbore, atribuindu-i
valoarea 0: Q(j)0.
PAS8. Se actualizeaz coada de prioriti pentru nodurile nealese, astfel pentru

I
fiecare nod i din Q execut: caut nodul jA cu care formeaz muchia cu

OG
costul minim.
Coada de prioriti Q este implementat cu un vector cu n elemente. Iniial:
0 dac i r
Q(i )
r dac i r

AG
n timpul execuiei algoritmului:
0 dac i A

Q(i ) r dac i A i nu j A a..[i, j] U
j dac i A i j A a..[i, j] U i cost([i, j]) min

ED

La terminarea execuiei algoritmului: Q(i)=0, pentru orice i (1in).
Lista H este implementat cu un vector cu n elemente. Iniial: H(i)=0, pentru orice i (1in).

P
n timpul execuiei algoritmului:
0 dac i r sau i A
H( i )
j dac i A, iar [i, j] H
I
La terminarea execuiei algoritmului:
0 dac i r
H( i )
j dac i r i [i, j] H

Pentru ca muchia [i,j] care se alege s fie o muchie sigur trebuie s ndeplineasc condiile:
IC

s aib costul minim se caut nodul j pentru care n matricea costurilor elementul
a[Q[j]][j] are valoarea minim;
extremitile sale s aparin la doi arbori pariali diferii trebuie ca Q(i)0 i Q(j)=0.
CT

Dup ce s-a gsit o muchie sigur, ea este adugat la arbore prin T(j)=Q(j).
Pentru graful G42 din figura 49, considernd r=1, algoritmul se excut astfel:
Lista muchiilor
DA

Muchia u [1,2] [1,3] [2,3] [2,4] [3,4] [3,6] [4,5] [4,6] [5,6] [5,7] [6,7]
Costul c 5 8 11 10 15 9 2 7 10 4 12

Arborele parial (H) i coada de prioriti Q iniial sunt:


DI

Nodul i 1 2 3 4 5 6 7 Arborele iniial


H[i] 0 0 0 0 0 0 0 Hinit=({1},)
Q[i] 0 1 1 1 1 1 1 min=5
Costul muchiei [i,Q[i]] - 5 8 VMAX VMAX VMAX VMAX j=2
RA

Muchia cu costul minim este [Q[j],j]= [Q[2],2]= [1,2]


Nodul i 1 2 3 4 5 6 7
H[2]=Q[2] H[i] 0 1 0 0 0 0 0
TU

Q[2]=0 Q[i] 0 0 1 1 1 1 1
Costul [i,Q[i]] - - 8 VMAX VMAX VMAX VMAX
Actualizare Q[i] 0 0 1 2 1 1 1 min=8
Q Costul [i,Q[i]] - - 8 10 VMAX VMAX VMAX j=3
I
ED

Arborele parial H=({1,2},{[1,2]}) i X-A={3,4,5,6,7} m=1


290 Implementarea structurilor de date

C
Muchia cu costul minim este [Q[j],j]= [Q[3],3]= [1,3]
Nodul i 1 2 3 4 5 6 7
H[3]=Q[3] H[i] 0 1 1 0 0 0 0

I
Q[3]=0 Q[i] 0 0 0 1 1 1 1

OG
Costul [i,Q[i]] - - - 10 VMAX VMAX VMAX
Actualizare Q[i] 0 0 0 2 1 3 1 min=9
Q Costul [i,Q[i]] - - - 10 VMAX 9 VMAX j=6
Arborele parial H=({1,2,3},{[1,2], [1,3]}) i X-A={4,5,6,7} m=2

AG
Muchia cu costul minim este [Q[j],j]= [Q[6],6]= [3,6]
Nodul i 1 2 3 4 5 6 7
H[6]=Q[6] H[i] 0 1 1 0 0 3 0
Q[6]=0 Q[i] 0 0 0 2 1 0 1

ED
Costul [i,Q[i]] - - - 10 VMAX - VMAX
Actualizare Q[i] 0 0 0 6 6 0 6 min=7
Q Costul [i,Q[i]] - - - 7 10 - 12 j=4
Arborele parial H=({1,2.3,6},{[1,2], [1,3], [3,6]}) i X-A={4,5,7} m=3

P
Muchia cu costul minim este [Q[j],j]= [Q[4],4]= [6,4]
Nodul i 1 2 3 4 5 6 7
I
H[4]=Q[4] H[i] 0 1 1 6 0 3 0
Q[4]=0 Q[i] 0 0 0 0 6 0 6
Costul [i,Q[i]] - - - - 10 - 12
Actualizare Q[i] 0 0 0 0 4 0 6 min=2

Q Costul [i,Q[i]] - - - - 2 - 12 j=5


Arborele parial H=({1,2.3,4,6},{[1,2], [1,3], [3,6], [4,6]}) i X-A={5,7} m=4
IC

Muchia cu costul minim este [Q[j],j]= [Q[5],5]= [4,5]


Nodul i 1 2 3 4 5 6 7
CT

H[5]=Q[5] H[i] 0 1 1 6 4 3 0
Q[5]=0 Q[i] 0 0 0 0 0 0 6
Costul [i,Q[i]] - - - - - - 12
Actualizare Q[i] 0 0 0 0 0 0 5 min=4
DA

Q Costul [i,Q[i]] - - - - - - 4 j=7


Arborele parial H=({1,2.3,4,5,6},{[1,2], [1,3], [3,6], [4,5], [4,6]}) i X-A={7} m=5
Muchia cu costul minim este [Q[j],j]= [Q[7],7]= [5,7]
DI

Nodul i 1 2 3 4 5 6 7
H[7]=Q[7] H[i] 0 1 1 6 4 3 5
Q[7]=0 Q[i] 0 0 0 0 0 0 0
Costul [i,Q[i]] - - - - - - -
RA

Actualizare Q[i] 0 0 0 0 0 0 0 X-A=


Q Costul [i,Q[i]] - - - - - - -
Arborele parial H=({1,2.3,4,5,6,7},{[1,2], [1,3], [3,6], [4,5], [4,6], [5,7]}) m=6
Pentru implementarea algoritmului se folosesc urmtoarele variabile i structuri de date:
TU

variabilele n i r pentru numrul de noduri, respectiv pentru nodul rdcin;


matricea ptratic A, cu dimeniunea n, pentru matricea costurilor asociat grafului;
vectorul Q, cu n elemente, pentru coada de prioriti;
vectorul H, cu n elemente, pentru lista muchiilor din APM;
I
ED

variabila ct pentru a calcula costul total al arborelui;


Informatic 291

C
variabila k pentru a numra muchiile adaugate la arborele parial; iniial are valoarea 0
arborele nu conine nici o muchie valoarea sa final este n-1 (numrul de muchii
ale unui arbore cu n noduri);

I
variabilele i i j pentru indicele cu care se parcurge coada de prioriti, respectiv

OG
pentru nodul care se adaug la arbore;
i subprogramele:
funcia procedural init_mc iniializeaz matricea costurilor;
funcia procedural citire_mc actualizeaz matricea costurilor cu datele din fiier;

AG
funcia procedural init_Q iniializeaz coada de prioriti Q;
funcia operand muchie caut o muchie sigur n mulimea muchiilor nealese;
funcia procedural actualizeaz_Q actualizeaz coada de prioriti Q dup ce a
fost adugat muchia la arborele parial;

ED
funcia procedural afiare afieaz APM.
#include <fstream.h>
fstream f("costapm.txt",ios::in);
int a[50][50],Q[50],H[50],n,r;

P
const int VMAX=5000;
void init mc()
{int i,j; f>>n;
I
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) if (i!=j) a[i][j]=VMAX; }
void citire mc()
{int i,j,c; while (f>>i>>j>>c) a[i][j]=c; a[j][i]=c; f.close();}

void init Q() {for (int i=1;i<=n;i++) if (i!=r) Q[i]=r;}


int muchie()
IC

{int i,j,min=VMAX;
for(i=1;i<=n;i++)
if (Q[i]!=0 && a[Q[i]][i]<min) {min=a[Q[i]][i]; j=i;}
CT

return j;}
void actualizeaza Q(int j)
{for(int i=1;i<=n;i++) if (Q[i]!=0 && a[i][Q[i]]>a[i][j]) Q[i]=j;}
void afisare()
{cout<<"APM este format din muchiile: "<<endl;
DA

for(int i=1;i<=n;i++) if (H[i]!=0) cout<<"["<<H[i]<<","<<i<<"] ";}


void main()
{int i,j,k=0,ct=0; init mc(); citire_mc();
cout<<"Nodul initial: "; cin>>r; init Q();
DI

while (k<n-1) //ct timp nu s-au gsit cele n-1 muchii ale APM
{j=muchie(); //alege o muchie sigur
H[j]=Q[j]; ct+=a[Q[j]][j]; //adaug la arbore nodul i muchia
Q[j]=0; //elimin din coada de prioriti nodul adugat
RA

actualizeaza Q(j); //actualizeaz coada de prioriti


k++;}
cout<<"costul total= "<<ct<<endl; afisare();}
Complexitatea algoritmului lui Prim
TU

Pasul 2 i pasul 3 au ordinul de complexitate O(n). Pasul 4 se execut de n-1 ori. n cazul
pasului 3, pentru fiecare muchie aleas, se execut pasul 5 i pasul 8 de n ori. Rezult c
2
Pasul 3 are ordinul de complexitate O((n-1)(n+n))=O(n ). Ordinul de complexitate al
2 2
I

algoritmului va fi: O(n)+O(n)+O(n )=O(n ).


ED
292 Implementarea structurilor de date

C
Pentru graful G43 din figura 51, determinai APM executnd algoritmul lui
Tem Prim. Verificai dac soluia obinut este corect executnd programul
pentru graful G43.

I
OG
2.8.2.4. Aplicaii practice
1. Trebuie s se construiasc o reea de autostrzi care s lege cele mai importante orae
din ar. Fiecare tronson de autostrad care leag dou orae are un cost de construire.
S se determine reeaua de autostrzi astfel nct toate oraele s fie legate prin

AG
autostrzi i costul construirii ei s fie minim.
2. ntr-o localitate trebuie construit o reea de canalizare care s lege n locuine i s
comunice cu dou puncte de deversare. Fiecare tronson de reea are un cost de
construire. S se determine reeaua de canalizare astfel nct toate locuinele s aib
acces la ea i costul construirii ei s fie minim.

ED
2.8.3. Arborele cu rdcin
2.8.3.1. Definiia arborelui cu rdcin

P
Se numete arbore cu rdcin un arbore A n care
exist un nod privilegiat numit nod rdcin.
I
Terminologie Muli dintre termenii folosii sunt preluai din terminologia arborilor
A
A
A111 genealogici sau a arborilor din natur (ca exemplu, arborele A1 figura 52).
Muchiile unui arbore se mai numesc ramuri sau arce.

Nodul rdcin mai este


numit vrf sau tulpin. n
IC

nodul rdcin nu intr nici


un arc.
ntr-un nod intr un singur
CT

arc (exceptnd rdcina) nlimea 4


care l leag de un alt nod
numit printe sau prede-
cesor.
DA

Dintr-un nod pot s ias


niciunul, unul sau mai mul- Fig. 52
te arce care l leag de un alt nod numit fiu sau succesor.
Nodurile fr succesori (din care nu iese nici un arc) se numesc frunze sau noduri
DI

terminale. Nodurile care nu sunt terminale se mai numesc noduri de ramificare.


Dou noduri adiacente din arbore sunt n relaia tat-fiu sau printe-fiu, iar muchiile
sunt legturi de tip tat-fiu. ntre mai multe noduri se poate stabili o relaie de tipul
RA

fiul fiului ... fiului sau tatl tatlui tatlui. n primul caz se poate spune c nodul
este descendent sau urma al unui alt nod, iar n al doilea caz c nodul este
ascendent sau strmo al unui nod.
Dou noduri care descind direct din acelai nod tat se numesc noduri frate.
TU

Ordinul unui nod este dat de numrul de descendeni direci.


Nodurile sunt organizate pe niveluri. Numerotnd nivelurile nodurilor, rdcina se g-
sete pe nivelul 0, descendenii ei pe nivelul 1, descendenii acestora pe nivelul 2 etc.
Nivelul unui nod este egal cu numrul de noduri parcurse pe calea de la rdcin la el.
I

Un arbore cu rdcin este arbore vid (arbore nul) dac nu are nici un nod.
ED
Informatic 293

C
nlimea unui arbore este dat de maximul dintre nivelurile nodurilor terminale
(lungimea celui mai lung lan care pornete din rdcin).
1. Pentru arborele cu rdcin A1 din figura 52 precizai:

I
Tem eticheta nodului rdcin;

OG
numrul de frunze i etichetele lor;
etichetele nodurilor care se gsesc pe nivelul 2;
etichetele fiilor nodului 2;
etichetele frailor nodului 5;

AG
eticheta printelui nodului 9;
numrul de frai ai nodului 7.
2. Un arbore cu rdcin A2 (X, U) este definit astfel: A
A
A222
X={1,2,3,4,5,6,7,8,9,10}

ED
U={[1,2], [1,3], [1,4], [2,6], [3,5], [3,7], [3,9], [4,8], [8,10] }.
Precizai:
dac eticheta nodului rdcin este 1, cte frunze are arborele i care sunt aceste
frunze;

P
dac eticheta nodului rdcin este 2, ci frai are nodul cu eticheta 1 i pe ce nivel se
gsete nodul cu eticheta 10;
dac eticheta nodului rdcin este 10, ce nlime are arborele, cine este prin-
I
tele nodului cu eticheta 1 i care sunt fiii nodului cu eticheta 3.
Caracteristici:
Nodul rdcin este un nod considerat privilegiat. El nu are printe (ascendent), ci

numai fii (descendeni). Este nodul de la care se consider c pornesc ramurile ctre
rdcinile altor arbori. Orice nod al arborelui poate fi considerat nod rdcin.
IC

Un arbore A este fie vid, fie format dintr-un nod rdcin R cruia i este ataat un
numr finit de arbori. Aceti arbori sunt subordonai rdcinii i se numesc subarbori ai
arborelui A. Orice nod dintr-un arbore este rdcina unui subarbore.
CT

ntre doi subarbori nu pot exista dect dou tipuri de relaii:


a. relaia de incluziune unul dintre subarbori este subarborele celuilalt;
b. relaia de excluziune cei doi subarbori nu au noduri comune, dar aparin
DA

aceluiai arbore.
Accesul de la rdcina unui arbore (subarbore) nevid la oricare nod, nseamn parcur-
gerea unui lan format din m arce, care trec prin n noduri (m=n+1), n reprezentnd
nivelul pe care se gsete nodul fa de rdcin.
DI

Definiii recursive:
Definiia arborelui. Un arbore nevid este o mulime finit A de noduri care au urmtoa-
rele proprieti:
a. Exist un nod care poate fi considerat nod rdcin.
RA

b. Celelalte noduri pot fi repartizate n i (i0) mulimi disjuncte (A1, A2, ...., Ai),
fiecare dintre aceste mulimi fiind considerate la rndul lor arbori.
Definiia nlimii. nlimea unui arbore este egal cu 1+maximul dintre nlimile
subarborilor si.
TU

1. Dac nodul cu eticheta 2 are patru frai, iar nodul cu eticheta 1 este
Tem printele lui, ce ordin are nodul cu eticheta 1?
2. Pentru arborele cu rdcin A1 din figura 52 precizai:
I

ci subarbori are nodul rdcin pentru fiecare subarbore precizai rdcina;


ED
294 Implementarea structurilor de date

C
ci subarbori are nodul cu eticheta 2 pentru fiecare subarbore precizai rdcina;
ci subarbori are nodul cu eticheta 10 precizai cine este acest subarbore;
n ce relaie sunt subarborele cu rdcina n nodul cu eticheta 2 i subarborele cu rdcina

I
n nodul cu eticheta 4;

OG
n ce relaie sunt subarborele cu rdcina n nodul cu eticheta 2 i subarborele cu rdcina
n nodul cu eticheta 9.
3. Pentru arborele cu rdcin A2 definit anterior precizai:
dac eticheta nodului rdcin este 1, n ce relaie sunt subarborele cu rdcina n nodul

AG
cu eticheta 2 i subarborele cu rdcina n nodul cu eticheta 8;
dac eticheta nodului rdcin este 3, ci subarbori are nodul rdcin pentru fiecare
subarbore precizai rdcina;
dac eticheta nodului rdcin este 2, ci subarbori are nodul cu eticheta 9 precizai
cine este acest subarbore;

ED
dac eticheta nodului rdcin este 3, ci subarbori are nodul cu eticheta 2 pentru
fiecare subarbore precizai rdcina;.
dac eticheta nodului rdcin este 4, n ce relaie sunt subarborele cu rdcina n nodul
cu eticheta 1 i subarborele cu rdcina n nodul cu eticheta 3.

P
Se numete arbore ordonat un arbore cu rdcin n care
fiii fiecrui nod sunt ordonai.
I
Observaie. ntr-un arbore ordonat, dac un nod are k fii, atunci exist un prim fiu, un al
doilea fiu, , un al k-lea fiu.
Se numete arborescen sau structur arborescent un arbore cu

rdcin n care s-a stabilit nodul rdcin.


Pentru a nelege deosebirea dintre tipurile de arbori enumerate, vom
IC

considera pentru exemplificare un arbore cu 3 noduri etichetate cu A, B


i C i vom pune n eviden numrul de arbori diferii care se pot forma
CT

cu aceste noduri.
Arbori liber. Se pot obine 3 arbori liberi diferii. n figura 53 sunt
prezentai aceti arbori.
Arbori cu rdcin. Se pot obine 9 arbori cu rdcin diferii. Exist Fig. 53
DA

trei moduri de a alege rdcina (nodul A, nodul B sau nodul


C). Pentru un nod rdcin ales, se pot obine trei arbori
diferii. De exemplu, dac se consider nodul A ca nod
rdcin, exist trei moduri diferite de a repartiza n arbore
DI

nodurile B i C: nodul A are doi fii (B i C) sau un singur fiu: B


sau C, obinndu-se trei arbori diferii (cei prezentai n figura Fig. 54
54). n total se obin 33=9 arbori cu rdcin diferii.
RA

Arbori cu rdcin ordonai. Se pot obine 12


arbori cu rdcin ordonai diferii. Ca i n cazul
precedent, exist trei moduri de a alege rdcina.
Pentru un nod rdcin ales, se pot obine patru
TU

arbori diferii. De exemplu, dac se consider Fig. 55


nodul A ca nod rdcin, exist patru moduri
diferite de a repartiza n arbore nodurile B i C:
I
ED
Informatic 295

C
nodul A are doi fii (B i C sau C i B n acest caz ordinea nodurilor B i C conteaz),
sau un singur fiu: B sau C, obinndu-se patru arbori diferii (cei
prezentai n figura 55). n total se obin 34=12 arbori cu

I
rdcin ordonai diferii.

OG
Structuri arborescente. Pentru un nod rdcin ales (de
exemplu nodul B) se pot obine 3 structuri arborescente diferite Fig. 56
deoarece exist trei moduri diferite de a repartiza n arbore
nodurile A i C: nodul B are doi fii (A i C) sau un singur fiu: A

AG
sau C (figura 56).
Se numete arbore poziional un arbore cu rdcin n
care este precizat poziia fiecrui fiu.

ED
Observaie. ntr-un arbore poziional, fiii fiecrui nod sunt etichetai
cu numere ntregi pozitive consecutive, iar dac lipsete fiul cu
eticheta k, aceast etichet nu se atribuie nici unui fiu (arborele A3 A
A
A333
din figura 57). Fig. 57

P
Scop: identificarea coleciilor de date care pot fi reprezentate prin arbori cu rdcin.
I
Enunul problemei 1. O firm are mai muli angajai. ntre angajai exist fie relaii de subor-
dine, fie relaii de colaborare. Directorul firmei d o dispoziie pe care o transmite subordo-
nailor si direci. Acetia primesc simultan dispoziia i o transmit mai departe subordonailor

direci .a.m.d. Transmiterea dispoziiei de la un nivel ierarhic la altul necesit acelai timp t.
S se determine n ct timp ajung s cunoasc dipoziia dat toi angajaii firmei (figura 58).
IC

Director
CT

ef compartiment 1 ef compartiment 2 ef compartiment 3


DA

ef ef ef
subcompartiment subcompartiment subcompartiment .....................
11 12 13

..........................................
DI

... ...
.
Fig. 58
Firma are o structur ierarhic, iar relaiile dintre angajai pot fi reprezentate cu ajutorul
RA

unei arborescene, n care angajaii sunt nodurile, iar arcele relaiile de subordonare.
Rdcina arborelui este directorul. ntre un angajat care are n subordine un alt angajat
exist o legtur de tip tat-fiu. ntre angajaii subordonai aceluiai angajat exist relaii
de colaborare. Aceti angajai sunt noduri frate. Timpul T necesar ca dispoziia s ajung
TU

de la director la toi angajaii este dat de produsul dintre timpul t necesar pentru
transmiterea de la un nivel la altul i nlimea h a arborelui: T=th.
Enunul problemei 2. Un produs este realizat din mai multe componente. Fiecare
component la rndul su este realizat prin asamblarea altor componente. Att produsul
I
ED

ct i componentele sunt caracterizate printr-o list de atribute (proprieti): denumire,


296 Implementarea structurilor de date

C
cod, pre, funcia realizat, costul asamblrii, firma care o produce etc. S se determine
preul produsului (figura 59).

I
Produs

OG
final

Componenta 1 Componenta 2 Componenta 3

AG
Componenta 11 Componenta 12 Componenta 13 ......................

... ...
.......................................

ED
Fig. 59
Produsul are o structur ierarhic, iar relaiile dintre componente pot fi reprezentate cu
ajutorul unei arborescene, n care componentele sunt nodurile, iar arcele relaiile de
apartenen a unei componente la o alt component. Rdcina arborelui este produsul

P
final. ntre o component i componenta pe care o are n subordine exist o legtur de
tip tat-fiu. Componentele care fac parte din aceeai component sunt frai. Pentru
I
stabilirea costului total al produsului trebuie parcurs arborele, ca s se calculeze costul
fiecrei componente. Costul c al unei componente se obine prin adunarea preului de
achiziie p la costul asamblrii a: c=p+a. Parcurgerea arborelui se face pornind de la
ultimul nivel ctre rdcin. Rdcina se prelucreaz ultima, dup ce au fost prelucrai

toi subarborii subordonai ei.


Observaie. Pentru studierea proprietilor unui obiect, orice obiect poate fi descompus
IC

la rndul su n obiecte mai simple. Fiecare obiect, la rndul su, poate fi caracterizat
printr-o list de proprieti. Procesul de descompunere poate s continue pe mai multe
CT

niveluri. El este finit i se termin dup un numr de etape care este dependent de
problema care trebuie rezolvat. Procesul de descompunere este un proces recursiv
(un obiect este compus din alte obiecte). Prin procesul de descompunere se
stabilete o ierarhie a obiectelor, iar reprezentarea acestei descompuneri se
DA

poate face printr-o arborescen.


1. Reprezentai sub forma unui arbore cu rd-
Tem cin, relaia de incluziune a mulimilor prezen-
tate n figura 60.
DI

2. Dorii s cumprai un calculator i dispunei de un anumit buget.


Pentru a avea un calculator mai performant, alegei varianta de a
cumpra componentele i de a le asambla singur. Calculatorul
RA

este un produs format din mai multe componente (unitatea


central, monitorul, tastatura, mouse-ul etc.) care la rndul lor pot
fi descompuse n alte componente (de exemplu, unitatea central Fig. 60
este format din carcas, plac de baz, unitatea de hard-disc, unitatea de compact disc
TU

sau de DVD, etc.). Desenai arborele structurii de componente a calculatorului.


3. Desenai un arbore genealogic al familiei care s prezinte filiaia (descendenii direci ai
unei persoane). Se va lua ca nod rdcin unul dintre str-strbunici. Identificai pe
acest arbore relaii de rudenie de tip: fiu, nepot, frate i vr.
I
ED
Informatic 297

C
4. Cuprinsul unei cri are o structur arborescent. Desenai structura arborescent a
capitolului Implementarea structurilor de date din acest manual.
5. Structura dosarelor cu fiiere de pe hard-disc, gestionate de sistemul de operare

I
Windows, este o structur arborescent. Desenai arborele dosarelor de pe hard-disc.

OG
Fiierele vor fi nodurile terminale.
6. O matrice cu n linii i m coloane este o structur de date ierarhizat care poate fi
reprezentat pe trei niveluri, ca o arborescen, astfel: nodul rdcin este matricea,
fiii nodului matrice sunt liniile, iar fiii fiecrei linii, elementele de pe linia respectiv.

AG
Desenai arborele cu rdcin al unei matrice cu patru linii i trei coloane. Precizai ce
tip de arbore cu rdcin este.
2.8.3.2. Implementarea arborelui cu rdcin
Implementarea structurilor de date de tip arbore cu rdcin se poate face prin:

ED
matrice de adiacen;
list de adiacen;
referine descendente legtura de tip tata;
referine ascendente legtura de tip printe nod terminal.

P
Observaie. Arborele, fiind un graf neorientat cu anumite proprieti,
pentru implementarea sa static se pot folosi aceleai metode ca i
I
la grafuri, dar aceste implementri sunt ineficiente. Arborilor le sunt
specifice implementarea cu legtura de tip tat i implementarea
cu legtura de tip printe nod terminal. n urmtoarele implemen-
tri se consider c arborele are n noduri i rdcina are eticheta r.

Fig. 61
a) Implementarea prin referine descendente
IC

Legtura de tip tat. Arborele este reprezentat sub forma unui vector t cu n componente
n care se memoreaz, pentru fiecare nod, eticheta printelui su. Algoritmul de constru-
ire a vectorului este urmtorul:
CT

PAS1. Pentru fiecare nod i din arbore execut:


PAS2. Dac nodul i=r, atunci t[i]0; altfel, t[i]j, unde j reprezint
nodul printe al nodului i.
A
A
DA

Exemplu. Vectorul tat pentru arborele A4 din figura 61 este: A444


Nod (indice i) 1 2 3 4 5 6 7 8 9
Printe (t[i]) 3 3 0 3 1 2 4 1 6
DI

Observaie. Din vectorul tat putei obine urmtoarele informaii


eticheta nodului rdcin indicele i pentru care t[i]=0;
etichetele nodurilor terminale nodurile j a cror etichet nu exist n vectorul t;
eticheta printelui unui nod j t[j];
RA

etichetele fiilor unui nod j indicii i pentru care t[i]=j;


etichetele frailor unui nod j indicii i pentru care t[i]=t[j].
1. Reprezentai sub forma vectorului tat arborele
Tem A
A
A555
cu rdcin A5 din figura 62.
TU

2. Scriei un program care s citeasc dintr-un fii-


er informaii despre matricea de adicen a unui arbore cu rd-
cin (de pe primul rnd numrul de noduri n i eticheta rdcinii Fig. 62
r, iar de pe urmtoarele n rnduri matricea de adiacen) i care
I
ED

s scrie vectorul tat al arborelui ntr-un al fiier.


298 Implementarea structurilor de date

C
3. Scriei un program care s citeasc din fiierul creat anterior vectorul tat al arborelui cu
rdcin i s afieze urmtoarele informaii:
a. eticheta nodului rdcin;

I
b. numrul de noduri terminale i etichetele lor;

OG
c. pentru fiecare nod, eticheta printelui, numrul de fii i etichetele lor, i numrul
de frai i etichetele lor.
b) Implementarea prin referine ascendente
Legtura de tip printe nod terminal. Arborele este reprezentat sub forma a doi vectori

AG
cu n-1 componente: vectorul t n care sunt memorate nodurile, n ordine, pornind de la
nodurile terminale, i vectorul pt n care sunt memorate nodurile printe ale nodurilor
terminale. Algoritmul de construire a celor doi vectori este urmtorul:
PAS1. Pentru fiecare indice i de la 1 la n-1 execut:

ED
PAS2. Se caut nodul terminal cu eticheta cea mai mic.
PAS3. Se atribuie aceast etichet lui t[i].
PAS4. Se atribuie lui pt[i] eticheta nodului printe al nodului terminal t[i].
PAS5. Se elimin din arbore nodul terminal t[i].

P
Exemplu. Pentru arborele A4 din figura 61, cei doi vectori se completeaz astfel (figura 63):
Iniial nodurile terminale au etichetele: 5, 8, 9 i 7. Se alege nodul terminal cu eticheta
I
cea mai mic (5). Se scrie eticheta sa n primul element al vectorului t, iar eticheta
printelui su (1) n primul element al vectorului pt. Se nltur nodul 5 din arbore.
Nodurile terminale au etichetele: 8, 9 i 7. Se alege nodul terminal cu eticheta cea mai
mic (7). Se scrie eticheta sa n al doilea element al vectorului t,

iar eticheta printelui su (4) n al doilea element al vectorului pt.


IC

Se nltur nodul 7 din arbore.


Nodurile terminale au etichetele: 8, 9 i 4. Se alege nodul
terminal cu eticheta cea mai mic (4). Se scrie eticheta sa n al
CT

treilea element al vectorului t, iar eticheta printelui su (3) n al


treilea element al vectorului pt. Se nltur nodul 4 din arbore.
Procedeul de adugare n vectorul t a nodului cu eticheta cea Fig. 63
mai mic i a printelui su n vectorul pt, urmat de eliminarea
DA

din arbore a nodului adugat, continu pn cnd n arbore nu mai rmne dect nodul
care are cea mai mare etichet.
Vectorii t i pt pentru arborele A4 din figura 61 sunt:
(indice vector i) 1 2 3 4 5 6 7 8
DI

Nod terminal (t[i]) 5 7 4 8 1 3 2 6


Printe nod terminal (pt[i]) 1 4 3 1 3 2 6 9
1. Reprezentai arborele cu rdcin A5 cu vectorii t i pt.
RA

Tem 2. Scriei un program care s citeasc dintr-un fiier informaii despre


matricea de adicen a unui arbore cu rdcin (de pe primul rnd
numrul de noduri n i eticheta rdcinii r, iar de pe urmtoarele n rnduri matricea de
adiacen) i care s scrie vectorii t i pt ai arborelui ntr-un alt fiier.
TU

Observaii:
1. Vectorii t i pt sunt aceiai pentru un arbore, indiferent de nodul rdcin ales.
2. La terminarea algoritmului, ultimul nod care mai rmne n arbore este nodul cu eticheta
cea mai mare n. Cunoscndu-se aceast etichet, n vectorul pt este suficient s se
I
ED

memoreze numai primele n-2 elemente, ultimul element avnd ntotdeauna valoarea n.
Informatic 299

C
3. Este suficient s se memoreze numai vectorul pt, deoarece din acest vector se poate
construi vectorul t. Pentru a gsi algoritmul de construire a vectorului t, trebuie observat
c eticheta j care se memoreaz n t[i] corespunde unui nod care ndeplinete urm-

I
toarele condiii:

OG
a. Nu a fost nc eliminat din arbore deci nu se gsete printre etichetele t[1], t[2],
, t[i-1].
b. Nu este printele nici unui nod terminal care se va aduga ulterior, deoarece va fi
eliminat din arbore deci nu se gsete printre etichetele pt[i], pt[i+1], , pt[n-1].

AG
c. Are cea mai mic etichet dintre nodurile care ndeplinesc condiiile (a) i (b).
Din aceste condiii rezult c, pentru orice i (1in-1):
t[i] = min{kk{1, 2, , n} - { t[1], t[2], , t[i-1], pt[i], pt[i+1], , pt[n-1] }}
Teorema 23

ED
n-2
Numrul total de arbori liberi care se pot forma cu n noduri este n .
Demonstraie. Vectorul pt fiind acelai pentru un arbore cu rdcin, indiferent de nodul rdcin
ales, el poate fi asociat i unui arbore liber. Vectorul pt are n-2 elemente. Notm cu A mulimea

P
indicilor din vectorul pt i cu B mulimea nodurilor arborelui liber. Fiecrui arbore i putem asocia o
funcie f:AB care asociaz unui indice i din vectorul pt un nod j din arbore: f(i)=j. Invers, unei funcii
f i putem ataa un arbore. Notm cu a=card(A)=n-2 i cu b=card(B)=n. Numrul de funcii f:AB este
I
a n-2
egal cu b = n . Rezult c numrul total de arbori care se pot forma cu n noduri este egal cu
n-2
numrul de funcii f, adic n .
1. Pentru arborele A4 din figura 61 reconstituii vectorul t cu ajutorul

Tem vectorului pt.


2. Scriei un program care s citeasc dintr-un fiier vectorul pt al unui
IC

arbore i care s construiasc vectorul t. Salvai acest vector, n acelai fiier, pe rndul
urmtor.
2.8.3.3. Algoritmi pentru parcurgerea unui arbore cu rdcin
CT

Parcurgerea unui arbore cu rdcin se poate face prin:


a) Algoritmul de parcurgere n lime;
b) Algoritmul de parcurgere n adncime.
DA

a) Algoritmul de parcurgere n lime


Metoda: se prelucreaz mai nti informaia din nodul rdcin, dup care sunt prelucrate,
de la stnga la dreapta, nodurile aflate pe primul nivel, apoi pe cel de al doilea etc.
DI

Structura de date folosit este coada (c) n care se adaug fiii nodului
prelucrat.
Algoritmul pentru parcurgerea arborelui este urmtorul:
RA

PAS1. Se iniializeaz coada cu nodul rdcin r.


PAS2. Ct timp coada nu este vid execut (prim<=utlim):
PAS3. Este extras din coad primul nod i este prelucrat.
PAS4. Sunt adugai n coad fii nodului prelucrat.
TU

Fig. 64 A
A
A666
Exemplu. Coada de ateptare la parcurgerea arborelui A6 din figura 64:
Pas 1 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3
Nod curent 1 2 3 4 5 6 7 8
Coada 1 - 23 3 34 4 456 56 56 6 678 78 78 8 8 -
I
ED

Nodurile sunt parcurse n ordinea: 1, 2, 3, 4, 5, 6, 7, 8.


300 Implementarea structurilor de date

C
Pentru implementarea algoritmului se folosesc subprogramele:
funcia procedural citire creeaz vectorul t (vectorul tat) prin preluarea infor-
maiilor din fiier;

I
funcia operand rad determin rdcina r a arborelui;

OG
funcia procedural init iniializeaz coada de ateptare cu rdcina;
funcia operand este_vida testeaz coada de ateptare dac este vid;
funcia procedural adauga adaug un nod la coada de ateptare;
funcia procedural elimina elimin nodul prelucrat din coada de ateptare;

AG
funcia procedural prelucrare prelucreaz primul nod din coad: adaug la coada de
atepare toi fiii acestui nod i apoi l elimin din coada de ateptare;
funcia procedural afisare afieaz nodurile arborelui n ordinea prelucrrii.
#include <fstream.h>

ED
int t[20],n,c[20],prim,ultim;
fstream f("arbore.txt",ios::in);
void citire() {f>>n; for (int i=1;i<=n;i++) f>>t[i]; f.close();}
int rad()
{for (int i=1;i<=n;i++) if (t[i]==0) return i;

P
return 0;} //n caz de eroare nu exist nod rdcin
void init (int k) {prim=ultim=1; c[ultim]=k;}
int este vida() {return ultim<prim;}
I
void adaug(int i) {ultim++; c[ultim]=i;}
void elimina() {prim++;}
void prelucrare()

{int r=c[prim];
for (int i=1;i<=n;i++) if (t[i]==r) adaug(i); elimina();}
void afisare() {for (int i=1;i<=n;i++) cout<<c[i]<<" ";}
IC

void main() {int r; citire(); r=rad(); init(r);


while (!este vida()) prelucrare(); afisare();}
CT

b) Algoritmul de parcurgere n adncime


Metoda: pornind de la nodul rdcin se prelucreaz fiii unui nod de la stnga la dreapta,
iar trecerea, de la nodul curent la fratele din dreapta, se face numai dup ce au fost vizitai
DA

toi descendenii nodului curent, deci ai ntregului subarbore dezvoltat din acesta. n funcie
de ordinea relativ de prelucrare a nodului rdcin i, respectiv, a subarborilor, exist doi
algoritmi:
Algoritmul de parcurgere n preordine. Informaia din nodul rdcin este prelucrat
DI

naintea informaiilor din celelalte noduri ale subarborilor. Implementarea arborelui se


face prin referine descendente.
Algoritmul de parcurgere n postordine. Informaia din nodul rdcin este prelucrat
dup ce au fost prelucrate informaiile din toate celelalte noduri ale subarborilor. Imple-
RA

mentarea arborelui se face prin referine ascendente.


Algoritmul de parcurgere n preordine
Structura de date folosit este stiva (st) n care informaia este format din perechi (nod
TU

tat, urmtorul fiu neprelucrat al acestuia). Iniial, se consider c nodul prelucrat este
nodul rdcin. Notm: NC = nod curent
NP = nod prelucrat (nodul care s-a vizitat)
PFNNC = primul fiu neprelucrat al nodului curent
I

PFNNP = primul fiu neprelucrat al nodului prelucrat


ED
Informatic 301

C
n vrful stivei se va memora perechea (NP, PFNNP).
Algoritmul pentru parcurgerea arborelui este urmtorul:
PAS1. Se iniializeaz stiva cu perechea (nodul rdcin, primul fiu al rdcinii).

I
PAS2. Ct timp stiva nu este vid (mai exist noduri n stiv) execut:

OG
PAS3. Se extrag informaii din vrful stivei despre:
Nodul prelucrat devine nod curent NCst[vf].NP (la prima parcurgere NC1).
Primul fiu neprelucrat al nodului prelucrat devine primul fiu neprelucrat al
nodului curent PFNNCst[vf].PFNNP (la prima parcurgere PFNNC3).

AG
Primul fiu neprelucrat al nodului curent devine nod prelucrat NPPFNNC
(la prima parcurgere NP2).
Primul fiu neprelucrat al nodului prelucrat devine primul fiu neprelucrat al
nodului prelucrat PFNNPst[vf].PFNNP (la prima parcurgere PFNNP4).

ED
PAS4. Dac nodul curent mai are i ali fii neprelucrai, atunci la stiv se adaug
perechea (NC, PFNNC). La prima parcurgere perechea este (1,3).
PAS5. Dac nodul prelucrat nu este nod terminal i mai are i ali fii neprelucrai,
atunci la stiv se adaug perechea (NP, PFNNP). La prima parcurgere

P
perechea este (2,4).
Exemplu. Stiva la parcurgerea arborelui A6 din figura 64:
I
PAS Stiv NC NP PFNNC PFNNP
1 (1,2) 1 2
3 - 1 2 3 4
4 (1,3) 1 2 3 4

5 (1,3); (2,4) 1 2 3 4
3 (1,3) 2 4 - -
IC

4 (1,3) 2 4 - -
5 (1,3) 2 4 - -
CT

3 - 1 3 - 5
4 - 1 3 - 5
5 (3,5) 1 3 - 5
3 - 3 5 6 7
DA

4 (3,6) 3 5 6 7
5 (3,6); (5,7) 3 5 6 7
3 (3,6) 5 7 8 -
4 (3,6);(5,8) 5 7 8 -
DI

5 (3,6); (5,8) 5 7 8 -
3 (3,6) 5 8 - -
4 (3,6) 5 8 - -
5 (3,6) 5 8 - -
RA

3 - 3 6 - -
4 - 3 6 - -
5 - 3 6 - -
TU

Nodurile sunt parcurse n ordinea: 1, 2, 4, 3, 5, 7, 8, 6.


Pentru implementarea algoritmului se folosesc subprogramele:
funcia procedural citire creeaz vectorul t (vectorul tat) prin preluarea infor-
maiilor din fiier;
I
ED

funcia operand rad determin rdcina r a arborelui;


302 Implementarea structurilor de date

C
funcia operand nodt verific dac un nod este nod terminal;
funcia procedural init iniializeaz stiva cu perechea (rdcin, primul fiul al rdcinii);
funcia operand este_vida testeaz stiva dac este vid;

I
funcia procedural adauga adaug un nod la stiv;

OG
funcia procedural elimina elimin nodul din vrful stivei;
funcia procedural prelucrare prelucreaz nodurile din vrful stivei astfel: nodul prelu-
crat devine nod curent, primul fiu neprelucrat al nodului curent devine nod prelucrat, afiea-
z nodul prelucrat, elimin perechea de noduri din vrful stivei, dac nodul curent mai are

AG
un fiu neprelucrat, adaug la stiv perechea (NC, PFNNC), iar dac nodul prelucrat nu
este nod terminal i mai are un fiu neprelucrat, adaug la stiv perechea (NP, PFNNP).
#include <fstream.h>
struct stiva {int NP, PFNNP;};

ED
stiva st[20];
int t[20],n,vf;
fstream f("arbore.txt",ios::in);
int nodt(int x)
{for (int i=1;i<=n;i++) if (t[i]==x) return 0;

P
return 1;}
void init (int r)
{int i=1; vf=1;
I
while (i<=n && t[i]!=r) i++;
st[vf].NP=r; st[vf].PFNNP=i;}
int este vida() {return vf==0;}
void adaug(int x, int y) {vf++; st[vf].NP=x; st[vf].PFNNP=y;}

void elimin() {vf--;}


void prelucrare()
IC

{int NC=st[vf].NP,PFNNC=st[vf].PFNNP,NP=PFNNC,PFNNP,i=PFNNC+1;
cout<<NP<<" "; PFNNP=st[vf].PFNNP; elimin();
while (i<=n && t[i]!=NC) i++;
CT

if (i<=n) {PFNNC=i; adaug(NC,PFNNC);}


if (!nodt(NP))
{i=PFNNP+1; while (i<=n && t[i]!=NP) i++;
if (i<=n) {PFNNP=i; adaug(NP,PFNNP);}}}
DA

void citire(){f>>n; for (int i=1;i<=n;i++) f>>t[i]; f.close();}


int rad()
{for (int i=1;i<=n;i++) if (t[i]==0) return i;
return 0;}
DI

void main()
{int r; citire(); r=rad(); init(r); cout<<"Nodurile vizitate: "<<r<<" ";
while (!este vida()) prelucrare();}
Prin parcurgerea n lime a unui arbore cu rdcin, prelucrarea
RA

Atenie informaiilor din noduri se face pe niveluri ierarhice, iar prin


parcurgerea n adncime n preordine a unui arbore, prelucrarea
informaiilor din noduri se face dup relaiile de subordonare.
TU

Algoritmul de parcurgere n postordine


Nodului rdcin i se va atribui cea mai mare etichet. Prelucrarea se face prin parcur-
gerea simultan a celor doi vectori i cutarea nodurilor care aparin aceluiai subarbore.
Evidena nodurilor prelucrate este inut prin intermediul vectorului vizitat (care este
I
ED

definit la fel ca i la algoritmii de parcurgere a grafurilor).


Informatic 303

C
Algoritmul pentru parcurgerea arborelui n postordine este urmtorul:
PAS1. Se iniializeaz cu 0 elementele vectorului vizitat.
PAS2. Ct timp mai sunt noduri nevizitate execut:

I
PAS3. Se caut n vectorul t indicele k al primului nod terminal nevizitat.

OG
PAS4. Se prelucreaz nodul t[k] i se declar vizitat.
PAS5. Pentru toate nodurile t[i] frate cu nodul t[k] execut
PAS6. Se prelucreaz nodul t[i] i se declar vizitat.
PAS7. Se prelucreaz printele nodului t[k] (pt[k]) i se declar vizitat.

AG
Pentru implementarea algoritmului se folosesc subprogramele:
funcia procedural citire creeaz vectorii t i pt prin preluarea informaiilor din fiier;
funcia operand terminat verific dac au fost prelucrate toate nodurile arborelui;
funcia procedural prelucrare prelucreaz nodurile unui subarbore, pornind de

ED
la nodul terminal cu cea mai mic etichet.
#include <fstream.h>
int t[20],pt[20],vizitat[20],n;
fstream f("arbore.txt",ios::in);

P
void citire()
{int i; f>>n; for (i=1;i<=n;i++) f>>t[i];
for (i=1;i<=n;i++) f>>pt[i]; f.close();}
I
int terminat()
{for (int i=1;i<n;i++) if (!vizitat[i]) return 0;
return 1;}
void prelucrare()

{int i,k;
for (i=1;i<n && vizitat[t[i]];i++);
IC

k=i; vizitat[t[k]]=1; cout<<t[k]<<" ";


for (i=k+1;i<n;i++)
if (pt[i]==pt[k]) {cout<<t[i]<<" "; vizitat[t[i]]=1;}
CT

cout<<pt[k]<<" "; vizitat[pt[k]]=1;}


void main() {citire(); cout<<"Nodurile vizitate sunt: ";
while (!terminat()) prelucrare();}
Exemplu n nodurile unui arbore se memoreaz eticheta nodului i un numr. La numrul
DA

memorat n fiecare nod se adun suma numerelor memorate n nodurile descendente. S se


afieze noua valoare memorat n fiecare nod. Pentru a putea calcula aceste sume,
parcurgerea arborelui trebuie s se fac n postordine, cu ajutorul vectorilor t i pt. Numerele
din fiecare nod vor fi memorate n vectorul c. Informaiile necesare se citesc dintr-un fiier
DI

text, astfel: de pe primul rnd numrul de noduri n, iar de pe urmtoarele trei rnduri, cele n
valori memorate n vectorii t, pt i c. Pe un rnd, numerele sunt separate prin spaiu.
#include <fstream.h>
RA

int t[20],pt[20],c[20],n;
fstream f("arbore.txt",ios::in);
void citire() //se citesc datele din fisier
{int i; f>>n; for (i=1;i<=n;i++) f>>t[i];
for (i=1;i<=n;i++) f>>pt[i]; for (i=1;i<=n;i++) f>>c[i]; f.close();}
TU

void prelucrare(){for (int i=1;i<=n;i++) c[pt[i]]=c[pt[i]]+c[t[i]];}


void afisare()
{for (i=1;i<=n;i++)
cout<<"Nodul "<<i<<" are totalul "<<c[i]<<endl;}
I

void main() {citire(); prelucrare(); afisare();}


ED
304 Implementarea structurilor de date

C
n nodurile unui arbore cu rdcin sunt memorate numere naturale.
Tem Informaiile despre arbore se citesc dintr-un fiier text, astfel: de pe primul
rnd numrul de noduri ale arborelui, de pe rndul al doilea vectorul tat, i

I
de pe al treilea rnd, n ordinea etichetelor, numerele memorate n noduri. Scriei un

OG
program care s calculeze suma numerelor pare memorate n arbore.

2.8.3.4. Aplicaii practice


1. Construii arborele genealogic al familiei, care s prezinte filiaia (descendenii direci ai

AG
unei persoane). Se va lua ca nod rdcin unul dintre str-strbunici. n fiecare nod se
va memora numele unei persoane. Informaiile despre arbore se citesc dintr-un fiier text,
astfel: de pe primul rnd numrul de noduri ale arborelui, de pe rndul urmtor vectorul
tat, i de pe al treilea rnd, n ordinea etichetelor, numele memorate n noduri. Scriei

ED
un program care s furnizeze urmtoare informaii:
a. Pentru un nume de persoan, citit de la tastatur, s se afieze descendenii direci i
ci copii are fiecare.
b. Pentru dou nume de persoan, citite de la tastatur, s se afieze strmoul comun.

P
2. O fabric de confecii este format din mai multe compartimente. ntre compartimente
exist fie relaii de subordonare, fie relaii de colaborare (relaiile de colaborare se
stabilesc pe acelai nivel ierarhic). n figura 65 este prezentat organigrama firmei. Fiecare
I
compartiment are urmtoarele atribute: numele compartimentului, numele persoanei care
conduce acel compartiment i numrul de angajai.
Fabrica de confecii

Direcia general
IC

Confecii brbai Confecii femei Confecii copii

.......... Compartiment operaional Compartiment marketing


CT

Creaie Croit Confecionat Finisat Zona 1 Zona 3

Fig. 65
a. Afiai lista angajailor care au funcii de conducere (numele compartimentului i
DA

numele persoanei) n dou moduri:


punnd n eviden relaiile de subordonare;
grupnd persoanele de pe acelai nivel ierarhic.
b. Afiai lista angajailor care au funcii de conducere i numrul total de angajai pe care
DI

i are fiecare dintre ei n subordine (o persoan cu funcie de conducere are n


subordine angajaii din compartimentul pe care l conduce i din toate compartimentele
subordonate acestuia).
RA

3. O reea de distribuie a produselor unei firme are o organizare piramidal n care fiecare
dintre agenii comerciali are n subordine ali ageni comerciali. n funcie de vnzri,
fiecare agent comercial primete un punctaj. Un agent comercial care are n subordine i
ali ageni comerciali cumuleaz la punctajul propriu i punctajele agenilor comerciali din
TU

subordine. Scriei un program care s afieze urmtoarele informaii:


a. punctajul total al reelei;
b. care este subordonatul direct al unui agent comercial (al crui nume se precizeaz
de la tastatur) care are punctajul cel mai mare i care este acest punctaj.
I
ED
Informatic 305

C
4. Angajaii unei firme dispun de o sum pentru prime distribuit astfel: directorul general
i stabilete prima i restul sumei o distribuie n mod egal subordonailor lui direci.
Orice subordonat care a primit o sum i stabilete singur prima (o parte sau ntreaga

I
sum primit) restul sumei fiind distribuit n mod egal subordonailor si direci, iar

OG
angajaii care nu au subordonai rein ntreaga sum pe care o primesc. tiind c orice
subordonat are un singur ef, scriei un program de distribuire a primelor i afiai lista
angajailor i primele primite. Pentru prima pe care o stabilete pentru sine un angajat,
folosii generatorul de numere aleatoare, care va genera un numr ntre 0 i suma

AG
primit pentru prime pentru a o distribui.
(Sesiunea august Bacalaureat 2003 adaptat)

Arbori multici.
Sunt arbori cu rdcin, la care nu exist o

ED
Arbori cu rdcin limit pentru ordinul nodurilor.
criteriul de clasificare folosit este
ordinul nodurilor Arbori binari
Sunt arbori cu rdcin, la care ordinul

P
fiecrui nod nu trebuie s fie mai mare de 2.

2.8.4. Arborele binar


I
2.8.4.1. Definiia arborelui binar
Se numete arbore binar un arbore cu rdcin poziional care are

proprietatea c fiecare nod are cel mult doi descendeni direci (succesori).
IC

Terminologie:
Cei doi succesori ai unui nod (dac exist) se numesc succesor stng (subarbore
stng) i succesor drept (subarbore drept) arborele A7 din figura 66. A
A
A777
CT

Caracteristici:
Deoarece, oricare ar fi un nod al arborelui, el nu
are mai mult de doi descendeni direci, ordinul
DA

unui nod dintr-un arbore binar poate fi 0 (nod


terminal), 1 (unul dintre subarbori este vid) sau 2.
Definiia arborelui binar este o definiie recursiv.
Exist un nod privilegiat numit nod rdcin, iar
DI

celelalte noduri (dac exist) sunt repartizate n


dou grupuri disjuncte i, fiecare dintre aceste
grupuri formeaz, la rndul su, un arbore binar.
RA

Observaie. Arborele binar fiind un arbore cu rdci-


n poziional, se face diferen ntre succesorul Fig. 66
stng i succesorul drept, adic, dac un nod are un singur descendent, trebuie s se
precizeze care dintre descendeni este. n figura 67 sunt prezentai doi
TU

arbori binari Ab1 i Ab2 care sunt diferii, chiar dac au dou noduri i
rdcina n nodul cu eticheta A. n arborele Ab1 succesorul stng are un
nod (B), iar succesorul drept este arborele vid, iar n arborele Ab2
succesorul stng este arborele vid, iar succesorul drept are un nod (B). Fig. 67
I
ED
306 Implementarea structurilor de date

C
Cu 3 noduri, etichetate cu A, B i C, se obin 30 de arbori
binari diferii. Exist trei moduri de a alege rdcina. Pentru
un nod rdcin ales, se pot obine zece arbori binari diferii

I
n total se vor obine 310=30 arbori binari diferii. n

OG
figura 68 sunt prezentai 6 dintre arborii binari care au
rdcina n nodul A.
Se numete arbore binar stict un arbore care are
proprietatea c fiecare nod, cu excepia nodurilor

AG
terminale, are exact doi descendeni (succesori).
A
A
A888 Exemplu Arborele binar A8 din figura 69
Fig. 68
Propoziia 17

ED
Un arbore binar strict, care are n noduri terminale, are n total 2n-1 noduri.
Demonstraie Notm cu k numrul de nivele din arbore, cu xk, xk-1, , x2, x1, numrul de noduri
terminale de pe fiecare nivel, i cu yk, yk-1, , y2, y1, numrul de noduri de pe fiecare nivel (cu
excepia nivelului 0, pe care se gsete rdcina) i cu N numrul total de noduri din arbore (N =

P
yk+ yk-1++y2+y1+1), cu n numrul total de noduri terminale (n = xk+xk-1++ x2+x1). Nivelul k
conine numai noduri terminale, i yk = xk. Pentru fiecare alt nivel exist relaia: yi = yi+1/2 + xi.
Arborele fiind strict, yi+1/2 este un numr ntreg, deoarece pe fiecare nivel
I
exist un numr par de noduri. Adunnd relaiile, obinem:
yk = xk
yk-1 = yk/2 + xk-1
yk-2 = yk-1/2 + xk-2

..
y2 = y3/2 + x2
IC

y1 = y2/2 + x1 Fig. 69
Rezult c: N = 1+yk+yk-1+ +y2+y1+y0 = 1+2(xk+xk-1+ +x2+x1) = 2n+1
Propoziia 16. Un arbore binar strict are un numr impar de noduri.
CT

Demonstraie Pe fiecare nivel k+1, pentru fiecare nod de pe nivelul k,


exist cte doi descendeni sau nici un descendent. Rezult c pe fiecare
nivel, cu excepia nivelului 0, exist un numr par de noduri. Numrul total
DA

de noduri va fi impar, deoarece la aceste noduri se adaug i nodul


rdcin.
Se numete arbore binar echilibrat un arbore binar care are
proprietatea c diferena dintre nlimile celor doi subarbori ai Fig. 70
DI

oricrui nod este cel mult 1.


A
A
A999 Exemplu Arborele A9 din figura 70.
Se numete arbore binar perfect echilibrat un arbore binar care
RA

are proprietatea c diferena dintre numrul nodurilor celor doi


subarbori ai oricrui nod este cel mult 1.
A
A
A111000 Exemplu Arborele A10 din figura 71
Fig. 71
TU

Proprietate. Un arbore binar cu n noduri este perfect echilibrat


dac subarborele stng are [n/2] noduri, iar subarborele drept are n-[n/2]-1 noduri.
Se numete arbore binar complet un arbore binar strict care are
toate nodurile terminale pe acelai nivel.
I

A
ED

A
A111111 Exemplu Arborele A11 din figura 72
Informatic 307

C
Propoziia 19. Un arbore binar complet, care are n noduri
terminale, are n total 2n-1 noduri.
Demonstraie Folosind principiul induciei matematice, demonstrm

I
k
c, ntr-un arbore binar complet, pe nivelul k sunt 2 noduri (se noteaz

OG
cu Pi propoziia i).
0
P0 Pe nivelul 0 exist un singur nod (nodul rdcin), adic 2 =1 nod.
1 Fig. 72
P1 Pe nivelul 1 exist dou noduri, adic 2 = 2 noduri.
.
k

AG
Pk Pe nivelul k exist 2 noduri..
k+1
Pk+1 Considernd propoziia Pk adevrat, trebuie s demonstrm c pe nivelul k+1 exist 2
noduri. Dac nivelul k+1 aparine arborelui, atunci pe acest nivel exist cte doi descendeni pentru
k k+1
fiecare nod de pe nivelul k, n total 22 =2 noduri.
Considernd c arborele are k niveluri i c numrul de noduri de pe nivelul k este n, numrul total de

ED
noduri din arbore se obine adunnd nodurile de pe cele k niveluri:
20 + 21 + 22 + + 2k = 2k+11= 2(2k) 1= 2n 1
Se numete arbore binar aproape complet un arbore binar

P
complet pn la penultimul nivel, la care completarea cu noduri,
pe ultimul nivel, se face de la stnga la dreapta.
Exemplu Arborele A12 din figura 73 A
A
A111222
I
Fig. 73

Scop: identificarea coleciilor de date care pot fi reprezentate prin arbori binari.
Enunul problemei 1. Trebuie s se organizeze un campionat de meciuri de baschet
IC

ntre echipele mai multor licee. Numrul de echipe este n. n fiecare duminic se
organizeaz un meci. Echipele care vor juca n prima etap se trag la sori. S se
realizeze planificarea meciurilor i s se determine numrul de duminici n care se va
CT

desfura campionatul (figura 74).


Campionatul are o structur ierarhic, iar
relaiile dintre componente pot fi repre-
zentate cu ajutorul unui arbore binar, n
DA

care cele dou echipe care joac sunt


nodurile. Nodurile terminale sunt echipele
liceelor, iar celelalte noduri reprezint cte o
echipa care a ctigat n meciul etapei
DI

Fig. 74
anterioare. Rdcina arborelui este echipa
care ctig finala. Deoarece o echip ctigtoare se desemneaz n urma unui meci
jucat, nodurile care nu sunt terminale reprezint meciuri jucate, iar nodul rdcin cores-
RA

punde meciului final. Arcele reprezint relaia de participare a unei echipe la un meci.
Arborele meciurilor este un arbore binar strict (la un meci particip dou echipe). Dac
arborele meciurilor este un arbore binar complet i la campionat particip n echipe, vor
fi n noduri terminale i arborele va avea 2n-1 noduri. Numrul de meciuri care se vor
TU

juca este dat de diferena dintre numrul total de noduri ale arborelui i numrul de noduri
terminale, adic n-1 meciuri, iar campionatul se va desfura n n-1 duminici.
Enunul problemei 2. S se reprezinte modul n care se evalueaz o expresie aritmetic.
O expresie aritmetic este format din operanzi (constante i variabile), operatori aritme-
I
ED

tici (+, -, /, * i ^ pentru ridicarea la putere) i paranteze. n evaluarea expresiei aritme-


308 Implementarea structurilor de date

C
tice se respect prioritatea operatorilor aritmetici. Operatorii aritmetici sunt
operatori binari care nu sunt toi comutativi (operatorii pentru scdere,
mprire i ridicare la putere nu sunt comutativi). Dac notm operanzii cu

I
x i y i operatorul cu op, atunci expresiei E = x op y putem s-i asociem

OG
arborele binar din figura 75, n care rdcina este operatorul op, subar- Fig. 75
borele stng este primul operand x, iar subarborele drept este al doilea
operand y. Dac expresia conine un singur operand, acestuia i se poate asocia un
arbore binar cu un singur nod nodul rdcin n care se memoreaz operandul. Pentru

AG
a putea reprezenta o expresie care este format cu un operator unar (de exemplu, E=x),
vom transforma expresia astfel nct s conin un operator binar (n exemplu, E=0x).
Expresia are o structur ierarhic, iar relaiile dintre componente pot fi reprezentate cu ajutorul
unui arbore binar, n care operanzii i operatorii sunt nodurile. Nodurile terminale sunt ope-

ED
ranzii, iar celelalte noduri reprezint operatorii. Rdcina arborelui este operatorul care se
evalueaz ultimul. Subarborele stng i subarborele drept ai rdcinii reprezint expresiile
crora li se aplic ultimul operand. Rdcina fiecrui subarbore va reprezenta operatorul care
se aplic pe cele dou expresii reprezentate prin subarborii
Fig. 76

P
stng i drept ai si. Arcele reprezint relaia de participare a
unei expresii la operatorul din nodul printe: ca prim operand
sau ca al doilea operand. Arborele expresiei este un arbore
I
binar strict (un operator leag doi operanzi). Dac expresia
conine n operanzi, arborele va avea n noduri terminale. Fiind
un arbore binar strict, va avea 2n-1 noduri. Numrul de
operatori este dat de diferena dintre numrul total de noduri

ale arborelui i numrul de noduri terminale, adic n-1


IC

operatori. Arborele expresiei nu este un arbore echilibrat.


Arborele binar din figura 76 este arborele expresiei aritmetice:
( x 2 4 y ) x
CT

E 5
zy y

Desenai 5 arbori binari cu trei noduri (etichetate cu A, B i C) diferii, alii


Tem
DA

dect cei din figura 69.


1. Desenai arborele genealogic al strmoilor unei persoane pn la
nivelul str-strbunici. Rdcina este persoana pentru care se ntocmete arborele
genealogic. Fiecare nod are doi descendeni: mama i tata. Ce tip de arbore binar este?
DI

Comparai acest arbore cu arborele genealogic al descendenilor (arborele filiaiei).


2. Desenai arborele campionatului de baschet pentru 7 echipe. Ce fel de arbore binar este?
a2 b
3. Desenai arborele binar al expresiei 7 (a b )
cd
RA

2.8.4.2. Implementarea arborelui binar


Implementarea structurilor de date de tip arbore binar se poate face:
a. static folosind vectori;
TU

b. dinamic folosind pointeri.


Fig. 77
a) Implementarea static a arborelui binar
Exist dou metode de implementare static a arborilor binari (se folosete arborele
I

A
A
ED

A111333 binar A13 din din figura 77).


Informatic 309

C
1. Folosind doi vectori n care se memoreaz cei doi succesori ai unui nod:
vectorul st n elementul i se memoreaz eticheta nodului succesor stng al
nodului i;

I
vectorul dr n elementul i se memoreaz eticheta nodului succesor drept al

OG
nodului i.
Dac nodul i nu are succesor stng, respectiv drept, elementul din vectorul st,
respectiv dr, va avea valoarea 0.
Pentru arborele A13 din figura 77 cei doi vectori sunt:

AG
Nodul i 1 2 3 4 5 6 7 8 9
st[i] 2 3 0 0 0 7 0 9 0
dr[i] 4 6 0 5 0 8 0 0 0

ED
Observaie. Din cei doi vectori putei obine urmtoarele informaii:
eticheta nodului rdcin r nodul i pentru care, oricare ar fi indicele j, st[j]i i
dr[j]i (nodul a crui etichet nu exist nici n vectorul st, nici n vectorul dr);
etichetele nodurilor terminale nodurile i pentru care st[i]+dr[i]=0;

P
eticheta printelui unui nod i indicele j pentru care st[j]=i sau dr[j]=i;
etichetele fiilor unui nod i st[i] i dr[i] (dac sunt diferii de 0);
eticheta fratelui unui nod i st[j] pentru dr[j]=i sau dr[j] pentru st[j]=i.
I
2. Folosind doi vectori n care se memoreaz filiaia nodurilor:
vectorul tata n elementul i se memoreaz numrul de ordine al nodului predece-
sor (printe) al nodului i;

vectorul fii (n elementul i se memoreaz ce fel de succesor al printelui este; dac


fii[i]=1, atunci nodul i este succesorul stng al printelui su, iar dac fii[i]=1,
IC

atunci nodul i este succesorul drept al printelui su.


Dac nodul i este nodul rdcin, elementul din vectorul tata, respectiv fii, va avea
valoarea 0.
CT

Pentru arborele A13 din figura 77 cei doi vectori sunt:


Nodul i 1 2 3 4 5 6 7 8 9
tata[i] 0 1 2 1 4 2 6 6 8
DA

fii[i] 0 -1 -1 1 1 1 1 -1 -1
Observaie. Din vectorul tat putei obine urmtoarele informaii:
eticheta nodului rdcin r indicele i pentru care tata[i]=0;
etichetele nodurilor terminale nodurile i a cror etichet nu exist n vectorul tata;
DI

eticheta printelui unui nod i tata[i];


etichetele fiilor unui nod i fiul stng: indicele j pentru care tata[j]=i i fii[j]=-1, iar fiul
drept: indicele j pentru care tata[j]=i i fii[j]=1;
RA

eticheta fratelui unui nod i indicele j pentru care tata[i]=tata[j].


Observaie. Datorit definiiei arborilor binari, algoritmii utilizai pentru prelucrarea lor pot
folosi tehnica recursivitii (definiia recursiv a arborilor binari) i strategia divide et
impera (fiecare nod nu are dect doi descendeni prelucrarea unui nod se descompune
TU

n dou subprobleme: prelucrarea subarborelui stng i prelucrarea subarborelui drept,


urmat de compunerea celor dou soluii).
Exemple dac pentru arborele binar se folosete implementarea static, pentru a
I

construi algoritmi recursivi cu strategia divide et impera se utilizeaz vectorii st i dr.


ED
310 Implementarea structurilor de date

C
nlimea arborelui binar Numrul de frunze din arborele binar
int max(int x, int y) int frunza(int i)
{if (x>y) return x; else return y;} {return st[i]+dr[i]==0;}

I
int h(int i) int nr_fr(int i)

OG
{if (st[i]==0 && dr[i]==0) return 0; {if (frunza(i)) return 1;
else else
return 1+max(h(st[i]),h(dr[i]));} if (st[i]==0)
void main() return nr frunze(dr[i]);
{int r; ... cout<<h(r); ... } else

AG
if (dr[i]==0)
return nr frunze(st[i]);
else
return nr fr(st[i])+nr fr(dr[i]);}
void main()

ED
{int r; ... cout<<nr fr(r); ... }
1. Scriei un program care s furnizeze urmtoarele informaii despre un
Tem arbore binar: nodul rdcin, nodurile terminale, nodurile cu exact un

P
fiu, nodurile cu exact doi fii, nodurile frai i nlimea. Informaiile
despre arbore (numrul de noduri i cei doi vectori) se vor citi dintr-un fiier. Arborele
este implementat:
I
a. cu vectorii n care se memoreaz cei doi succesori ai unui nod;
b. cu vectorii n care se memoreaz filiaia nodurilor.
2. Scriei un program care citete dintr-un fiier numrul de noduri i vectorii st i dr ai unui

arbore binar. S se reprezinte arborele prin vectorii tata i fii.


3. Scriei un program care citete dintr-un fiier numrul de noduri i vectorii tata i fii ai
IC

unui arbore binar. S se reprezinte arborele prin vectorii st i dr.


4. Scriei un program care citete dintr-un fiier numrul de noduri i vectorii st i dr ai unui
arbore binar. S se verifice dac arborele binar este un arbore binar strict.
CT

5. Scriei un program care citete dintr-un fiier numrul de noduri i vectorii st i dr ai unui
arbore binar. S se verifice dac este un arbore binar perfect echilibrat sau un arbore
binar echilibrat.
DA

b) Implementarea dinamic a arborelui binar


Se face prin definirea unui tip de dat pentru un nod din arbore (tipul nod) i a adresei unui
nod (un pointer ctre tipul de dat nod nod*). Tipul de dat este definit ca o nregistrare
care conine 3 categorii de cmpuri:
DI

informaia util poate fi compus din mai multe cmpuri (<tip> info);
adresa subarborelui stng (nod *s s este adresa rdcinii subarborelui stng);
adresa subarborelui drept (nod *d d este adresa rdcinii subarborelui drept).
RA

struct nod {<tip> info:;


nod *s,*d;};
nod *r; //r=adresa rdcinii
Trebuie precizate n fiecare moment poziiile a trei componente: rdcina (*r) i cei
TU

doi subarbori (*s i *d).


Regul. ntotdeauna este reprezentat subarborele stng i apoi subarborele drept.
Dac un nod nu are un succesor, succesorul va fi considerat arborele vid.
I
ED

Se numete arbore vid un arbore care are adresa NULL.


Informatic 311

C
Exemplul 1 Pentru un arbore binar pe care-l construim pentru campionatul de meciuri de
baschet ntre echipele mai multor licee, informaia util poate fi format din mai multe
cmpuri: numele echipei (n e), numele liceului (n l) i eticheta nodului (nr):

I
struct nod {char n e[15],n l[15];

OG
int nr;
nod *s,*d;} *r;
Exemplul 2 Pentru exemplele urmtoare, informaia util va fi format numai din eticheta
nodului:

AG
struct nod {int nr;
nod *s,*d;};
nod *r;
n figura 78 este prezentat imple-

ED
mentarea dinamic a arborelui A13 din
figura 77. Fig. 78

Algoritmul pentru crearea unui arbore binar

P
Agoritmul pentru crearea unui arbore binar implementat dinamic folosete strategia
divide et impera prin descompunerea problemei n trei subprobleme:
I
1. crearea nodului rdcin (cazul de baz);
2. crearea subarborelui stng;
3. crearea subarborelui drept.
Descompunerea problemei continu pn cnd subarborele care se creeaz este arborele

vid. Combinarea soluiilor se face prin legarea nodului rdcin de cei doi subarbori.
IC

Dac datele se citesc de la tastatur, pentru a evidenia c nodul care se creeaz este
rdcina unui arbore vid, n cmpul pentru etichet se introduce valoarea 0 (care mar-
cheaz lipsa de informaii pentru acel nod). De exemplu, pentru a crea arborele din figura
CT

79, se introduc n ordine, de la tastatur, etichetele: 1 2 3 0 0 6 7 0 0 8 9 0 0 0 4 0 5 0 0.


Algoritmul pentru crearea arborelui binar este:
PAS1. Se citete informaia util din nod.
PAS2. Dac nodul nu conine informaie util, atunci se creeaz arborele vid; altfel:
DA

PAS3. Se creeaz un nod rdcin prin alocarea unei zone de memorie.


PAS4. Se atribuie, cmpului cu informaie din nod, informaia citit.
PAS5. Se creeaz subarborele stng.
PAS6. Se creeaz subarborele drept.
DI

Subprogramul care creeaz un arbore binar poate fi implementat ca funcie procedural


sau ca funcie operand.
Funcie procedural Funcie operand
RA

void creare(nod *&r) nod *creare()


{int n; {int n; nod *r;
cout<<"Eticheta nod: "; cin>>n; cout<<"Eticheta nod: "; cin>>n;
if (n==0) r=NULL; if (n==0) return NULL;
TU

else {r = new nod; else {r = new nod;


r->nr=n; r->nr=n;
creare(r->s); r->s=creare();
creare(r->d);}} r->d=creare();
I

return r;}}
ED
312 Implementarea structurilor de date

C
void main() void main()
{creare(r); {r=creare();
cout<<"Radacina= "<<r->nr;... } cout<<"Radacina= "<<r->nr;... }

I
Exemple Funcii, implementate recursiv folosind strategia divide et impera, prin care se

OG
prelucreaz arbori binari.
nlimea arborelui binar Numrul de frunze ale arborelui binar
int max(int x, int y) int frunza(nod *r)
{if (x>y) return x; {return r->s==NULL && r->d==NULL;}

AG
else return y;} int nr fr(nod *r)
int h(nod *r) {if (r==NULL) return 0;
{if (r==NULL) return 0; else if (frunza(r)) return 1;
else else

ED
return 1+max(h(r->s),h(r->d));} return nr fr(r->s)+nr fr(r->d); }
Copierea unui arbore binar Compararea a doi arbori binari
nod *comb(int n,nod *s,nod *d) int egal(nod *r1,nod *r2)
{nod *c; c = new nod; c->nr=n; {if (r1==NULL) return r2==NULL;

P
c->s=s; c->d=d; return c;} else if (r2==NULL) return 0;
nod *copie(nod *c) else return
{if (c==NULL) return NULL; r1->nr==r2->nr &&
I
else return egal(r1->s,r2->s) &&
comb(c->nr,copie(c->s),copie(c->d));} egal(r1->d,r2->d);}
void main() void main()
{r1=creare(); r2=copie(r1); ... } {... if (egal(r1,r2)) ... }

Afiarea etichetelor de pe un nivel Verificarea existenei unui nod cu


IC

precizat eticheta precizat


void nivel(nod *r,int i,int k) int caut(nod *r,int k)
{if (r!=NULL) {if (r==NULL) return 0;
CT

{if (i==k) cout<<r->nr<<" "; else


nivel(r->s,i+1,k); if (r->nr==k) return 1;
nivel(r->d,i+1,k);}} else
void main() return caut(r->s,k)||caut(r->d,k);}
DA

{int k; r=creare(); void main()


cout<<"Nivelul: "; cin>>k; {int k; r=creare();
nivel(r,0,k);} cout<<"Nodul: "; cin>>k;
if (caut(r,k))
cout<<"A fost gasit";
DI

else cout<<"Nu a fost gasit";}


2.8.4.3. Algoritmi pentru parcurgerea unui arbore binar
RA

Parcurgerea unui arbore binar se poate face prin:


algoritmul de parcurgere n lime (la fel ca la grafuri);
algoritmi de parcurgere n adncime (specifici arborilor binari):
algoritmul RSD (traversarea n preordine);
TU

algoritmul SRD (traversarea n inordine);


algoritmul SDR (traversarea n postordine).
Observaie. Algoritmii pentru parcurgerea unui arbore binar pot fi folosii pentru a prelucra
informaiile din noduri.
I
ED
Informatic 313

C
Algoritmul RSD
Metoda: se prelucreaz rdcina, subarborele stng, subarborele drept (pentru arborele
A13 din figura 77 1 2 3 6 7 8 9 4 5).

I
Implementarea static Implementarea dinamic

OG
void rsd(int i) void rsd(nod *r)
{cout<<i<<" "; {if (r!=NULL)
if (st[i]!=0) srd(st[i]); {cout<<r->nr<<" ";
if (dr[i]!=0) srd(dr[i]);} rsd(r->s);

AG
void main() rsd(r->d);}}
{ ...rsd(r); cout<<endl; ...} void main()
{ ...rsd(r); cout<<endl; ...}
Algoritmul SRD

ED
Metoda: se prelucreaz subarborele stng, rdcina, subarborele drept (pentru arborele
A13 din figura 77 3 2 7 6 9 8 1 4 5).
Implementarea static Implementarea dinamic
void srd(int i) void srd(nod *r)

P
{if (st[i]!=0) srd(st[i]); {if (r!=NULL)
cout<<i<<" "; {srd(r->s);
if (dr[i]!=0) srd(dr[i]);} cout<<r->nr<<" ";
I
void main() srd(r->d);}}
{ ...srd(r); cout<<endl; ...} void main()
{ ...srd(r); cout<<endl; ...}

Algoritmul SDR
Metoda: se prelucreaz subarborele stng, subarborele drept, rdcina (pentru arborele
IC

A13 din figura 77 3 7 9 8 6 2 5 4 1).


Implementarea static Implementarea dinamic
void sdr(int i) void sdr(nod *r)
CT

{if (st[i]!=0) srd(st[i]); {if (r!=NULL)


if (dr[i]!=0) srd(dr[i]); {sdr(r->s);
cout<<i<<" ";} sdr(r->d);
void main() cout<<r->nr<<" ";}}
DA

{ ...sdr(r); cout<<endl; ...} void main()


{ ...sdr(r); cout<<endl; ...}
Observaie. Informaiile din nodurile arborelui binar, dup prelucrare, pot fi salvate ntr-un
fiier text. La o nou execuie a programului ele permit restaurarea arborelui pentru o nou
DI

prelucrare.
Exemplu pentru arborele creat anterior, etichetele nodurilor sunt salvate ntr-un fiier text
(sunt scrise pe un rnd, desprite prin spaiu) i la o nou execuie a programului sunt
RA

readuse n memoria intern:


Salvarea arborelui n fiierul text Restaurarea arborelui din fiierul text
fstream f("arbore.txt",ios::out); fstream g("arbore.txt",ios::in);
void salvare(nod *r) nod *restaurare()
TU

{if (r!=NULL) {int n; nod *r; g>>n;


{f<<r->nr<<" "; if (n==0) return NULL;
rsd(r->s); else {r = new nod;
rsd(r->d);} r->nr=n;
I

else f<<0<<" ";} r->s=restaurare();


ED
314 Implementarea structurilor de date

C
void main() r->d=restaurare();
{ ...salvare(r); ...} return r;}}
void main()

I
{ ...r=restuarare(r); ...}

OG
1. Scriei cte un subprogram pentru urmtoarele metode de parcurgere
Tem a arborilor binari: RDS (rdcin, subarbore drept, subarbore stng),
DRS (subarbore drept, rdcin, subarbore stng) i DSR (subarbore
drept, subarbore stng, rdcin).

AG
2. Scriei un program care citete succesiunea nodurilor afiate prin parcurgerea SDR i
prin parcurgerea RSD i afieaz etichetele nodurilor prin parcurgerea RSD.
3. Scriei o funcie iterativ pentru metoda de parcurgere RSD a arborilor binari.

ED
4. Scriei o funcie care afieaz numrul nivelului cu cele mai multe frunze.
5. Scriei o funcie care s verifice dac un arbore binar este perfect echilibrat.
6. Scriei un program care s furnizeze urmtoarele informaii despre un arbore binar:
nodul rdcin, nodurile terminale, nodurile cu exact un fiu, nodurile cu exact doi fii,

P
nodurile frai i nlimea. Arborele binar este implementat dinamic i crearea lui se face
prin introducerea informaiilor din noduri de la tastatur.
7. Scriei un program care creeaz un arbore binar implementat dinamic prin citirea etiche-
I
telor dintr-un fiier text (etichetele sunt scrise pe un rnd, desprite prin spaiu, n ordi-
nea n care ar fi fost introduse de la tastatur) i care verific dac arborele binar este
un arbore binar strict.

8. n nodurile unui arbore binar sunt memorate numere ntregi care nu sunt distincte. Scriei
un program care creeaz un arbore binar implementat dinamic prin citirea numerelor din-
IC

tr-un fiier text (numerele sunt scrise pe un rnd. desprite prin spaiu, n ordinea n care
ar fi fost introduse de la tastatur) i care creeaz o list dublu nlnuit care s conin
numai numerele distincte i, pentru fiecare numr, de cte ori apare n arbore.
CT

9. n nodurile unui arbore binar sunt memorate numere ntregi care nu sunt distincte.
Scriei un program care creeaz un arbore binar implementat dinamic prin citirea
numerelor dintr-un fiier text i care creeaz o list simpl, ordonat descresctor, care
DA

s conin numai numerele distincte.


10. n nodurile unui arbore binar sunt memorate numere naturale. Scriei un program care
s realizeze urmtoarele:
a. Creeaz arborele binar (implementat dinamic) prin introducerea numerelor de la
DI

tastatur.
b. Calculeaz suma numerelor pare din nodurile terminale.
c. Calculeaz suma numerelor pozitive din nodurile care au exact doi succesori.
d. Determin numrul cu valoarea cea mai mare i de cte ori apare n nodurile arborelui.
RA

e. Creeaz o list simplu nlnuit cu numerele din nodurile arborelui care au ultima
cifr 5 sau 3.
f. Afieaz pe ecran numerele de pe un nivel k (k se citete de la tastatur).
g. Salveaz, ntr-un fiier text, numerele de pe fiecare nivel (numerele de pe acelai
TU

nivel vor fi scrise pe un rnd, separate prin spaiu).


h. Creeaz un arbore cu aceeai structur arborescent ca cel creat la punctul (a) dar
care difer de el prin informaia din noduri: dac n primul arbore numrul este par, n
al doilea arbore este nlocuit cu suma cifrelor sale, iar dac n primul arbore numrul
I

este impar, n al doilea arbore este nlocuit cu inversul lui.


ED
Informatic 315

C
2.8.4.4. Aplicaii practice
1. Construii arborele genealogic al strmoilor familiei pn la nivelul str-strbunici
(prinii direci ai fiecrei persoane). Se va lua ca nod rdcin persoana pentru care se

I
OG
ntocmete arborele. n fiecare nod se va memora numele unei persoane (mama sau
tatl persoanei din nodul printe). Informaiile despre arbore se citesc dintr-un fiier text,
astfel: de pe primul rnd, numrul de noduri ale arborelui, de pe urmtoarele dou rnduri
vectorii st i dr, i de pe al patrulea rnd, n ordinea etichetelor, numele memorate n
noduri. Scriei un program care, pentru un nume citit de la tastatur, s afieze numele

AG
prinilor i numele bunicilor persoanei respective.
2. Construii arborele campionatului de meciuri de baschet. n fiecare nod se vor pstra
urmtoarele informaii: eticheta nodului, numele celor dou echipe, scorul fiecrei
echipe i data la care s-a jucat meciul. n nodurile terminale vor fi pstrate numai

ED
numele echipelor. Scriei un program care s asigure urmtoarea funcie: dup fiecare
meci, se va copleta informaia n fiecare nod: data la care s-a jucat meciul i scorul; pe
baza scorului, n nodul printe va fi scris numele echipei ctigtoare. Dup fiecare
execuie a programului, arborele trebuie salvat ntr-un fiier, de unde trebuie readus la

P
urmtoarea execuie.

2.8.5. Arborele binar de cutare


I
2.8.5.1. Definiia arborelui binar de cutare
Terminologie:

Se numete cheie un cmp din informaia util a nodului care poate fi folosit pentru a
IC

identifica unic nodurile arborelui.


Se numete arbore binar de cutare un arbore binar
care are proprietatea c, pentru fiecare nod, cheia din
CT

succesorul stng este mai mic dect cheia din nod,


iar cheia din succesorul drept este mai mare dect
cheia din nod.
DA

Exemplu Arborele binar A14 din figura 79. Fig. 79 A


A
A111444
Caracteristici:
Pentru orice nod, subarborele stng conine noduri cu valori mai mici ale cheii, iar
DI

subarborele drept conine noduri cu valori mai mari ale cheii.


ntr-un arbore binar de cutare nu exist dou noduri cu aceeai valoare a cheii.

Pentru mulimea de chei {2, 5, 7, 10, 12, 15, 23} desenai arborii binari de
Tem
RA

cutare cu nlimea 2, 3, 4, 5 i 6.

2.8.5.2. Algoritmi pentru prelucrarea unui arbore binar de cutare


Pentru prelucrarea unui arbore binar de cutare se pot folosi urmtorii algoritmi:
TU

Algoritmul pentru creare,


Algoritmii pentru parcurgere,
Algoritmii pentru actualizare.
I
ED
316 Implementarea structurilor de date

C
Algoritmul pentru crearea unui arbore binar de cutare
Crearea unui arbore binar de cutare se face prin adugarea fiecrui nod ca nod terminal, n

I
poziia corespunztoare, astfel nct arborele s nu-i piard proprietatea din definiie.

OG
Cutarea nodului la care se va aduga ca succesor nodul terminal i ce fel de succesor va fi
(stng sau drept) se face cu ajutorul unui pointer care va indica nodul curent care se
analizeaz. Nodul de la care se pornete este rdcina arborelui. Cu ajutorul acestui pointer
se avanseaz pe nivelurile arborelui prin succesorul stng sau succesorul drept al nodului
curent, n funcie de rezultatul comparaiei dintre valoarea citit pentru cheie i valoarea cheii

AG
din nodul curent. Avansarea continu pn cnd succesorul nodului curent la care a ajuns
pointerul este arborele vid. Algoritmul pentru crearea arborelui binar de cutare este:
PAS1. Se iniializeaz arborele cu arborele vid, atribuind rdcinii adresa NULL.
PAS2. Se citete informaia util, cu valoarea v pentru cheie.

ED
PAS3. Ct timp exist informaie util execut:
PAS4. Se iniializeaz nodul curent cu nodul rdcin.
PAS5. Dac nodul curent nu este un arbore vid, atunci se trece la Pasul 9.
PAS6. Se creeaz un nod prin alocarea unei zone de memorie.

P
PAS7. Se atribuie, cmpului cu informaie din nod, informaia citit.
PAS8. Se atribuie, succesorilor nodului, arborele vid. Se trece la Pasul 11.
I
PAS9. Dac v (cheia din informaie), este mai mic dect cheia nodului curent,
atunci nodul curent devine succesorul stng i se revine la Pasul 5.
PAS10. Dac v (cheia din informaie) este mai mare dect cheia nodului curent,
atunci nodul curent devine succesorul drept i se revine la Pasul 5;

altfel, se afieaz mesajul Cheia exista deja.


PAS11. Se citete informaia util cu valoarea v pentru cheie.
IC

Implementarea subprogramului prin care se adaug un nod la arbore s-a fcut recursiv.
Observaie. Dac se prelucreaz o mulime de valori numerice care nu sunt diferite ntre
CT

ele, se poate folosi arborele binar de cutare, adugnd la structura nodului un cmp n
care se numr frecvena de apariie a numrului n irul de valori (frecv):
struct nod {int nr,frecv;
nod *s,*d;};
DA

n acest mod, este respectat condiia de cheie unic impus de definiia arborelui binar de
cutare, n nodurile lui fiind memorate numai valorile unice ale cheii. Programul de creare a
unui arbore binar de cutare, n cele dou variante, este:
Valoarea pentru cheie este unic Valoarea pentru cheie nu este unic
DI

void creare(nod *&r, int n) void creare(nod *&r, int n)


{if (r!=NULL) {if (r!=NULL)
if (n<r->nr) creare(r->s,n); if (n<r->nr) creare(r->s,n);
RA

else if (n>r->nr) creare(r->d,n); else if (n>r->nr) creare(r->d,n);


else else r->frecv++;
cout<<"Numarul exista"<<endl; else {r = new nod;
else {r = new nod; r->nr=n;
r->nr=n; r->frecv=1;
TU

r->s=NULL; r->s=NULL;
r->d=NULL;}} r->d=NULL;}}
void main() void main()
{int n; r=NULL; {int n; r=NULL;
I

cout<<"Numar: "; cin>>n; cout<<"Numar: "; cin>>n;


ED
Informatic 317

C
while (n!=0) while (n!=0)
{creare(r,n); {creare(r,n);
cout<<"Numar: "; cin>>n;} cout<<"Numar: "; cin>>n;}

I
...} ...}

OG
Observaie. nlimea arborelui binar de cutare depinde de ordinea n care se
introduc valorile cheii.
1. Pentru fiecare dintre arborii binari de cutare desenai la tema anteri-
Tem oar, precizai n ce ordine au fost citite cheile, la crearea arborelui.

AG
2. Desenai arborii binari de cutare care se creeaz atunci cnd
introducei pentru cheie, n ordine, urmtoarele valori:
a. 3, 6, 2, 7, 8, 1, 5, 4, 0;
b. 7, 3, 1, 2, 8, 5, 4, 6, 0;

ED
c. 1, 2, 3, 4, 5, 6, 7, 8, 0.
Algoritmi pentru parcurgerea unui arbore binar de cutare
Pentru parcurgerea arborilor binari de cutare se folosesc algoritmii de parcurgere a unui

P
arbore binar.
Observaii
I
1. Prin parcurgerea arborelui cu algoritmul SRD cheile sunt afiate n ordine cresctoare.
2. Prin parcurgerea arborelui cu algoritmul DRS cheile sunt afiate n ordine descresctoare.
3. Cheia cu valoarea maxim se gsete n nodul cel mai din stnga, iar cutarea sa se
face parcurgnd arborele numai pe legtura cu succesorul stng, pornind din rdcin.

4. Cheia cu valoarea minim se gsete n nodul cel mai din dreapta, iar cutarea sa se
face parcurgnd arborele numai pe legtura cu succesorul drept, pornind din rdcin.
IC

Valoarea minim Valoarea maxim


Implementare recursiv
CT

int min(nod *r) int max(nod *r)


{if (r->s!=NULL) {if (r->d!=NULL)
return min(r->s); return max(r->d);
else return r->nr;} else return r->nr;}
DA

void main() void main()


{ ... { ...
cout<<endl<<"Minim: "<<min(r); ...} cout<<endl<<"Maxim: "<<max(r); ...}
Implementare iterativ
DI

int min(nod *r) int max(nod *r)


{while (r->s!=NULL) {while (r->d!)
r=r->s; r=r->d;
return r->nr;} return r->nr;}
RA

void main() void main()


{ ... { ...
cout<<endl<<"Minim: "<<min(r); ...} cout<<endl<<"Maxim: "<<max(r); ...}
5. Deoarece ntre nodurile arborelui binar de cutare este stabilit o relaie de ordine,
TU

cutarea unei anumite chei se face rapid prin mecanismul cutrii binare (se caut n
una din cele dou submulimi de valori subarborele stng sau subarborele drept).
Cutarea nodului se face cu ajutorul unui pointer, care pornete din nodul rdcin i
care va indica nodul curent care se analizeaz. Pointerul va avansa prin succesorul
I

stng sau succesorul drept al nodului curent, n funcie de rezultatul comparaiei dintre
ED
318 Implementarea structurilor de date

C
valoarea citit pentru cheie i valoarea cheii
din nodul curent. Avansarea continu pn
cnd se gsete un nod care conine cheia

I
cutat sau pn se ajunge la un arbore vid

OG
(cazul n care nu exist cheia cutat n
arbore) figura 80.
PAS1. Se citete cheia k care se caut.
PAS2. Se iniializeaz pointerul cu adresa rd- Fig. 80

AG
cinii.
PAS3. Ct timp nu s-a gsit cheia cutat i nu s-a ajuns la arbore vid execut:
PAS4. Dac nodul curent are cheia mai mic dect k, atunci pointerul avanseaz
la subarborele stng; altfel, pointerul avanseaz la subarborele drept.

ED
Implementare recursiv Implementare iterativ
nod *cauta(nod *r,int k) nod *cauta(nod *r,int k)
{if (r==NULL || r->nr==k) return r; {while (r!=NULL && r->nr!=k)
else if(r->nr>k) r=r->s;

P
if(r->nr>k) return cauta(r->s,k); else r=r->d;
else return cauta(r->d,k);} return r;}
void main() void main()
I
{int k; ... {int k; ...
cout<<"Cheia cautata: "; cin>>k; cout<<"Cheia cautata: "; cin>>k;
if (cauta(r,k)!=NULL) if (cauta(r,k)!=NULL)
cout<<"S-a gasit"; cout<<"S-a gasit";

else cout<<"Nu s-a gasit"; ...} else cout<<"Nu s-a gasit"; ...}
IC

Algoritmi pentru actualizarea unui arbore binar de cutare


n arborii binari de cutare se pot executa urmtoarele operaii de actualizare:
inserarea unui nod;
CT

tergerea unui nod.


n urma acestor operaii de actualizare, arborele trebuie s-i
Atenie
pstreze calitatea de arbore binar de cutare.
DA

Algoritmul pentru inserarea unui nod


Cutarea poziiei n care se insereaz nodul se face cu ajutorul unui pointer, care pornete
din nodul rdcin i care va indica nodul curent care se analizeaz. Pointerul va avansa
DI

prin succesorul stng sau succesorul drept al nodului curent, n funcie de rezultatul
comparaiei dintre valoarea citit pentru cheia care se insereaz i valoarea cheii din nodul
curent. Avansarea continu pn cnd se gsete un nod care conine o cheie egal cu
cheia care se insereaz (cazul n care nodul nu se poate insera, deoarece mai exist o
RA

cheie cu aceeai valoare n arbore) sau pn cnd, n nodul curent, succesorul pe care
avanseaz pointerul este un arbore vid. Dac s-a ajuns la arborele vid, nseamn c
valoarea cheii care se insereaz nu mai exist n arbore i cheia se adaug ca succesor
al nodului curent, drept sau stng, n funcie de valoarea cheii care se insereaz i de
TU

valoarea cheii din nodul curent. Variabila r este pointerul ctre nodul care se insereaz. n
varianta iterativ, variabila c este pointerul ctre nodul curent, iar variabila logic x se
folosete pentru a ti dac n arbore s-a gsit cheia care se insereaz (este iniializat cu
I

valoarea 1, presupunndu-se c nu mai exist cheia n arbore).


ED
Informatic 319

C
PAS1. Se citete cheia k a nodului care se insereaz.
PAS2. Se iniializeaz pointerul r cu adresa rdcinii.
PAS3. Ct timp nu s-a ajuns la arbore vid i nu s-a gsit cheia care se insereaz execut:

I
PAS4. Dac nodul curent are cheia egala cu k, atunci se afieaz mesajul Cheia

OG
exista, se atribuie lui x valoarea 0 i se trece la Pasul 6.
PAS5. Dac nodul curent are cheia mai mic dect k, atunci pointerul avansea-
z la subarborele stng; altfel, pointerul avanseaz la subarborele drept
i se revine la Pasul 3.

AG
PAS6. Dac nu s-a gsit n arbore cheia care se insereaz (x0), atunci:
PAS7. Se creeaz un nod prin alocarea unei zone de memorie.
PAS8. Se atribuie, cmpului cu informaie din nod, informaia care se insereaz.
PAS9. Se atribuie, succesorilor nodului, arborele vid.
PAS10. Dac nodul curent c are cheia mai mic dect k, atunci nodul care se in-

ED
sereaz este succesorul drept; altfel, nodul care se insereaz este
succesorul stng.
Valoarea pentru cheie este unic Valoarea pentru cheie nu este unic

P
Implementare recursiv
void inserare(nod *&r,int k) void inserare(nod *&r,int k)
{if (r!=NULL) {if (r!=NULL)
I
if (r->nr==k) if (r->nr==k)r->frecv++;
cout<<"Cheia exista"<<endl; else if (r->nr>k)
else if (r->nr>k) inserare(r->s,k);
inserare(r->s,k); else inserare(r->d,k);

else inserare(r->d,k); else {r=new nod; r->nr=k;


else {r=new nod; r->nr=k; r->s=NULL; r->d=NULL;}}
IC

r->s=NULL; r->d=NULL;}} void main()


void main() {int k; ...
{int k; ... cout<<"Cheia care se insereaza: ";
CT

cout<<"Cheia care se insereaza: "; cin>>k; inserare(r,k); ...}


cin>>k; inserare(r,k); ...}
Implementare iterativ
void inserare(nod *r,int k) void inserare(nod *r,int k)
DA

{int x=1; nod *c; {int x=1; nod *c;


while (r!=NULL && x) while (r!=NULL && x)
if (r->nr==k) if (r->nr==k)
{cout<<"Cheia exista"<<endl; {r->frecv++; x=0;}
DI

x=0;} else
else if (r->nr>k) {c=r; r=r->s;}
if (r->nr>k) {c=r; r=r->s;} else {c=r; r=r->d;}
else {c=r; r=r->d;} if (x)
RA

if (x) {r=new nod; r->nr=k;


{r=new nod; r->nr=k; r->s=NULL; r->d=NULL;
r->s=NULL; r->d=NULL; if (p->nr>k) c->s=r;
if (c->nr>k) c->s=r; else c->d=r;}}
else c->d=r;}} void main()
TU

void main() {int k; ...


{int k; ... cout<<"Cheia care se insereaza: ";
cout<<"Cheia care se insereaza: "; cin>>k; inserare(r,k); ...}
cin>>k; inserare(r,k); ...}
I
ED
320 Implementarea structurilor de date

C
Algoritmul pentru tergerea unui nod
La tergerea unui nod din arborele binar pot s apar trei cazuri:
1. Nodul care se terge nu are fii. n nodul printe, adresa lui este nlocuit cu adresa

I
OG
arborelui vid figura 81.
tergere nod terminal: k=1. tergere nod terminal: k=7.
p->s=NULL; p->d=NULL;
delete q1; delete q2;

AG
Fig. 81
2. Nodul care se terge are un fiu. n nodul printe, adresa lui este nlocuit cu adresa

ED
fiului (se stabilete o legtur ntre printele lui i fiul lui) figura 82.

Fig. 82

P
tergere nod cu fiu stng: k=5. tergere nod cu fiu drept: k=11.
p->s=p->s->s; p->d=p->d->d;
delete q1; delete q2
I
3. Nodul care se terge are doi fii. Se caut, n subarborele drept al nodului care trebuie
ters, primul nod care nu are succesor drept. Acest nod are cea mai mare cheie din
subarborele drept i, implicit, cea mai mare cheie din subarborii subordonai nodului

care se terge. Informaia util din acest nod este copiat n nodul care trebuie ters,
dup care este ters nodul gsit ca nod cu un singur fiu succesorul stng (cazul 2).
IC

Prin copierea informaiei din nodul cu cheia cea mai mare, arborele i pstreaz
proprietatea de arbore binar de cutare figura 83.
CT

tergere nod cu doi fii: k=7.


q->info=r->info;
p->s=p->s->d;
delete r;
DA

Fig. 83
DI

PAS1. Se citete cheia k a nodului care se terge.


PAS2. Se iniializeaz pointerul r cu adresa rdcinii.
PAS3. Ct timp nu s-a ters nodul i nu s-a ajuns la arborele vid execut:
PAS4. Dac nodul curent are cheia egal cu k, atunci se trece la Pasul 5, pentru
RA

a se analiza ce tip de nod este; altfel, se trece la Pasul 9.


PAS5. Dac nodul curent este nod terminal, atunci, n nodul printe, adresa lui
este nlocuit cu arborele vid, se elibereaz zona de memorie ocupat de
nodul curent i se revine la Pasul 3.
TU

PAS6. Dac nodul curent are numai succesor drept, atunci, n nodul printe,
adresa lui este nlocuit cu adresa succesorului su drept, se elibereaz
zona de memorie ocupat de nodul curent i se revine la Pasul 3.
I
ED
Informatic 321

C
PAS7. Dac nodul curent are numai succesor stng, atunci, n nodul printe,
adresa lui este nlocuit cu adresa succesorului su stng, se elibereaz
zona de memorie ocupat de nodul curent i se revine la Pasul 3.

I
PAS8. Se caut, n subarborele drept al nodului curent, primul nod care nu are

OG
succesor drept, se copiaz informaia util din acest nod n nodul curent, se
elibereaz zona de memorie ocupat de nodul gsit i se revine la Pasul 3.
PAS9. Dac nodul curent are cheia mai mic dect k, atunci se caut nodul
care trebuie ters n succesorul drept; altfel, se caut nodul care trebuie

AG
ters n succesorul stng. Se revine la Pasul 3.
PAS10. Dac s-a ajuns la arborele vid, atunci se afieaz mesajul Cheia nu exista,
Observaie. Transmiterea adresei de la nodul curent (care se terge) la printele su, se
face prin transmiterea prin referin a parametrului cu adresa nodului.

ED
void sterge nod(nod *&r, nod *&c)
/*se caut n subarborele drept al nodului curent (r) primul nod care
nu are succesor drept (c) */
{nod *p;

P
if (c->d!=NULL) sterge nod(r,c->d);
else {r->nr=c->nr; //se copiaz informaia util din nodul
//gsit n nodul curent
I
p=c->s; delete c; c=p; }}
//se terge nodul gsit ca nod care are numai succesor drept
void stergere(nod *&r,int k)
{nod *c;

if (r!=NULL)
if (r->nr==k) //dac s-a gsit nodul care trebuie ters
IC

if (r->s==NULL && r->s==NULL) //dac este nod terminal


{delete r; r=NULL;}
else
CT

if (r->s==NULL) //dac este nod care are numai succesor drept


{c=r->d; delete r; r=c;}
else if (r->d==NULL) //dac este nod care are numai succesor stng
{c=r->s; delete r; r=c;}
else sterge nod(r,r->s); //dac are ambii succesori
DA

else //dac nu s-a gsit nodul care trebuie ters


if (r->nr<k) stergere(r->d,k); //caut n succesorul drept
else stergere(r->s,k); //caut n succesorul stng
else cout<<"Cheia nu exista";}
DI

void main()
{int k; ... cout<<"Cheia care se sterge: "; cin>>k; stergere(r,k); ...}

Complexitatea algoritmilor de prelucrare a arborilor binari de cutare


RA

Cutarea unei informaii identificat printr-o cheie cu valoarea k ncepe de la nodul


rdcin i se termin, n cel mai ru caz, ntr-unul dintre nodurile terminale ale arborelui.
Gsirea nodului presupune executarea operaiei de comparare dintre cheia cu valoarea k i
TU

cheia nodului curent. Timpul mediu de execuie al algoritmului se calculeaz la fel ca la


algoritmul de cutare secvenial ntr-o structur liniar de n chei (reprezentate sub form
de vector sau list nlnuit), unde:
n1
Tmed
I

2
ED
322 Implementarea structurilor de date

C
n cazul arborelui binar de cutare, dimensiunea datelor nu este n, ci numrul de niveluri
ale arborelui de cutare (sau nlimea lui). nlimea fiind cu 1 mai mic dect numrul de
niveluri parcurse (se consider i nivelul rdcinii), n cazul arborelui binar de cutare:

I
h2

OG
Tmed
2
Ordinul de complexitate al algoritmului este O(h). Rezult c timpul consumat pentru operaii-
le de prelucrare a arborilor binari de cutare este direct proporional cu nlimea arborelui h.
Propoziia 20

AG
nlimea unui arbore binar cu n noduri poate lua valori ntre log2(n)-1 i n-1.
Demonstraie. Notm cu h nlimea arborelui binar cu n noduri. Arborele binar are cea mai mare
nlime (h_max) atunci cnd este degenerat (nodurile sunt distribuite cte unul pe fiecare nivel
cu excepia nodului terminal, ordinul fiecrui nod este 1). Rezult c h_max=n-1 i hn-1 Arborele

ED
binar are cea mai mic nlime (h_min) atunci cnd este complet (toate nodurile terminale se
gsesc pe acelai nivel i ordinul fiecrui nod, cu excepia nodurilor terminale, este 2). n acest caz,
i h_min+1
pe fiecare nivel i vor fi 2 noduri, iar numrul n de noduri va fi egal cu 2 1. Rezult c n+1 =
h_min+1
2 i h_min+1= log2(n+1). Din ultima egalitate rezult c h log2(n)-1.

P
Eficiena algoritmului de prelucrare a arborilor binari depinde de modul n care a fost
creat arborele. Dac el are nlimea maxim (arborele binar degenerat, n care fiecare nod nu
I
are dect un succesor), ordinul de complexitate al algoritmului va fi O(n) i este egal cu cel al
algoritmului de cutare secvenial ntr-o structur de date liniar. Dac el are nlimea minim
(arborele complet sau aproape complet), ordinul de complexitate al algoritmului va fi O(log2n).

1. Comparai, din punct de vedere al eficienei, algoritmii recursivi i


Tem iterativi pentru determinarea minimului, respectiv a maximului, ntr-un
IC

arbore binar de cutare. Care dintre variante este mai eficient?


2. Pentru arborele binar A14 din figura 79, cte operaii de deplasare n structura de date
se execut pentru a determina minimul? Dac valorile din arbore ar fi fost memorate
CT

ntr-o structur liniar, cte operaii de deplasare s-ar fi executat pentru a determina
minimul? Care dintre structurile de date este mai eficient?
3. Scriei o funcie care s creeze un arbore binar de cutare perfect echilibrat.
4. Scriei o funcie care s verifice dac un arbore binar este un arbore binar de cutare.
DA

5. n nodurile unui arbore binar sunt memorate numrtorul i numitorul unor fracii
distincte. S se simplifice fraciile din arbore, iar dac n urma simplificrii rezult un
numr ntreg, s se elimine din arbore.
6. n nodurile unui arbore binar sunt memorate numere ntregi. Se citete de la tastatur un
DI

numr ntreg x. S se caute n arbore nodul cheia x i dac se gsete, s se afieze


fratele su precizndu-se dac este fratele stng sau fratele drept. S se afieze un
mesaj de informare dac nu se gsete cheia x n arbore sau dac nodul nu are frate.
RA

2.8.5.3. Aplicaii practice


1. Un text conine cuvinte care se pot repeta. Textul este memorat ntr-un fiier text. Scriei
un program care s citeasc textul din fiier i care s afieze cuvintele din text,
ordonate alfabetic, i frecvena lor de apariie n text.
TU

2. Realizai o agend de telefon cu ajutorul unui arbore binar de cutare. n fiecare nod se
vor pstra urmtoarele informaii: numele i prenumele persoanei, numrul (numerele
de telefon) i adresa de e-mail. Scriei un program care s permit adugarea de noi
persoane n agend, eliminarea unor persoane i cutarea unei persoane pentru a afla
I
ED

numrul de telefon i adresa de e-mail.


Informatic 323

C
2.8.6. Ansamblul Heap
2.8.6.1. Definiia ansamblului Heap

I
OG
Se numete ansamblu Heap un arbore binar care ndeplinete urmtoarele condiii:
(1) este un arbore aproape complet;
(2) n orice pereche de noduri tat-fiu cheile sunt ntr-o relaie de ordine prestabilit.
Exemplu. n figura 84 este prezentat ansamblul Heap A15 n A
A
A111555

AG
nodurile cruia sunt memorate numere naturale, relaia de
ordine fiind: dac n nodul tat este un numr impar, n
nodul fiu nu poate fi dect tot un numr impar. Numerele
scrise n exteriorul nodurilor, reprezint indici pentru nume-
rotarea nodurilor.

ED
Fig. 84
Terminologie:
Ansamblul Heap se mai numete i arbore de selecie sau arbore parial ordonat.
Un ansamblu Heap maxim este un ansamblu Heap n care

P
cheia printelui este mai mare sau egal cu cheia fiului
(arborele binar A16 din figura 85). A
A
A111666
Un ansamblu Heap minim este un ansamblu Heap n care
I
cheia printelui este mai mic sau egal cu cheia fiului
(arborele binar A17 din figura 86). A
A
A111777
Fig. 85
Caracteristici:

ntr-un ansamblu Heap cu n noduri, nlimea arborelui h este egal cu [log2n]-1.


IC

ntr-un ansamblu Heap (de exemplu, ntr-un ansamblu


Heap minim sau Heap maxim) pot exista chei cu
aceeai valoare.
CT

ntr-un ansamblu Heap minim cheia din orice nod este


mai mic sau egal cu cheile tuturor nodurilor din cei doi
subarbori ai si, iar n nodul rdcin se gsete cheia
Fig. 86
cea mai mic din arbore.
DA

ntr-un ansamblu Heap maxim cheia din orice nod este mai mare sau egal cu cheile
tuturor nodurilor din cei doi subarbori ai si, iar n nodul rdcin se gsete cheia cea
mai mare din arbore.
Un ansamblu Heap poate fi folosit pentru a implementa o coad de prioriti (de aici i
DI

vine i denumirea de arbore de selecie), deoarece prin extragerea cheilor prin nodul
rdcin se extrag datele n conformitate cu relaia de ordine prestabilit. Pentru
ansamblul Heap A15 din figura 85, ordinea de extragere a datelor este: mai nti
RA

numerele pare i apoi numerele impare. n ansamblul Heap A16 din figura 86 extragerea
nodurilor se face n ordinea descresctoare a etichetelor, iar n ansamblul Heap A17 din
figura 86 extragerea nodurilor se face n ordinea cresctoare a etichetelor.
Proprietate: Ansamblul Heap are o proprietate foarte important (pe care o motenete de
TU

la arborii binari complei): dac nodurile arborelui se numeroteaz cu indici, n ordinea


parcurgerii n lime (ca n figura 84), ntre indicii printelui, al subarborelui stng i al
subarborelui drept exist urmtoarele relaii:
Printele nodului cu indicele i are indicele i .
I
ED

2
324 Implementarea structurilor de date

C
Fiul stng al printelui cu indicele i are indicele 2i.
Fiul drept al printelui cu indicele i are indicele 2i+1.
Aceast proprietate a arborilor complei i aproape complei ne permite s implementm

I
static ansamblul Heap, cu ajutorul unui vector v.

OG
Rdcina arborelui are eticheta v[1].
Fiul stng al nodului cu eticheta v[i] este nodul cu eticheta v[2*i].
Fiul drept al nodului cu eticheta v[i] este nodul cu eticheta v[2*i+1].
Indice 1 2 3 4 5 6 7 8 9 10

AG
vectorul A16 2 10 18 20 3 5 9 11 15 25
v A17 2 3 5 10 9 15 11 18 20 25
pentru A18 25 20 18 11 15 9 10 5 3 2
Observaii:

ED
1. ntr-un vector care implementeaz un ansamblu Heap Maxim: v[i]v[2i] i v[i]v[2i+1]
pentru i{1, 2, 3, , [n/2]} i dac 2in, respectiv 2i+1n.
2. ntr-un vector care implementeaz un ansamblu Heap Minim: v[i]v[2i] i v[i] v[2i+1]

P
pentru i{1, 2, 3, , [n/2]} i dac 2in, respectiv 2i+1n.
Invers, un vector v poate fi reprezentat ca un arbore binar aproape
complet. Pentru un indice i{1, 2, 3, , [n/2]}:
I
Fig. 87
dac 2in, se poate construi un subansamblu Heap care este format numai
din nodul printe v[i] (figura 87);
dac 2i=n, se poate construi un subansamblu Heap care este format din

nodul printe v[i] i fiul stng v[2i] (figura 88);


dac 2i<n i 2i+1n, se poate construi un subansamblu Heap care este
IC

Fig. 88
format din nodul printe v[i], fiul stng v[2i] i fiul drept v[2i+1] (figura 89).
Pentru mulimea de chei {2, 5, 7, 10, 12, 15, 23, 25, 28}
CT

Tem scriei vectorul corespunztor ansamblului Heap maxim i


vectorul corespunztor ansamblului Heap minim. Dese-
nai ansamblurile Heap pornind de la vectori. Fig. 89
DA

2.8.6.2. Algoritmi pentru prelucrarea unui ansamblu Heap


Pentru prelucrarea unui ansamblu Heap se pot folosi urmtorii algoritmi:
Algoritmul pentru crearea ansamblului Heap,
Algoritmul pentru inserarea unui nod,
DI

Algoritmul pentru extragerea unui nod.

Atenie n urma acestor operaii de prelucrare, arborele trebuie s-i


pstreze calitatea de ansamblu Heap.
RA

n algoritmii pentru prelucrarea unui ansamblu Heap se va folosi implementarea static a


ansamblului cu ajutorul vectorului. Dac lungimea fizic a vectorului este NMAX, numrul
de noduri n ale ansamblului Heap nu trebuie s fie mai mare dect NMAX-1. Deoarece
TU

vectorul Heap se construiete pe baza mecanismului de legtur printe-fii ntre indici,


etichetele ansamblului Heap se vor memora n vector ncepnd cu indicele 1.
I
ED
Informatic 325

C
Algoritmul pentru crearea unui ansamblu Heap
Crearea unui ansamblu Heap presupune adugarea elementelor n vector, pornind de la pri-
mul element, astfel nct aceast reprezentare s respecte proprietile unui ansamblu Heap:

I
(1) S fie un arbore aproape complet. Deoarece n arbore nodul trebuie adugat pe

OG
ultimul nivel, imediat la dreapta nodului existent, nseamn c n vector se va
aduga noua cheie imediat dup ultimul element.
(2) n orice pereche de noduri tat-fiu, cheile trebuie s fie n relaia de ordine presta-
bilit. Dac n arbore se adaug un nod n poziia precizat, este posibil ca el s

AG
nu fie cu printele su n relaia de ordine prestabiit. Soluia este de a propaga
informaia din acest nod ctre rdcin, pn cnd este ndeplinit relaia de
ordine ntre nodul n care a ajuns informaia i printele su.
n algoritmul pentru crearea ansamblului Heap se folosete variabila j pentru lungimea

ED
logic a vectorului (reprezint numrul de elemente care au fost adugate n vector) i
variabila i pentru indicele nodului curent. Algoritmul urmtor se poate folosi pentru crearea
unui Heap Maxim:
PAS1. Se citete prima cheie i se memoreaz n rdcina arborelui (elementul v[1]).

P
PAS2. Pentru nodul j de la al doilea nod, pn la ultimul nod din arbore, execut:
PAS3. Se scrie cheia n elementul cu indicele j.
I
PAS4. Se iniializeaz indicele elementului curent i cu lungimea logic a vectorului j.
PAS5. Ct timp nodul curent este diferit de nodul rdcin execut:
PAS6. Dac cheia memorat n nodul curent (elementul cu indicele i) este
mai mare dect cheia memorat n nodul printe al nodului curent

(elementul cu indicele i/2), atunci se interschimb cheia din nodul


curent cu cheia din nodul printe, iar nodul printe devine nod curent;
IC

altfel, rdcina devine nod curent.


fstream f("heap.txt",ios::in); //cheile se citesc din fiier
int const NMAX=100;
CT

int v[NMAX],n;
void creare heap()
{int i,j,aux; f>>n;
if (n<=NMAX-1)
DA

{f>>v[1];
for (j=2;j<=n;j++)
{f>>v[j]; i=j;
while (i>1)
DI

if (v[i]>=v[i/2]) {aux=v[i],v[i]=v[i/2]; v[i/2]=aux; i=i/2;}


else i=1;}}
else cout<<"Nu se poate crea - arborele are mai multe noduri
decat lungimea fizica a vectorului"<<endl;}
RA

void afisare() {for (int i=1;i<=n;i++) cout<<v[i]<<" ";}


void main() {creare heap()(); afisare();}
Algoritmul pentru inserarea unui nod n ansamblul Heap
TU

Prin adugarea unui nou nod, lungimea logic a vectorului crete cu 1 i trebuie s se
verifice s nu depeasc lungimea fizic a vectorului. Prin inserarea unui nod, arborele
trebuie s-i pstreze calitatea de ansamblu Heap, adic s aib proprietile:
(1) S fie un arbore aproape complet. n arbore, nodul se va aduga pe ultimul nivel,
I

imediat la dreapta nodului existent. Dac ultimul nivel este complet, nodul se va aduga
ED
326 Implementarea structurilor de date

C
pe urmtorul nivel, ca succesor stng al nodului din extremitatea stng de pe nivelul
anterior. nseamn c n vector se va aduga noua cheie imediat dup ultimul element.
(2) n orice pereche de noduri tat-fiu cheile trebuie s fie n relaia de ordine presta-

I
bilit. Dac n arbore se adaug un nod n poziia precizat, este posibil ca el s nu fie

OG
cu printele su n relaia de ordine prestabilit i informaia trebuie s se propage
din acest nod ctre rdcin, la fel ca la algoritmul de creare. nseamn c, n vector,
ultimul element va fi considerat element curent i cheia memorat n ele se va
compara cu cheia memorat n printe. Dac nu respect relaia de ordine, se in-

AG
terschimb cheia nodului curent cu cheia printelui, iar printele devine nod curent.
Propagarea cheii continu pn cnd ntre elementul curent i printele su este
respectat relaia de ordine, sau pn cnd rdcina ajunge s fie element curent.
...

ED
void adauga() //pentru ansamblul Heap Maxim
{int x,i;
if (n==NMAX-1) cout<<"Nu se mai poate adauga nodul"<<endl;
else
{cout<<"cheia= "; cin>>x; n++; v[n]=x; i=n;

P
while (i>1)
if (v[i]>=v[i/2]) {x=v[i]; v[i]=v[i/2]; v[i/2]=x; i=i/2;}
else i=1;}}
I
void main() {creare(); ... adauga(); ... }
Algoritmul pentru extragerea unui nod din ansamblul Heap
Ansamblul Heap, fiind o coad de prioriti, prima informaie care se prelucreaz este cea

din nodul rdcin. Extragerea unui nod din ansamblul Heap nseamn de fapt prelucrarea
informaiei din nodul rdcin i eliminarea acestui nod din arbore. Pentru ca arborele s-i
IC

pstreze calitatea de ansamblu Heap, dup eliminarea nodului rdcin trebuie s aib
proprietile:
CT

(1) S fie un arbore aproape complet. nseamn c trebuie s dispar din arbore
nodul cel mai din dreapta de pe ultimul nivel. Dac din arbore dispare nodul din
dreapta de pe ultimul nivel, nu trebuie s dispar din arbore i informaia din acest
nod din arbore trebuie s dispar informaia din nodul rdcin. De aceea, n
DA

nodul rdcin este adus informaia din ultimul nod. n vector, cheia din ultimul
element va fi salvat n primul element, dup care, este eliminat ultimul element
prin decrementarea lungimii logice a vectorului.
(2) n orice pereche de noduri tat-fiu cheile trebuie s fie n relaia de ordine presta-
DI

bilit. Dac n nodul rdcin este adus informaia din ultimul nod, este foarte pro-
babil s nu mai fie respectat relaia de ordine ntre nodul rdcin i fiii si. Soluia
este de a propaga informaia adus n rdcin, ctre nivelurile inferioare, pn
cnd este ndeplinit relaia de ordine ntre nodul n care a ajuns informaia i fiii si.
RA

n algoritmul pentru eliminarea nodului din ansamblul Heap se folosete variabila i pentru
indicele nodului curent, iar variabila j pentru indicele nodului fiu al nodului curent.
PAS1. Se prelucreaz cheia din rdcin (elementul v[1]).
TU

PAS2. Se copiaz n rdcin cheia din ultimul nod (elementul v[n]) i se micoreaz cu
1 lungimea logic a vectorului.
PAS3. Se iniializeaz nodul curent cu nodul rdcin (indicele i are valoarea 1).
PAS4. Ct timp nodul curent face parte din arbore (elementul cu indicele i face parte din
I

vector) execut:
ED
Informatic 327

C
PAS5. Dac nodul curent are succesor stng, atunci fiul su va fi succesorul stng
(indicele j este egal cu 2*i); altfel, nodul curent este scos n afara arborelui,
atribuind indicelui i o valoare mai mare dect lungimea logic a vectorului

I
i se revine la Pasul 4.

OG
PAS6. Dac nodul curent are i succesor drept, i cheia din succesorul stng este
mai mic dect cheia din succesorul drept, atunci fiul nodului curent va fi
succesorul drept (indicele j este egal cu 2*i+1).
PAS7. Dac cheia memorat n nodul curent (elementul cu indicele i) este mai mic

AG
dect cheia memorat n nodul fiu al nodului curent (elementul cu indicele j),
atunci se interschimb cheia din nodul curent cu cheia din nodul fiu, iar
nodul fiu devine nod curent; altfel, nodul curent este scos n afara arborelui.
Se revine la Pasul 4.

ED
...
int elimina() //pentru ansamblul Heap Maxim
{int i,j,x=v[1],aux; v[1]=v[n]; n--; i=1;
while (i<=n)
{if (2*i<=n)

P
{j=2*i;
if (j+1<=n && v[j+1]>=v[j]) j++;
if (v[i]<=v[j]){aux=v[i]; v[i]=v[j]; v[j]=aux; i=j;}
I
else i=n+1;}
else i=n+1;}
return x;}

void main()
{creare();...cout<<"Cheia cea mai mare este "<<elimina()<<endl;...}
IC

Observaie. Dac se extrag din arbore toate nodurile i se afieaz cheile nodurilor
extrase, cheile vor fi afiate n relaia de ordine prestabilit pentru ansamblul Heap.
Complexitatea algoritmilor de prelucrare a ansamblurilor Heap
CT

n algoritmul de creare a unui ansamblu Heap, se parcurge secvenial vectorul pentru adu-
garea celor n elemente. Complexitatea parcurgerii secveniale este O(n). Pentru fiecare ele-
ment adugat la vector, cheia nodului trebuie adus n poziia corespunztoare din ansamblul
DA

Heap. Cazul cel mai defavorabil este atunci cnd cheia se propag de pe nivelul pe care a
fost adugat, pn la nivelul rdcinii, numrul de comparaii executate fiind egal cu
nlimea h a arborelui la acel moment (care ia valori de la 0 pn la lg2n), iar complexitatea
algoritmului de propagare a unui nod de pe nivelul cu nlimea h pn n rdcin va fi
DI

O(lg2n). Rezult c, n algoritmul de creare, complexitatea este O(n) O(lg2n) = O(nlg2n).


Algoritmul de inserare a unui nod are complexitatea O(lg2n) cazul cel mai defavorabil
fiind atunci cnd cheia se propag de pe ultimul nivel pn n rdcin. Algoritmul de
adugare a unui nod are complexitatea O(lg2n) cazul cel mai defavorabil fiind atunci cnd
RA

cheia se propag din rdcin pn la ultimul nivel.

2.8.6.3. Algoritmul HeapSort


Dac un vector este organizat ca ansamblu Heap, nodurile vor fi extrase n ordinea preci-
TU

zat prin relaia de ordine asociat arborelui. Aceast caracteristic a ansamblurilor Heap,
st la baza algoritmului de sortare HeapSort. Dac fiecare element eliminat este adus dup
ultimul element din vectorul rmas dup extragerea lui, n vectorul obinut, cheile vor fi
I

ordonate invers dect prin relaia de ordine prestabilit n ansamblul Heap. Astfel:
ED
328 Implementarea structurilor de date

C
Dac vectorul era organizat ca un ansamblu Heap Maxim, va fi ordonat descresctor.
Dac vectorul era organizat ca un ansamblu Heap Minim, va fi ordonat cresctor.
1 2 3 4 5 n-1 n

I
OG
Cheia maxim din n noduri
1 2 3 4 n-2 n-1 n

AG
Cheia maxim din n-1 noduri
.
1 2 3 4 n-2 n-1 n

ED
Cheia maxim din 2 noduri

P
Algoritmul este:
PAS1. Se creeaz vectorul care urmeaz s fie sortat ca un vector care implementeaz
un ansamblu Heap.
I
PAS2. Se salveaz lungimea logic a vectorului.
PAS3. Se iniializeaz nodul curent cu ultimul nod (indicele i are valoarea n).
PAS4. Ct timp mai exist noduri de extras din ansamblul Heap execut
PAS5. Se elimin nodul din arbore i se salveaz n nodul curent.

PAS6. Nodul curent devine ultimul nod din ansamblul rmas dup eliminare (se
decrementeaz cu 1 indicele nodului curent) i se revine la Pasul 4.
IC

...//datele i structurile de date declarate global


void creare heap() {...}
CT

void afisare(){...}
int elimina() {...}
void HeapSort()
{int i,j=n;
for (i=n;i>1;i--) v[i]=elimina();
DA

n=j;}
void main() {creare heap(); HeapSort(); afisare(); cout<<endl;}
Complexitatea algoritmului de sortare
DI

n algoritmul de sortare a unui ansamblu Heap se parcurge secvenial vectorul pentru a elimi-
na cele n elemente. Complexitatea parcurgerii secveniale este O(n). Pentru fiecare nod se exe-
cut algoritmul de eliminare care are complexitatea O(lg2n). Rezult c, n algoritmul de sor-
tare a unui vector organizat ca ansamblu Heap, complexitatea este O(n)O(lg2n) = O(nlg2n).
RA

Algoritmul de sortare a unui vector folosind metoda HeapSort presupune organizarea vecto-
rului ca un ansamblu Heap complexitatea O(nlg2n), urmat de sortarea ansamblului Heap
complexitatea O(nlg2n). Rezult c n algoritmul de sortare prin metoda HeapSort, com-
plexitatea este O(nlg2n)+O(nlg2n) = O(nlg2n+nlg2n) = O(2nlg2n)= O(nlg2n).
TU

Se citesc din fiierul BAC.TXT mai multe iruri de numere naturale nenule,
Tem sfritul fiecrui ir fiind marcat de o valoare 0 (care nu se consider c
face parte din vreun ir). tiind c fiecare dintre iruri este un ir strict
I
ED
Informatic 329

C
cresctor i c n total sunt cel mult 5000 de numere, scriei un program care s realizeze
afiarea tuturor numerelor nenule distincte din fiier, n odinea cresctoare a valorilor lor.
a. Descriei dou metode de rezolvare, una dintre metode fiind eficient ca timp de

I
executare.

OG
b. Scriei un program corespunztor metodei eficiente descrise.
(Bacalaureat Simulare 2004)

2.8.6.4. Aplicaii practice

AG
1. Mai multe vehicule parcurg acelai traseu. Fiecare vehicul este caracterizat de un
identificator, timpul de pornire, timpul de sosire i timpul de parcurgere a traseului (care
se calculeaz din diferena celor doi timpi). Scriei un program care s memoreze aceste
informaii ntr-un ansamblu heap i care s asigure urmtoarele funcii: adugarea unui

ED
nod (un vehicul care a sosit) i afiarea informaiilor despre vehicule, n ordinea
cresctoare a timpului de parcurs.
2. Produsul realizat de o secie a unei fabrici este cerut de mai muli clieni. Fiecare client
este caracterizat de nume, numr de telefon, data la care trebuie livrat produsul i

P
cantitatea comandat. Cererile sunt onorate n ordinea calendaristic a datelor de livrare
i n funcie de cantitatea disponibil n stoc. Scriei un program care s permit ntre-
inerea zilnic a acestei structuri de date, prin urmtoarele operaii:
I
a. adugarea de noi comenzi;
b. afiarea listei de comenzi care trebuie onorate n ziua respectiv i salvarea ei ntr-un
fiier text (data calendaristic i stocul de produse la nceputul zilei se citesc de la

tastatur);
c. stocul la sfritul zilei, dup ce au fost onorate comenzile.
IC
CT

Adevrat sau Fals:


1. Arborele este un graf fr cicluri, minimal cu aceast proprietate.
2. Arborele parial de cost minim determin drumurile de lungime minim dintre oricare
dou noduri dintr-un graf conex.
DA

3. n algoritmul lui Kruskal pentru construirea APM, se pornete de la un arbore parial


care conine nodul rdcin.
4. ntr-un arbore cu rdcin, implementarea cu referine ascendente folosete doi
vectori: unul pentru a memora nodurile terminale i altul pentru a memora prinii
DI

nodurilor terminale.
5. Algoritmul de parcurgere n lime a unui arbore cu rdcin prelucreaz informaia
n funcie de relaiile de subordonare dintre noduri.
RA

6. Arborele binar este un arbore cu rdcin, n care fiecare nod are cel mult doi
succesori.
7. Un arbore binar strict este un arbore echilibrat.
8. Un arbore vid este un arbore n care nodul rdcin nu are succesori.
TU

9. ntr-un arbore binar de cutare, cheia oricrui nod este mai mare dect cheile
succesorilor lui.
10. Pentru a sorta cresctor un vector cu algoritmul HeapSort, vectorul trebuie s imple-
menteze un arbore binar n care, pentru fiecare nod, cheia din succesorul stng este
I
ED
330 Implementarea structurilor de date

C
mai mic dect cheia din nod, iar cheia din succesorul drept este mai mare dect cheia
din nod.
11. ntr-un ansamblu Heap, cheile nodurilor trebuie s fie distincte.

I
Alegei:

OG
1. Orice graf neorientat cu n noduri i n-1 muchii:
a. este aciclic i neconex b. este conex dac i numai dac este aciclic
c. este un arbore d. este conex i conine un ciclu
(Bacalaureat Simulare 2003)

AG
2. Numrul de muchii ale unui arbore cu 9 noduri este:
a. 9 b. 7 c. 8 d. 10
3. Numrul maxim de noduri terminale ale unui arbore liber cu 15 noduri este:
a. 15 b. 14 c. 12 d. 10

ED
4. Numrul maxim de noduri terminale ale unui arbore cu rdcin cu 15 noduri este:
a. 15 b. 14 c. 12 d. 10
5. Numrul maxim de noduri terminale ale unui arbore binar cu 15 noduri este:

P
a. 6 b. 7 c. 5 d. 4
6. Se consider un arbore cu urmtoarele proprieti: rdcina este nodul 1 (considerat
de nivel 1) i fiecare nod i (cu 1i3) aflat pe nivelul j are ca descendeni nodurile i+j
I
i i+2*j. Nodurile i (cu i3) sunt noduri terminale (frunze). Stabilii care dintre vectorii
urmtori este vectorul de tai (sau de predecesori) corespunztor arborelui:
a. 0 1 2 2 1 3 3 b. 0 -1 1 -1 -1 1 1

c. 0 1 1 2 3 2 3 d. 0 1 1 2 2 3 3
(Bacalaureat Simulare 2003)
IC

7. Se consider arborele din figura alturat. Care dintre noduri


trebuie ales ca rdcin astfel nct nlimea arborelui s fie
minim.
CT

a. 7 b. 3 c. 5 d. 6
(Bacalaureat Sesiunea special 2003)
8. Un arbore are 14 noduri. Att rdcina, ct i fiecare dintre nodurile neterminale au
cel mult 3 descendeni direci. nlimea maxim a arborelui (numrul maxim de
DA

muchii ce leag rdcina de o frunz) este:


a. 4 b. 13 c. 5 d. 3
(Bacalaureat Sesiunea special 2003)
DI

9. Memorarea unui arbore cu ajutorul matricei de adiacen a grafului este o metod:


a. eficient b. neeficient c. incorect d. recomandabil
(Bacalaureat Sesiunea special 2003)
10.Se consider arborele din figura A28. Definim nlimea arborelui ca fiind numrul
RA

maxim de muchii care formeaz un lan care unete rdcina de


un nod terminal. Care este nlimea maxim a arborelui cu
rdcin ce se poate obine alegnd ca rdcin unul dintre
noduri?
TU

a. 5 b. 3 c. 6 d. 7
(Bacalaureat Sesiunea iunie-iulie 2003)
11.Se consider un arbore cu rdcin n care orice nod care nu este terminal are exact
I

3 descendeni direci. Atunci, numrul de noduri terminale (frunze) poate fi:


ED
Informatic 331

C
a. 15 b. 24 c. 2 d. 14
(Bacalaureat Sesiunea iunie-iulie 2003)
12.Se consider un arbore n care rdcina este considerat de nivelul 1 i orice nod de

I
pe nivelul i are exact i+1 descendeni direci, cu excepia nodurilor de pe nivelul 4

OG
care sunt noduri terminale. Numrul de noduri terminale (frunze) sunt:
a. 24 b. 120 c. 6 d. 30
(Bacalaureat Sesiunea august 2003)
13.Se consider un arbore. Despre un lan care unete dou noduri distincte n1 i n2 se

AG
poate afirma:
a. este unic oricare ar fi n1 i n2 b. este unic dac i numai dac n1 sau n2 este terminal
c. nu este unic oricare ar fi n1 i n2 d. este unic dac i numai dac n1 sau n2 este rdcin
(Bacalaureat Sesiunea august 2003)

ED
14.Stabilii care dintre grafurile alturate
este arbore: a. b. c. d.
(Bacalaureat Simulare 2004)
Urmtorii 4 itemi se refer la arborele cu

P
rdcin cu 8 noduri, cu muchiile [1,7],
[1,8], [3,1], [3,4], [3,5], [4,2], [4,6] i cu rdcina n nodul cu eticheta 3.
I
15.Vectorul tat al arborelui este:
a. 3 4 0 3 3 4 1 2 b. 3 3 0 4 3 4 1 1 c. 3 4 0 3 3 4 1 1 d. 3 4 3 3 4 1 1 0
16.Numrul de noduri terminale ale arborelui este:

a. 6 b. 4 c. 5 d. 3
17.nlimea maxim pe care o poate avea, schimbndu-se nodul, rdcin este:
IC

a. 6 b. 5 c. 4 d. 3
18.Dac se ia ca rdcin nodul cu eticheta 2, nlimea arborelui este:
a. 5 b. 2 c. 4 d. 3
CT

19.Numrul de componente conexe care se obin dac se elimin muchiile care au o


extremitate n nodul cu eticheta 3 este:
a. 3 b. 4 c. 2 d. 1
DA

Urmtorii 5 itemi se refer la arborele cu rdcin cu 8 noduri care are vectorul tat: 2 0 2
1 1 1 3 3.
20. Numrul de noduri terminale ale arborelui este:
a. 3 b. 4 c. 5 d. 2
DI

21.Numrul de lanuri de lungime 3 este:


a. 3 b. 4 c. 5 d. 6
22.Numrul de lanuri de lungime 2 care pornesc din rdcin este:
RA

a. 2 b. 4 c. 3 d. 5
23.Numrul de nivele ale arborelui este:
a. 2 b. 3 c. 4 d. 5
TU

24.Fiii nodului 3 sunt:


a. 4, 5, 6 b. 1, 2 c. 7, 8 d. 2, 7, 8
25.Un arbore binar strict cu 4 noduri terminale are n total
a. 5 noduri b. 7 noduri c. 9 noduri d. 10 noduri
I
ED

26.Un arbore binar strict are:


332 Implementarea structurilor de date

C
a. un numr par de noduri b. un numr impar de noduri
c. un numr par de muchii d. un numr impar de muchii
27.Se consider arborele din figura alturat. Stabilii ce fel de

I
arbore nu este:

OG
a. arbore binar b. arbore de cutare
c. ansamblu Heap d. arbore strict
28.Se consider arborele din figura de la problma anterioar.
Stabilii ce fel de arbore nu este:

AG
a. arbore echilibrat b. arbore complet
c. arbore aproape complet d. arbore strict
29.Un arbore binar strict cu 4 noduri terminale are n total:
a. 4 muchii b. muchii c. 8 muchii d. 9 muchii

ED
Urmtorii 5 itemi se refer la arborele binar din figura alturat; r
este un pointer ctre rdcin, iar p i q, doi pointeri ctre un
nod oarecare:

P
30. Alegei varianta corect pentru a afia cheia 15:
a. cout<<r->d->d>->info; b. cout<<r->s->s>->info;
c. p=r->s->d;cout<<p->d->info; d. p=r->s->d;cout<<p->info;
I
31.Dac se execut instruciunea: p=r->s->d->d; pointerul p va indica cheia:
a. 21 b. 20 c. 18 d. 25
32.Urmtoarea secven de instruciuni:

p=r->d->d; p=p->s; q=new nod; q->info=5; q->s=NULL; q->s=NULL; p->s=q;


realizeaz:
IC

a. adaug nodul cu cheia 5 ca succesor stng al nodului cu cheia 30;


b. adaug nodul cu cheia 5 ca succesor drept al nodului cu cheia 30;
c. adaug nodul cu cheia 5 ca succesor stng al nodului cu cheia 19;
CT

d. adaug nodul cu cheia 5 ca succesor drept al nodului cu cheia 19;


33.Urmtoarea secven de instruciuni:
for (p=r;p->s!=NULL;p=p->s); q=new nod;
DA

q->info=20; q->s=NULL; q->s=NULL; p->s=q;


realizeaz:
a. adaug nodul cu cheia 20 ca succesor stng al nodului cu cheia 25;
b. adaug nodul cu cheia 20 ca succesor drept al nodului cu cheia 25;
DI

c. adaug nodul cu cheia 20 ca succesor stng al nodului cu cheia 21;


d. adaug nodul cu cheia 20 ca succesor drept al nodului cu cheia 21;
34.Urmtoarea secven de instruciuni:
for (p=r;p->d->d!=NULL;p=p->d); q=p->d; p->d=NULL; dispose q;
RA

realizeaz:
a. elimin nodul cu cheia 21; b. elimin nodul cu cheia 18;
c. elimin nodul cu cheia 25; d. elimin nodul cu cheia 30;
TU

Miniproiecte:
1. Pentru evidena elevilor din clas, se pstreaz urmtoarele informaii: numrul de ordine
din catalog, numele i prenumele, mediile semestriale i media anual la disciplina infor-
matic. Realizai o aplicaie care s asigure urmtoarele funcii:
I
ED

a. adugarea unui nou elev;


Informatic 333

C
b. eliminarea unui elev;
c. modificarea mediei unui elev;
d. afiarea elevilor cu mediile (semestriale, respectiv anuale), n ordinea descresctoare a

I
mediilor;

OG
e. afiarea elevilor cu mediile (semestriale, respectiv anuale) cuprinse ntre dou valori care
se citesc de la tastatur.
2. ntr-o bibliotec, pentru fiecare carte se pstreaz urmtoarele informaii: codul crii, titlul,
autorul, numrul total de exemplare i numrul de exemplare disponibile la un moment dat.

AG
Realizai o aplicaie care s asigure urmtoarele funcii;
a. regsirea unei cri, dup autor, pentru a afia numrul de exemplare disponibile;
b. adugarea unui nou titlu;
c. adugarea de noi exemplare, pentru titlurile existente;

ED
d. modificarea numrului total de exemplare (n cazul distrugerii unora dintre ele);
e. modificarea numrului de exemplare disponibile, n cazul n care o carte este
mprumutat sau napoiat:
f. afiarea crilor pentru care nu mai exist exemplare disponibile;

P
g. afiarea n ordine alfabetic a autorilor.
3. Pentru fiecare articol dintr-o magazie, se pstreaz urmtoarele informaii: codul articolului
I
(este unic pentru fiecare articol), denumirea articolului, unitatea de msur i cantitatea din
stoc. Realizai o aplicaie pentru gestionarea magaziei care s asigure urmtoarele funcii;
a. adugarea unui nou articol;
b. tergerea unui articol;

c. introducerea de la tastatur a cantitii intrate, dintr-un articol precizat prin cod, i


actualizarea stocului;
IC

d. introducerea de la tastur a cantitii ieite, dintr-un articol precizat prin cod, i cu


actualizarea stocului;
e. afiarea articolelor care au stocul pe 0;
CT

f. afiarea stocului unui articol al crui cod se introduce de la tastatur;


g. afiarea, n ordinea codurilor, a stocurilor din fiecare articol.
DA
DI
RA
TUI
ED
Cuprins

C
1. Tehnici de programare........................................................................................ 3
1.1. Analiza algoritmilor.............................................................................................3
1.2. Metode de construire a algoritmilor..................................................................5
1.3. Metoda backtracking ..........................................................................................6

I
1.3.1. Descrierea metodei backtracking .................................................................6

OG
1.3.2. Implementarea metodei backtracking.........................................................10
1.3.3. Probleme rezolvabile prin metoda backtracking.........................................14
1.3.3.1. Generarea permutrilor....................................................................15
1.3.3.2. Generarea produsului cartezian.......................................................17
1.3.3.3. Generarea aranjamentelor ...............................................................20

AG
1.3.3.4. Generarea combinrilor ...................................................................22
1.3.3.5. Generarea tuturor partiiilor unui numr natural...............................24
1.3.3.6. Generarea tuturor partiiilor unei mulimi..........................................27
1.3.3.7. Generarea tuturor funciilor surjective..............................................28

ED
1.3.3.8. Problema celor n dame ....................................................................30
1.3.3.9. Parcurgerea tablei de ah cu un cal ................................................31
1.3.3.10. Generarea tuturor posibilitior de ieire din labirint ......................34
1.4. Metoda Divide et Impera ...............................................................................40

P
1.4.1. Descrierea metodei Divide et Impera .......................................................40
1.4.2. Implementarea metodei Divide et Impera ................................................41
1.4.3. Cutarea binar ..........................................................................................48
I
1.4.4. Sortarea rapid (QuickSort) ........................................................................50
1.4.5. Sortarea prin interclasare (MergeSort) .......................................................53
1.4.6. Problema turnurilor din Hanoi .....................................................................54
1.4.7. Generarea modelelor fractale .....................................................................56

1.5. Metoda greedy...................................................................................................59


IC

1.5.1. Descrierea metodei greedy.........................................................................59


1.5.2. Implementarea metodei greedy ..................................................................61
1.6. Metoda programrii dinamice..........................................................................70
CT

1.6.1. Descrierea metodei programrii dinamice ..................................................70


1.6.2. Implementarea metodei programrii dinamice ...........................................73
1.7. Compararea metodelor de construire a algoritmilor.....................................83
Evaluare .........................................................................................................................85
DA

2. Implementarea structurilor de date .................................................................. 90


2.1. Tipuri de date specifice pentru adresarea memoriei.....................................90
2.2. Tipul de dat pointer.........................................................................................91
2.2.1. Declarararea varibilelei de tip pointer .........................................................92
DI

2.2.2. Constante de tip adres..............................................................................92


2.2.3. Operatori pentru variabile de tp pointer ......................................................94
2.2.3.1. Operatorii specifici............................................................................94
2.2.3.2. Operatorul de atribuire .....................................................................97
RA

2.2.3.3. Operatorii aritmetici ........................................................................100


2.2.3.4. Operatorii relaionali .......................................................................101
2.3. Tipul de dat referin.....................................................................................102
2.4. Alocarea dinamic a memoriei ......................................................................106
TU

2.5. Clasificarea structurilor de date ....................................................................109


2.6. Lista liniar ......................................................................................................113
2.6.1. Implementarea dinamic a listelor n limbajul C++...................................115
2.6.2. Clasificarea listelor....................................................................................117
I
ED

2.6.3. Algoritmi pentru prelucrarea listelor simplu nlnuite...............................118


2.6.3.1. Iniializarea listei .............................................................................118
2.6.3.2. Crearea listei ..................................................................................118
2.6.3.3. Adugarea primului nod la list......................................................118

C
2.6.3.4. Adugarea unui nod la list............................................................119
2.6.3.5. Parcurgerea listei ...........................................................................121
2.6.3.6. Cutarea unui nod n list ..............................................................121
2.6.3.7. Eliminarea unui nod din list ..........................................................122

I
2.6.3.8. Eliberarea spaiului de memorie ocupat de list ...........................123

OG
2.6.3.9. Liste ordonate.................................................................................124
2.6.3.10. Prelucrarea listelor simplu nlnuite ............................................127
2.6.4. Algoritmi pentru prelucrarea listelor circulare simplu nlnuite ................137
2.6.4.1. Crearea listei ..................................................................................137

AG
2.6.4.2. Parcurgerea listei ...........................................................................138
2.6.4.3. Eliminarea unui nod din list ..........................................................138
2.6.5. Algoritmi pentru prelucrarea listelor dublu nlnuite ................................140
2.6.5.1. Adugarea primului nod la list......................................................140

ED
2.6.5.2. Adugarea unui nod la list............................................................140
2.6.5.3. Parcurgerea listei ...........................................................................141
2.6.5.4. Eliminarea unui nod din list ..........................................................141
2.6.6. Algoritmi pentru prelucrarea stivelor .........................................................145

P
2.6.6.1. Iniializarea stivei ............................................................................145
2.6.6.2. Adugarea unui nod la stiv...........................................................146
2.6.6.3. Extragerea unui nod din stiv.........................................................146
I
2.6.6.4. Prelucrarea stivei............................................................................146
2.6.7. Algoritmi pentru prelucrarea cozilor ..........................................................148
2.6.7.1. Iniializarea cozii .............................................................................149

2.6.7.2. Adugarea unui nod la coad ........................................................149


2.6.7.3. Extragerea unui nod din coad ......................................................149
IC

2.6.7.4. Prelucrarea cozii.............................................................................149


2.6.8. Aplicaii practice ........................................................................................151
Evaluare .......................................................................................................................152
CT

2.7. Graful................................................................................................................159
2.7.1. Definiia matematic a grafului .................................................................159
2.7.2. Graful neorientat .......................................................................................160
2.7.2.1. Terminologie...................................................................................160
DA

2.7.2.2. Gradul unui nod al grafului neorientat............................................162


2.7.2.3. irul grafic ......................................................................................164
2.7.3. Graful orientat ...........................................................................................165
2.7.3.1. Terminologie...................................................................................165
DI

2.7.3.2. Gradele unui nod al grafului orientat..............................................167


2.7.4. Reprezentarea i implementarea grafului.................................................169
2.7.4.1. Reprezentarea prin matricea de adiacen....................................169
2.7.4.2. Reprezentarea prin matricea de inciden .....................................175
RA

2.7.4.3. Reprezentarea prin lista muchiilor (arcelor) ...................................182


2.7.4.4. Reprezentarea prin lista de adiacen (listele vecinilor) ................187
2.7.4.5. Aplicaii practice .............................................................................197
2.7.5. Grafuri speciale.........................................................................................201
TU

2.7.5.1. Graful nul........................................................................................201


2.7.5.2. Graful complet ................................................................................201
2.7.6. Grafuri derivate dintr-un graf.....................................................................203
2.7.6.1. Graful parial...................................................................................203
I
ED

2.7.6.2. Subgraful ........................................................................................207


2.7.6.3. Graful complementar......................................................................211
2.7.4.4. Aplicaii practice .............................................................................212
2.7.7. Conexitatea grafurilor................................................................................213

C
2.7.7.1. Lanul..............................................................................................213
2.7.7.2. Ciclul...............................................................................................218
2.7.7.3. Drumul............................................................................................220
2.7.7.4. Circuitul ..........................................................................................223

I
2.7.7.5. Graful conex ...................................................................................225

OG
2.7.7.6. Graful tare conex............................................................................228
2.7.4.7. Aplicaii practice .............................................................................235
2.7.8. Parcurgerea grafului .................................................................................235
2.7.8.1. Parcurgerea n lime Breadth First ............................................236

AG
2.7.8.2. Parcurgerea n adncime Depth First .........................................240
2.7.8.3. Aplicaii practice .............................................................................246
2.7.9. Graful ponderat .........................................................................................246
2.7.9.1. Definiia grafului ponderat ..............................................................246

ED
2.7.9.2. Matricea costurilor..........................................................................247
2.7.9.3. Algoritmi pentru determinarea costului minim (maxim)..................249
2.7.9.4. Aplicaii practice .............................................................................255
2.7.10. Grafuri speciale.......................................................................................256

P
2.7.10.1. Graful bipartit................................................................................256
2.7.10.2. Graful hamiltonian ........................................................................260
2.7.10.3. Graful eulerian..............................................................................263
I
2.7.10.4. Graful turneu ................................................................................268
2.7.10.5. Aplicaii practice ...........................................................................271
Evaluare .......................................................................................................................272

2.8. Arborele ...........................................................................................................281


2.8.1. Arborele liber.............................................................................................281
IC

2.8.1.1. Definiia arborelui liber ...................................................................281


2.8.1.2. Proprietile arborilor liberi .............................................................281
2.8.2. Arborele parial..........................................................................................283
CT

2.8.2.1. Definiia arborelui parial ................................................................283


2.8.2.2. Definiia arborelui parial de cost minim .........................................283
2.8.2.3. Algoritmi de determinare a arborelui parial de cost minim............285
2.8.2.4. Aplicaii practice .............................................................................292
DA

2.8.3. Arborele cu rdcin.................................................................................292


2.8.3.1. Definiia arborelui cu rdcin........................................................292
2.8.3.2. Implementarea arborelui cu rdcin ............................................297
2.8.3.3. Algoritmi pentru parcurgerea unui arbore cu rdcin ..................299
DI

2.8.3.4. Aplicaii practice .............................................................................304


2.8.4. Arborele binar ...........................................................................................305
2.8.4.1. Definiia arborelui binar ..................................................................305
2.8.4.2. Implementarea arborelui binar .......................................................305
RA

2.8.4.3. Algoritmi pentru parcurgerea unui arbore binar .............................312


2.8.4.4. Aplicaii practice .............................................................................315
2.8.5. Arborele binar de cutare .........................................................................315
2.8.5.1. Definiia arborelui binar de cutare ................................................315
TU

2.8.5.2. Algoritmi pentru prelucrarea unui arbore binar de cutare ............315


2.8.5.3. Aplicaii practice .............................................................................322
2.8.6. Ansamblul Heap........................................................................................323
2.8.6.1. Definiia ansambului Heap .............................................................323
I

2.8.6.2. Algoritmi pentru prelucrarea unui ansamblu Heap.........................324


ED

2.8.6.3. Algoritmul HeapSort .......................................................................327


2.8.5.4. Aplicaii practice .............................................................................329
Evaluare .......................................................................................................................329

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