Documente Academic
Documente Profesional
Documente Cultură
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
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
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.
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
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
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
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
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}.
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
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
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
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
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
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
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
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
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;
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
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
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
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
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:
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
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
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++)
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
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
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
trebuie s fie ambele pare sau ambele impare. Indicaie. n subprogramul valid() se
mai verific i condiia suplimentar de vecintate.
int valid()
DA
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
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
cout<<endl;} cout<<endl;}
void bt() void bt(int k)
{//partea fix a algoritmului} {//partea fix a algoritmului}
void main() void main()
RA
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
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;
{st[k]=-1;} {st[k]=0;}
int succesor() int succesor(int k)
{if (st[k]<1) {if (st[k]<st[k-1]+1)
CT
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.
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
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];
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
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
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
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
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.
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
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
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++)
s-=st[k];} s-=st[k];}
void bt() void bt(int k)
{//partea fix a algoritmului} {//partea fix a algoritmului}
CT
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 (!este) cout<<"Imposibil"; }
Scriei urmtoarele programe, n care s folosii metoda backtracking pentru
Tem generarea tuturor partiiior unui numr natural.
RA
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.
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
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
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
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
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;
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).
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
gseasc pe linia i.
Dama din coloana k nu trebuie s se g-
seasc pe diagonala cu dama din coloa- i-p, k
I
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 }
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
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
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
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)) .
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
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-
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
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
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
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;
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>
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
for (i=1;i<=n;i++)
ED
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
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
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
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
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
nerea continu pn cnd trebuie determinai termenii f1 i f2, a cror valoare este
cunoscut.
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
{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
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:
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
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
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
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
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
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
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;
{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
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;}
{int mijl;
if (d==s)
if (d<=minim(n,m)) r[d]=p[d]+q[d];
CT
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
#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.
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
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
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
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
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
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
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.
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.
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
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;
{int i=s,j=d,pi=0,pj=1;
// pivotul fiind pe pozitia s, parcurgerea incepe cu indicele j
while (i<j)
CT
{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
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
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
k
ED
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
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
{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
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
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
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
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,
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
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
#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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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-
#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
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
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
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
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)
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
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
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-
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
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
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.
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
tricei sumelor).
Subprogramul afiseaza() afieaz suma maxim i soluia problemei folosind infor-
maiile din matricea p.
Strategia programrii dinamice este implementat astfel:
RA
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
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.
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
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
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
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
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();}
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.
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
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
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];
j-=a[p[i][j]].g;
while (p[i][j]==k) i--;}}
void main()
CT
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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.
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
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
4 octei
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.
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
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
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
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
structuri.
<nume variabil pointer> > <nume cmp>
El conine dou referine: una la coninutul adresei indicate de pointer i alta ctre un
DI
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
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
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
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:
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
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
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
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
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
Exemplul 6:
int *q;
q=0; // pointerului q i se atribuie constanta 0
cout<<*q<<endl; /*nu afieaz nimic, deoarece pointerul q are
DI
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
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
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
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
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)
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
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
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
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
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
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
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
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.
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
AG
a[1][0] a[1][1] a[2][0] a[2][1] Nivelul 3
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
Din studiul de caz anterior putem folosi un nou criteriu pentru clasificarea structurilor
de date:
criteriul relaiei de ordine
RA
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
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.
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.
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
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
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.
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
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
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
P
n funcie de modul n care sunt aranjate elementele n list, se pot folosi metodele:
Metode de implementare a listelor
I
secvenial nlnuit
static secvenial nu nu
static nlnuit nu da
dinamic nlnuit da da
DA
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
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
adr5 adr4
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
.............................................
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.
(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
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
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;}
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
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
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
prim ultim
info urm info urm info urm info NULL
RA
p info NULL
p devine nodul ultim
TU
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
anume: informaia din predecesorul nodului q trebuie s fie anterioar ei, iar informaia din
p v2 urm
(2)
prim q q->urm ultim
TU
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)
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
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;}
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
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
C
Eliminarea ultimului nod
prim ultim
I
OG
info urm info urm info NULL info NULL
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).
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
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
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;}
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;
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
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
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
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
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);}
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
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
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;
{nod *prim1,*prim2,*prim3,*q,*r,*p;
creare(prim1); creare(prim2);
if (prim2->info>prim1->info)
CT
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
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)
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
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
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
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);
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
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
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);
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
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
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
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
#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
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
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
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);}}}}
cout<<endl;}
void main()
{nod *prim1,*ultim1,*prim2,*ultim2,*prim3,*ultim3,*prim4,*ultim4;
CT
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
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
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
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.
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
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
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.
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
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
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<<" ";
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
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.
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
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
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
C
Adugarea n interiorul listei
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-
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
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);}
{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
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);}
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
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
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
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-
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
Scop: exemplificarea modului n care, pentru rezolvarea problemei, folosii algoritmii de prelu-
RA
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
{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
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
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
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
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
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
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
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).
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. 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
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.
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:
Caut (L,k)
Adaug (L,x)
Elimin (L,x)
CT
Succesorul (L,x)
Predecesorul (L,x)
Minim (L)
Maxim (L)
DA
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(k=0,p=prim;p->info!=0;p=p->urm)
Informatic 153
C
if (p->urm->info-p->info==1) k++;
cout<<k;
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;
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
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
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
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
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
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
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
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
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
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
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
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:
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
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
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
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
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
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
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
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
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
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
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
(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.
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
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
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
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
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
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
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
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
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] }.
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
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
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.
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
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.
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
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
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
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<<" ";
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 j,g=0;
for (j=1;j<=n;j++) g+=a[j][i]; return g;}
void main()
{int i,j,k;
RA
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=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
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;
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
void generare()
{int k=0,i,j; randomize();
while(k<m)
{i=rand()%n+1; j=rand()%n+1;
I
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}.
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
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
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:
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
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
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
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
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
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;
{int i,j,p,k;
cout<<"numar de noduri "; cin>>n; cout<<"numar de muchii "; cin>>m;
for(k=1;k<=m;k++)
CT
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
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++)
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(); }
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;
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
{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).
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
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
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
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
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
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
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
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
{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
#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
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
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
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.
Din lista de adiacen implementat static cu matrice putei obine urmtoarele informaii:
IC
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
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
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]).
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
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
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].
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
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;
{f1>>x;
if (x==0) L[2][i]=0;
else {L[2][i]=j;
CT
f1.close();}
int grad(int i)
{int g,j=L[2][i];
if (L[2][i]==0) g=0;
else {g=1;
DI
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;
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
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
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
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
{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
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
f.close();}
void afisare vecini()
{for (int i=1;i<=n;i++)
{cout<<"Vecinii nodului "<<i<<": ";
RA
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.)
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
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
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
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
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
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
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).
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=),
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
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
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
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
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
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
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
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
#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
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(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
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
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
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
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
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
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.
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
#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
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
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()
return 1;}
void main()
{int i,j; f1>>n;
for(i=1;i<=n;i++)
DA
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
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
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
{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
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
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.
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
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
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
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
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
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
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-
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
{as=1; ev=0;
ED
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);
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
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
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())
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
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
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
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
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
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
2.7.7.3. Drumul
TU
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
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
#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
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";}
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
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
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
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
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
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
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.
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);
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
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}.
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
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
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
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
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
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.
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
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
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.
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;
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
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();}
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
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
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
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
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
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 componente()
{for(int i=1;i<=n;i++)
if (v[i]==0)
{nr++; v[i]=1; cout<<endl<<"Componenta "<<nr<<": "<<i<<" ";
TU
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,
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
muchiile (arcele) adiacente s fie atins o singur dat. Vecinii unui nod sunt reprezentai
ED
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
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
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
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
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
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
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
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
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
(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<<": ";
cout<<endl;}
cout<<endl;}
void main()
{citeste();
DA
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
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
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
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
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
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 ||
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
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
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).
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 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
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;}
{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
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.
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
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
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
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
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
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.
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
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
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
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
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
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
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
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])
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
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
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.
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
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
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
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
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
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
{d[i]=a[x][i];
if (i!=x && d[i]<MAX) p[i]=x;}
for(i=1;i<=n-1;i++)
CT
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
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.
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
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
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.
grafuri hamiltoniene:
grafuri euleriene:
grafuri turneu.
CT
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
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
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
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;}}}}
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
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
#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
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
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
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
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
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
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
#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
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
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
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
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.
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
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
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
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
#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
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 (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
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.
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
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
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
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
PAS1. Dac exist arcul [1,2], atunci D[1]=1 i D[2]=2; altfel, D[1]=2 i D[2]=1.
ED
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
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
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
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
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
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.
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
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
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
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
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
a. 6 b. 3 c. 4 d. 5
26.Numrul de componente tare conexe este:
a. 1 b. 3 c. 2 d. 4
CT
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. 4 b. 8 c. 27 d. 7
ED
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
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
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
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
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.
principal cu
a. 2 b. 0 c. 3 d. 1
(Bacalaureat Sesiunea iunie-iulie 2004)
CT
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
a. 3 4 3 2 4 b. 3 1 2 3 c. 2 1 3 4 d. 4 3 1 2
ED
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
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
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
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
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
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
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
(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
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
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.
Un graf G conine un arbore parial dac i numai dac este un graf conex.
Demonstraie. Notm cele dou propoziii, astfel:
DA
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.
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
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
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
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
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
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
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
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
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
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<<"["<<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
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
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
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
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
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
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
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();}
{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
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
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
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.
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
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
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
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
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
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 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
C
cod, pre, funcia realizat, costul asamblrii, firma care o produce etc. S se determine
preul produsului (figura 59).
I
Produs
OG
final
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
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
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
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,
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
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
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
Structura de date folosit este coada (c) n care se adaug fiii nodului
prelucrat.
Algoritmul pentru parcurgerea arborelui este urmtorul:
RA
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
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
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
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
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
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;}
{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
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
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
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
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.
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
Fig. 65
a. Afiai lista angajailor care au funcii de conducere (numele compartimentului i
DA
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
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.
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
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
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
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
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
E 5
zy y
A
A
ED
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;
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
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
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
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
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
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
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)) ... }
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
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
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
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
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.
Se numete cheie un cmp din informaia util a nodului care poate fi folosit pentru a
IC
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.
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;
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
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
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
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
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
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);
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
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
Fig. 83
DI
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
void main()
{int k; ... cout<<"Cheia care se sterge: "; cin>>k; stergere(r,k); ...}
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).
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
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
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 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
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
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
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
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
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
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
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)
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
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
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
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
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
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
a. 2 b. 4 c. 3 d. 5
23.Numrul de nivele ale arborelui este:
a. 2 b. 3 c. 4 d. 5
TU
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:
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
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
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
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.7. Graful................................................................................................................159
2.7.1. Definiia matematic a grafului .................................................................159
2.7.2. Graful neorientat .......................................................................................160
2.7.2.1. Terminologie...................................................................................160
DA
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