Sunteți pe pagina 1din 11

INFORMATIC*I* IC.07.

Grafuri

Capitolul IC.07. Grafuri

Cuvinte-cheie
Graf, digraf, nod, arc, muchie,
Parcurgeri n adncime, n lime, sortare topologic

IC.07.1 Aspecte generale

IC.07.1.1 Definii

Definiie: [L01]
Un graf este o pereche G = (V , E ) , unde V este o mulime de vrfuri, iar E este o
mulime de perechi neordonate de vrfuri {u , v} denumite muchii.

Dac e = {u, v} este o muchie din graf, atunci: [L01]


- u i v se numesc extremitile muchiei e.
- e este incident n u i v.
- vrfurile u i v sunt adiacente.

Dac un graf G conine muchii de forma {u, u} , atunci o astfel de muchie se numete
bucl, iar graful G poart numele de graf general sau pseudograf.

Definiie: [C02]
Un digraf este o pereche D = (V , A) , unde V este o mulime de vrfuri, iar A este o
mulime de perechi ordonate de vrfuri (u , v) denumite arce.

Altfel spus, un arc este o muchie pentru care se stabilete un sens. Dac a = (u, v) este
un arc ntr-un digraf, atunci: [C02]
- u este extremitatea iniial (sau sursa) i v este extremitatea final (sau destinaia) a
arcului a.
- u se numete predecesor imediat al lui v, iar v este succesor imediat al lui u.
- a este incident spre interior cu v i incident spre exterior cu u (sau, altfel spus, arcul a
pleac din u i sosete n v).

Definiie: [C02]
Dat fiind un digraf D = (V , A) , atunci nlocuind fiecare arc a = (u, v) cu mulimea
{u , v}, se obine un graf G (D ) numit graful suport al digrafului D.

Reformulnd definiia anterioar, se poate spune c graful G suport al unui digraf D


se obine prin eliminarea sensului (sau a orientrii) arcelor.

0 1 G = (V , E ) , unde:
V = {0,1,2,3}
E = {{0,1},{1,2},{1,3},{2,3}}
2 3
Figura 1: Exemplu de graf

-1-
INFORMATIC*I* IC.07. Grafuri

0 1 D = (V , A) , unde:
V = {0,1,2,3}
A = {(0,1), (2,1), (1,3), (3,2)}
2 3
Figura 2: Exemplu de digraf

Considernd exemplele din Figurile 1 i 2, se observ c graful G prezentat n Figura


1 este graful suport pentru digraful D prezentat n Figura 2.

Definiie: [L01]
Se numete mers de la u la v n graful G o secven:
u = v0 ,{v0 , v1}, v1 ,...,{vn1 , vn }, vn = v,
unde vi ,0 i n sunt vrfuri n G, iar {vi 1 , vi },1 i n sunt muchii n G.

Definiii: [L01]
Un mers pentru care toate vrfurile sunt distincte se numete parcurs.
Un mers pentru care toate muchiile sunt distincte se numete drum.
Un drum pentru care extremitile coincid se numete circuit.

Definiii:
Fie un graf G = (V , E ) . Gradul unui vrf u din graful G reprezint numrul total de
muchii incidente cu vrful u.
Fie un digraf D = (V , A) . Pentru orice vrf u se definesc:
- gradul interior al vrfului numrul total de arce incidente spre interior cu u
(sau, reformulnd, numrul total de arce care intr n vrful u);
- gradul exterior al vrfului numrul total de arce incidente spre exterior cu u
(sau, altfel spus, numrul total de arce care pleac din vrful u).

Observaie:
n continuare, vrfurile unui graf/digraf vor fi numite noduri.

IC.07.1.2 Tipuri de grafuri

Un graf G/digraf D este complet dac fiecare nod este conectat cu toate celelalte
noduri din graf/digraf (altfel spus, toate nodurile sunt adiacente).
Un graf G = (V , E ) este bipartit dac:
V = V1 V2 , a.i.V1 V2 = i
{i, j} E , atunci i V1 , j V2 sau j V1 , i V2 . [C02]
Similar, un digraf D = (V , A) este bipartit dac:
V = V1 V2 , a.i.V1 V2 = i
(i, j ) A, atunci i V1 , j V2 sau j V1 , i V2 . [C02]

Un graf G = (V , E ) se numete conex dac u, v V , exist drum de la u la v. Un


digraf D = (V , A) se numete conex dac graful su suport este conex. Un digraf D = (V , A)
se numete tare conex dac u, v V , atunci exist un drum de la u la v i un drum de la v la

-2-
INFORMATIC*I* IC.07. Grafuri

u. Un digraf D = (V , A) se numete unilateral conex dac u, v V , atunci exist un drum


de la u la v sau un drum de la v la u [C02].

IC.07.1.3 Operaii pe grafuri [L01]

Nume operaie Descriere


GrafVid Intare: nimic
Ieire: un graf G
Rol: o astfel de metod poate fi utilizat pentru instanierea
unui obiect de tip graf
EsteGrafVid Intrare: un graf G = (V , E )
Ieire: valoare de tip boolean
- true dac graful este vid (nu conine noduri);
- false n caz contrar.
InsereazNod Intrare: un graf G = (V , E ) , cu V = {0,1,..., n 1}
Ieire: graful G la care se adaug vrful izolat n.
InsereazMuchie Intrare: un graf G = (V , E ) i dou noduri diferite i, j V
Ieire: graful G la care se adaug muchia {i, j}
tergeVrf Intrare: un graf G = (V , E ) i un nod k V
Ieire: graful G din care au fost eliminate toate muchiile
incidente n k, iar nodurile i > k au fost redenumite i 1 .
tergeMuchie Intrare: un graf G = (V , E ) i dou noduri diferite i, j V
Ieire: graful G din care a fost eliminat muchia {i, j} .
ListAdiacen Intrare: Intrare: un graf G = (V , E ) i un nod k V
Ieire: mulimea nodurilor adiacente cu nodul k.
ListVrfuriAccesibile Intrare: Intrare: un graf G = (V , E ) i un nod k V
Ieire: mulimea nodurilor pentru care exist un drum de la
nodul k.

Observaie:
Operaiile definite anterior se pot aplica i peste digrafuri.

IC.07.2 Modaliti reprezentare a grafurilor

Structurile de tip graf/digraf sunt n mod uzual reprezentate fie prin matrici de
adiacen, fie prin liste de adiacen.

IC.07.2.1 Reprezentarea grafurilor prin matrici de adiacen

O matrice de adiacen reprezint un tablou bidimensional. n cadrul acestui tablou,


locaia [i,j] indic prin valoarea stocat dac exist o muchie (sau un arc n cazul digrafurilor)
ntre nodul i i nodul j (sau, pentru digrafuri, un arc de la nodul i la nodul j). n general, pentru
a marca faptul c exist o muchie/un arc ntre nodurile i i j se stocheaz n matrice n locaia
corespunztoare valorea 1, n caz contrar memorndu-se valoarea 0. Considernd n numrul
total de noduri din graf/digraf, o matrice de adiacen are dimensiune n n (sau, altfel spus,
necesarul de memorie destinat stocrii unui graf/digraf este de clas O(n 2 ) ).
Pentru exemplele prezentate n Figurile 1 i 2 matricile de adiacen corespunztoare
sunt prezentate n tabelul urmtor:

-3-
INFORMATIC*I* IC.07. Grafuri

Graf Figura 1 Digraf Figura 2

0 1 2 3 0 1 2 3
0 0 1 0 0 0 0 1 0 0
1 1 0 1 1 1 0 0 0 1
2 0 1 0 1 2 0 1 0 0
3 0 1 1 0 3 0 0 1 0

Un prim lucru ce se poate remarca este faptul c matricea de adiacen prin care se
descrie un graf este o matrice simetric fa de diagonala principal.
Un graf/digraf pentru care, din punct de vedere logic, este important doar existena
muchiilor/arcelor mai poart numele graf/digraf neponderat. Exist situaii n care pentru
grafuri/digrafuri este important att existena muchiei (sau a arcului), ct i un cost asociat.
n aceste cazuri grafurile/digrafurile se numesc grafuri/digrafuri ponderate. Acestea din
urm sunt reprezentate prin intermediul unor matrici de adiacen ponderate. Un exemplu
este prezentat n figura de mai jos:

0 2 1 0 2 1

1 1
5

5
2 4 3 2 4 3

Matricea de adiacen Matricea de adiacen


0 1 2 3 0 1 2 3
0 0 2 0 0 0 0 2 0 0
1 2 0 1 5 1 0 0 0 5
2 0 1 0 4 2 0 1 0 0
3 0 5 4 0 3 0 0 4 0

a) Graf ponderat b) Digraf pronderat


Figura 3: Exemplu de graf/digraf ponderat

IC.07.2.2 Reprezentarea grafurilor prin liste de adiacen

Reprezentarea grafurilor (sau a digrafurilor) prin liste de adiacen implica stocarea


unui vector de n pointeri (unde n este numrul de noduri din graf/digraf) ctre structuri de
tipul liste liniare simplu nlnuite. Un element n cadrul unei liste liniare va stoca nodul
adiacent cu nodul curent i informaia de nlnuire. Declararea unui astfel de element se
realizeaz (limbajul C++):
struct Element {
int vecin;
Element* leg;
};

Declararea unui graf/digraf utiliznd liste de adiacen (limbajul C++):

Declarare static (n numrul de noduri) Declarare dinamic


(n numrul de noduri)
Element graf[n]; Element *graf;
graf = new Element[n];

-4-
INFORMATIC*I* IC.07. Grafuri

Declaraiile de mai sus pot fi, la rndul lor, ncapsulate n cadrul unei structuri astfel
nct informaiile ce descriu un graf/digraf s fie stocate n interiorul aceleiai entiti:

Structur static pentru reprezentrea Structur dinamic pentru reprezentrea


grafurilor grafurilor
struct Graf { struct Graf {
int nrNoduri; int nrNoduri;
Element liste[DIM_MAX]; Element * liste;
}; };
... ...
Graf g; Graf g;

Observaii:
1. n cadrul declaraiilor de mai sus, constanta DIM_MAX reprezint numrul maxim
de noduri pe care le poate avea un graf descris de structura respectiv (constant
definit de utilizator).
2. Pentru grafurile neorientate, o muchie ntre nodurile i i j va fi memorat de dou
ori: o dat n lista de adiacen a nodului i i, a doua oar, n lista de adiacen a
nodului j.

Necesarul de memorie pentru stocarea unui graf/digraf prin intermediul listelor de


adiacen este de ordinul O(n + E ) (n numrul de noduri din graf/digraf, E - numrul de
muchii din graf/numrul de arce din digraf). Schematic, reprezentarea prin intermediul listelor
de adiacen a grafurilot din Figurile 1 i 2 sunt prezentate n figura urmtoare:

0 1
1 0 2 3
2
3 1 3
1 2
Figura 4: Reprezentarea grafului expus n Figura 1

0 1
1 3
2
3 1
2
Figura 5: Reprezentarea digrafului expus n Figura 2

Observaie:
Dei este o tehnic mai puin utilizat, un graf/digraf ponderat poate fi reprezentat i
prin intermediul listelor de adiacen ponderate. Pentru a putea realiza acest lucru,
structura Element declarat anterior se modific dup cum urmeaz:
struct Element {
int vecin, pondere;
Element* leg;
};

-5-
INFORMATIC*I* IC.07. Grafuri

IC.07.3 Modaliti de parcurgere a grafurilor: n adncime, n lime

n cazul cel mai general, problema parcugerii unui graf nseamn vizitarea, dup un
anumit set de constrngeri, a uneia dintre cele dou mulimi caracteristice grafului/digrafului.
De cele mai multe ori, muimea vizat n explorare este mulimea nodurilor. n acest caz,
problema explorrii sistematice a unui graf/digraf se poate defini astfel [C02]:

Dat fiind un vrf i ntr-un graf/digraf, s se genereze lista vrfurilor accesibile din i.

Pseudocodul general al algoritmului (Tarjan, 72) [C02]


Notaii: S mulimea nodurilor accesibile din i la un moment dat:

1. explorare(D,i)
2. S <- {i};
3. marcheaza toate arcele ca fiind neutilizate;
4. while(exista arce neutilizate care pleca din vfufuri din s) do
5. alege j din S si un arc neutilizat (j,k) din A;
6. marcheaza (j,k) ca fiind utilizat;
7. adauga k la S;
8. end-while
9. end

O variant mai complet a pseudocodului anterior este urmtoarea:

Pseudocod general al algoritmului de explorare variant complet:


Notaii: S mulimea nodurilor accesibile din i la un moment dat;
Sprim mulimea nodurilor care au nc arce neutilizate.

1. explorare2(D,i)
2. S <- {i}; Sprim <- {i};
3. while (Sprim contine noduri) do
4. alege j din Sprim;
5. if(nu mai exist muchii neutilizate incidente din j)then
6. elimina j din Sprim;
7. else
8. fie (j,k) urmatorul arc neutilizat incident din j;
9. if (k nu este in S) then
10. proceseaza (k);
11. S <- S U {k};
12. Sprim <- Sprim U {k};
13. end-if
14. end-if
15. end-while
16. end

n funcie de restriciile ce se impun asupra mulimii Sprim (i, respectiv, n funcie de


modul de implementare practic) se pot obine dou tipuri de explorri ale
grafurilor/digrafurilor [C02]:
- dac Sprim este o stiv, atunci procedura explorare2 realizeaz explorarea n
adncime a grafului/digrafului int;
- dac Sprim este o coad, atunci procedura explorare2 realizeaz explorarea n lime
a grafului/digrafului int.

Conceptual, cele dou tipuri de explorri pot fi formulate astfel:

-6-
INFORMATIC*I* IC.07. Grafuri

Explorarea n adncime
Pentru fiecare nod nou accesibil, se aplic rnd pe rnd o procedur de vizitare
pentru fiecare nod vecin neprocesat nc (sintagma rnd pe rnd trebuie interpretat
n acest caz n sensul de se aplic n iteraii diferite).

Explorarea n lime
Pentru fiecare nod nou accesibil, se aplic simultan o procedur de vizitare pentru
toate nodurile vecine neprocesate nc (cuvntul cheie simultan se interpreteaz n
acest caz n sensul de se aplic n cadrul aceleiai iteraii).

IC.07.3.1 Parcurgerea grafurilor n adncime

Pseudocod algoritm iterativ [C02]:

Notaii:
- S vector de n locaii prin intermediul cruia se marcheaz dac nodul de index i a
fost vizitat sau nu; vectorul se iniializeaz cu valori de 0 (n sensul c nodurile nu au
fost procesate/vizitate);
- st o structur de tip stiv;
- Graf G o structur de tip graf dup modelul menionat anterior;
- i (parametru de intrare) indexul nodului de start pentru parcurgere.

1. DFS_iter(G, i)
2. for (j=0,...,n-1) do
3. p[j] = G.liste[j];
4. end-for
5. proceseaza (i); //se proceseaza nodul de start
6. S[i] = 1; //se marcheaza nodul de start ca fiind vizitat
7. initStack (st);
8. push (st, i);
9. while (!isEmpty (st)) do
10. j = top (st);
11. if (p[j] == NULL) then //nu mai exista vecini ai nodului
12. //j care nu au fost vizitati
13. pop (st);
14. else
15. k = p[j]->vecin;
16. p[j] = p[j]->leg;
17. if (S[k] == 0) then //nodul k nevizitat
18. proceseaza (k);
19. S[k] = 1;
20. push (st, k);
21. end-if
22. end-if
23. end-while
24. end

Structura de date caracteristic acestui tip de explorare este o stiv. n acest caz,
pseudocodul prezentat mai sus poate fi implementat ntr-o manier recursiv.

-7-
INFORMATIC*I* IC.07. Grafuri

Pseudocod algoritm recursiv [C02]

1. DFS_rec(G, i)
2. proceseaza (i); //se proceseaza nodul de start
3. S[i] = 1; //se marcheaza nodul de start ca fiind vizitat
4. p = G.liste[i];
5. while (p != NULL) do
6. if (S[p->vecin] == 0) then
7. DFS_rec (G, p->vecin);
8. end-if
9. p = p->leg;
10. end-while
11. end

IC.07.3.2 Parcurgerea grafurilor n lime

Pentru acest caz, dup cum a fost menionat i n paragrafele anterioare, structura
caracteristic de explorare este o structur de tip coad. Acest lucru implic un algoritm
iterativ.

Pseudocodul algoritmului [C02]:


Notaii:
- S (similar parcugerii n adncime) vector de n locaii prin intermediul cruia se
marcheaz dac nodul de index i a fost vizitat sau nu; vectorul se iniializeaz cu
valori de 0 (n sensul c nodurile nu au fost procesate/vizitate);
- q o structur de tip coad;
- Graf G o structur de tip graf dup modelul menionat anterior;
- i (parametru de intrare) indexul nodului de start pentru parcurgere.

1. BFS (G, i)
2. proceseaza (i);
3. S[i] = 1;
4. put (q, i);
5. while (!isEmpty (q)) do
6. j = get (q);
7. p = G.liste[j];
8. while (p != NULL) do
9. k = p->vecin;
10. if (S[k] == 0) then
11. proceseaza (k);
12. S[k] = 1;
13. put (q, k);
14. end-if
15. p = p->leg;
16. end-while
17. end-while
18. end

Aplicaii ale parcurgerii n lime sortarea topologic

Sortarea topologic a unui digraf aciclic const n determinarea unei liste liniare a
nodurilor din digraf pe baza unui criteriu numit preceden. Astfel, oricare ar fi dou noduri u
i v ntr-un digraf, dac exist arc de la u la v, atunci nodul u apare naintea nodului v n lista
liniar sortat [L01][C02]. Altfel spus, pentru un digraf aciclic D = (V, A) ,
u, v V, u < v (u, v) A . Conform acestei relaii de ordine, primele valori din lista sortat

-8-
INFORMATIC*I* IC.07. Grafuri

vor fi alese dintre nodurile fr predecesori (se spune despre un nod c nu are predecesori
dac acel nod nu are arce incidente n el). Aceste noduri se mai numesc surse [L01][C02].
Principiul algoritmlui este urmtorul [L01][C02]:
1. se iniializeaz o coad de explorare cu cu nodurile surs;
2. se extrage un nod u din coada de explorare i se adaug n lista parial ordonat;
3. se elimin din reprezentarea lui digrafului nodul u i toate arcele incidente din u
(arcele care pleac din nodul u);
4. dac n timpul eliminrilor de la pasul 3. se identific noduri v care rmn fr
predecesori, atunci aceste noduri vor fi introduse n coada de explorare;
5. se repet paii 2. 4. pn coada de explorare devine vid.

Not:
Stuctura de date prin intermediul creia vom stoca digraful pentru sortare topologic
va fi:
struct Graf {
int nrNoduri;
Element * liste;
int * np;
};
n cadrul acestei structuri membrul np nou adugat este un pointer ce va indica un
vector de nrNoduri locaii de tip int. Pentru orice nod i {0,..., nrNoduri 1} din
digraf, D.np[i] va stoca numrul de predecesori ai nodului i.

Pseudocodul algoritmului de sortare topologic [L01][C02]:


Notaii:
- q o structur de tip coad;
- l o list liniar simplu nlnuit pentru care metoda insertEnd realizeaz inserarea
la sfrit de list;
- Graf D (parametrul de intrare) o structur de tip graf dup modelul de mai sus;
- Element *p un pointer ctre un element de tip list liniar simplu nlnuit.

1. sortareTopologicaBFS (D)
2. init (q);
3. for (u=0; u<D.nrNoduri; u++) do
4. if (D.np[i] == 0) then
5. put (q, u);
6. end-if
7. end-for
8. for (k=0; k<D.nrNoduri; k++) do
9. if (isEmpty (q)) then
10. return (digraful contine cicluri);
11. end-if
12. u = get (q);
13. insertEnd (l, u);
14. p = D.liste[u];
15. while (p != NULL) do
16. D.np[p->vecin] = D.np[p->vecin] 1;
17. if (D.np[p->vecin] == 0) then
18. put (q, p->vecin]);
19. end-if
20. p = p->leg;
21. end-while
22. end-for
23. end

-9-
INFORMATIC*I* IC.07. Grafuri

Considerm digraful din figura urmtoare:

Figura 6: Digraf exemplu pentru sortare topologic

Numrul de predecesori ai fiecrui nod n parte este:


- nodurile 0, 6 i 7 nu au arce incidente n nod, ceea ce implic 0 predecesori;
- nodurile 1, 3 i 5 au fiecare cte un arc incident n nod, deci fiecare nod are cte 1
predecesor;
- nodurile 4 i 2 au fiecare cte dou arce incidente n nod, ceea ce implic un numr de
2 predecesori pe nod.

Dup etapa de iniializare (etapa n cadrul creia se determin numrul de predecesori


pentru fiecare nod n parte), urmeaz etapa de iniializare a cozii de explorare. Conform
observaiilor anterioare, n aceast coad vor fi introduse nodurile 0, 6, 7. Analiznd Figura 6,
se pot face urmtoarele observaii:
- oricare ar fi un drum care conine nodurile 0, 6 sau 7, acest drum ncepe din aceste
noduri;
- nu exist nici un drum care s includ simultan cele 3 noduri amintite la punctul
anterior, ceea ce implic faptul c ntre aceste noduri nu se poate stabili o relaie de
ordine (altfel spus, pentru aceste 3 noduri nu exist un criteriu de preceden).
Presupunem acum c ordinea n care se insereaz cele 3 noduri n coada de explorare
este: 0, 6, 7 (ordinea cresctoare a valorilor din noduri). Conform algoritmului prezentat (linia
12), nodul 0 va fi primul extras din coada de explorare pentru a fi inserat apoi n lista liniar
simplu nlnuit ce va reine n final ordinea topologic a nodurilor. Pentru acest nod, vor fi
apoi procesai simultan (n cadrul aceleiai iteraii liniile de cod 15 -> 21) toi vecinii direci
(practic, datorit acestui mod de procesare se spune ca algoritmul de sortare topologic este o
aplicaie direct a algoritmului de parcurgere BFS). Procesarea const n decrementarea
numrului de predecesori pentru vecinii nodului curent i includerea n coada de procesare a
acelor vecini care rmn fr predecesori. Bucla principal a algoritmului se repet apoi n
aceeai manier pn cnd sunt atinse toate nodurile din graf.

S considerm acum digraful din Figura 7.

Figura 7: Contra-exemplu pentru algoritmul de sortare topologic

-10-
INFORMATIC*I* IC.07. Grafuri

Analiznd digraful prezentat n Figura 7, se pot obine urmtoarele drumuri:

0 1 2
2 0 1
1 2 0

Considernd criteriul de precende amintit anterior (nodul i este mai mic dect nodul j
dac, oricare ar fi un drum care trece simultan prin cele dou noduri, i apare naintea lui j,
obinem:
0 <1< 2
2 < 0 <1
1< 2 < 0

Relaiile de mai sus reprezint, n mod evident, o absurditate. n concluzie, algoritmul


de sortare topologic nu poate fi aplicat pe digrafuri ce conin cicluri.

Aplicaii

1. Evaluai complexitatea timp pentru algoritmii prezentai n cadrul acestui capitol. Se


consider pentru analiz cazurile n care grafurile/digrafurile sunt reprezentate prin
liste de adiacen. Cum se modific aceste clase de complexitate n momentul n care
grafurile/digrafurile sunt reprezentate prin matrici de adiacen?
2. Implementai n C/C++ algoritmii propui n cadrul acestui sub-capitol. Contorizai
pentru fiecare rulare numrul de operaii efectuate. Corelai aceast informaie cu
analiza realizat n cadrul primei probleme.
3. Propunei un algoritm bazat pe explorarea DFS pentru problema sortrii topologice.

Bibliografie
[L01] Lucanu D., Craus M., Proiectarea Algoritmilor, Cap. 2: Tipuri de date de nivel nalt,
Editura Polirom, ISBN 978-973-46-1140-9, 2008
[C02] Craus M., Proiectarea Algoritmilor Note de curs, Universitatea Tehnic Gheorghe
Asachi din Iai, Facultatea de Automatic i Calculatoare

-11-

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