Sunteți pe pagina 1din 49

Colegiul Naional Roman-Vod

Proiect pentru obinerea atestatului de


competene profesionale

Elev: Profesor coordonator:


Dumea Eduard Constantin Gavril Petru Florin

Roman
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

Mai 2011

Tem proiect :
Programare orientat pe obiect.
Grafuri neorientate.

2
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

Cuprins
Cuprins........................................................................................................................................ 3
Argument......................................................................................................................................4

1. 5
Programare orientat pe obiect (noiuni introductive)..........................................
2. Grafuri neorientate ......................................................................................... 9
2.1 Noiuni introductive............................................................................................9
2.2 12
Modaliti de reprezentare.....................................................................................

3. Algoritmi eseniali grafuri neorientate...............................................................


14

3.1 Citirea grafurilor..14


3.2 14
Afiarea grafurilor..
3.3 14
Parcurgerea grafurilor..
3.4 16
Lan. Lan elementar. Ciclu. Ciclu elementar..
3.5 16
Graf complementar..
3.6 17
Graf bipartit..
3.7 17
Graf conex. Numarul de componente conexe
3.8 Graf hamiltonian..................................................................................................18
3.9 18
Graf eulerian
19
3.10 Algoritmul Bellman-Ford.
22
3.11 Algoritmul lui Kruskal..
24
3.12 Algoritmul lui Prim
27
3.13 Grafuri izomorfe....................................................................................................
3.14 Supraincarcarea operatorilor.............................................................................. 27

4. Clasa graf.........................................................................................................28
4.1 graf.h................................................................................................................ 29
4.2 graf.cpp............................................................................................................ 30

3
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

5. 50
Bibliografie...........................................................................................................

Argument

nc de la apariia limbajelor de programare s-a ncercat ca acestea s descrie cat mai bine
realitatea. Programarea Orientata pe Obiecte (POO) este o modalitate avansat de programare care
se apropie foarte mult de acest scop. Cuvantul cheie e obiectul (clasa).
Am ales graful ca tem pentru realizarea proiectului deoarece consider c grafurile au o
importan deosebit fiind utilizai n domenii precum: cibernetic, matematic, cercetri
operaionale n vederea optimizrii diferitelor activiti economice, chimie (pentru descrierea
structurii cristalelor), reelele de transport de toate tipurile (pentru optimizarea traseelor), circuite
electrice (pentru simularea funcionri corecte), inteligena artificiala i nu n ultimul rnd n
domeniul analizei aplicaiilor software.

4
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

1. Programare orientat pe obiect

(noiuni introductive)

Programarea orientat pe obiecte este o tehnologie modern n domeniul programrii


calculatoarelor, care a rezultat din necesitatea realizrii de aplicaii din ce n ce mai complexe.
Programarea clasic i structurata avea urmatoarele dezavantaje: control greoi al programelor de
dimensiuni mari, dificultati cu privire la reutilizarea codurilor de programe i inflexibiliatea
adaptarii i extinderii unor module de program deja realizate. Programarea clasic structurata are la
baza celebra ecuatie a lui Nikolaus Wirth:
Program = Structuri de date + Algoritmi
Programarea orientat pe Obiecte, POO, se fundamenteaza pe conceptul de obiect,
care este definit printr-o multime de date, numite proprieti, i o multime de proceduri sau
funcii de prelucrare ale acestor date, numite metode. n consecinta, ecuatia POO este:
Obiect = Date + Funcii
sau
Obiect = Date + Funcii

Obiect = Proprieti + Metode


Diferenta dintre cele dou ci de abordare ale programarii calculatoarelor const n
maniera de abordare a programarii. n timp ce programarea clasic structurata se concentreaza pe
prelucrarea datelor, adic pe programe, proceduri i funcii, POO se bazeaza pe definirea
obiectelor, adic, pe proprietile acestora, numite date, i pe funciile acestor obiecte, numite
metode.

Clase i obiecte

La baza POO stau conceptele de clas i de obiect.

5
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

Definitia 1

Clasa, ntr-un anumit limbaj de programare, reprezin definirea unui tip de obiecte
abstracte sau concrete, adic descrierea proprietilor, a datelor i a metodelor, a prelucrrilor,
posibile asupra datelor. Clasa este, de fapt, o noiune abstracta, care defineste un anumit tip de
obiecte, sau, altfel spus, o clas reprezin mulimea posibila a mai multor obiecte de acelasi tip.

Definitia 2

Obiect, reprezin o multime de date care descrie un anumit obiect concret sau
abstract, numite i proprieti, impreuna cu procedurile, funciile, de prelucrare a cestora, numite
metode.

Crearea unui obiect presupune specificarea clasei din care face parte, astfel
idendtificndu-se proprietile obiectului i modul n care acestea pot fi folosite i prelucrate

Observaie:

Crearea sau declararea unui obiect este similar cu crearea sau declararea unor variabile.
Declararea unei variabile se face, dup cum se stie, prin specificarea identificatorului acesteia,
precedat de tipul variabilei iar declararea unui obiect presupune precizarea identificatorului
acestuia, precedat de clasa din care face parte, clasa care n mod implicit determin proprietile i
metodele obiectului definit.

O clas n limbajul C++ poate fi reprezentata ca o extindere a conceptului de structura,


care, ca i o structura, descrie un ablon pentru viitoarele declarari de variabile obiect.

Definirea generala a unei clase n C++

n fiierul nume_clasa.h:

class [nume_clasa]
{

6
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

specificator_acces1;
date_i_funcii1;
specificator_acces2;
date_i_funcii2;
..
specificator_accesn;
date_i_funciin;
}[obiect1] [,obiect2] [,obiectm];

In fiierul nume_clasa.cpp:

Codul complet al metodelor

unde:

- nume_clasa este un identificator ales de programator care denumete clasa


definita i prin intermediul caruia se apeleaza aceasta;

- specificator_accesi (i=1,n) este o eticheta care poate fi unul dintre cuvinele cheie:
public, private sau protected.
Spre deosebire de o structura, ai carei membri sunt toti accesibili programului, o clasa
poate avea membri pe care programul ii poate accesa direct (public), utilizand operatorul punct (.)
i alti membri, denumiti privati (private), pe care programul nu-i poate accesa direct. Unica
accesare a datelor i metodelor private (private) se face numai prin intermediul metodelor publice.
Dup cum se va vedea, o clasa poate deriva dintr-o clasa de baza, anterior definita, concept
cunoscut sub numele de mostenire. Un membru protejat (protected) are un statut intermediar intre
membri publici i privati. Pentru clasa de baza, obiectele acesteia pot accesa membri protejati, ca i
cum ar fi publici, iar obiectele claselor derivate nu pot accesa un membru declarat protected n
clasa de baza, decat prin intermediul unor funcii de interfata declarate publice.

- date_i_funciii; (i=1,n) descrie datele, adic proprietile, i funciile, adic metodele


specifice clasei definite care, n funcie de specificator_accesi (i=1,n), pot fi public, private sau
protected.

7
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

- [obiect1] [,obiect2] [,obiectm] reprezin identificatorii obiectelor de tipul clasei la


care sunt atasati, adic numele variabilelor obiect respective care vor fi utilizate n programul n
care apar.

Observaii:

- la declararea obiectelor, o data cu definirea clasei asociate, se poate omite identificatorul


de clasa, nume_clasa.

- declararea obiectelor, ulterior definirii clasei asociate, impune obligativitatea


identificatorului de clasa, nume_clasa.

Declararea obiectelor, ulterior definirii clase se face astfel:

class nume_clasa [obiect1] [,obiect2] [,obiectm];

unde, nume_clasa,obiect1,obiect2, ,obiectm au semnificatiilie mai sus prezentate.

8
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

2. Grafuri neorientate
2.1 Noiuni introductive

Definiie Se numete graf neorientat o pereche ordonat de mulimi G=(X,U), unde X este o
mulime finit i nevid de elemente numit mulimea vrfurilor (nodurilor), iar U este o mulime
de perechi neordonate de elemente din X numit mulimea muchiilor.
Not. G=(X,U) - graf neorientat
u=[x,y]U se numete muchie a grafului G=(X,U)
Exemplu: graful din Figura 1 1
2 3
G=(X,U)
X={1, 2, 3, 4, 5} Figura 1.
U={[1,5], [2,5], [2,4], [4,5]}
5 4
x,y se numesc extremiti ale muchiei u
Obs: [x,y]=[y,x] deoarece nu conteaz orientarea muchiei
Definiie Vrfurile x i y se numesc adiacente n G dac sunt extremiti ale aceleiai muchii.
Exemplu de vrfuri adiacente: 1-5, 2-5, 2-4 i 4-5
Definiie Spunem c dou muchii sunt incidente dac au o extremitate comun.
Exemplu: Muchiile [1,5] i [2,5] sunt incidente.
Definiie Un graf parial al grafului G=(X,U) este un graf G 1=(X,V) cu proprietatea c VU (este
graful nsui sau se obine din graful iniial prin eliminarea unor muchii). Se mai spune c graful
parial G1 este indus de mulimea de muchii V.
1
Exemplu: graful din figura 2, graf partial pentru figura 1 2 3

G1=(X,U) este graf partial al lui G


X={1,2,3,4,5} Figura 2.
5 4
V={[5,1], [5,4]}

9
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

Definiie Un subgraf al unui graf neorientat G=(X,U) este un graf H=(Y,V) astfel nct YX i V
conine toate muchiile din U care au ambele extremiti n Y (poate fi graful iniial sau se obine din
acesta prin eliminarea unor vrfuri i a muchiilor incidente cu acestea). Spunem c subgraful H este
indus de mulimea de vrfuri Y. 1

Exemplu: graful din figura 3, subgraf al grafului din figura 1 Figura 3.


H=(Y,V) este subgraf al lui G
5 4
Y={1,4,5}
V={[1,5], [5,4]}
Obs. Numrul total al grafurilor neorientate cu n vrfuri date este 2n(n-1)/2.
Definiie Gradul unui vrf este numrul muchiilor incidente cu el i se noteaz d(x).
Definiie Un vrf care are gradul 0 se numete vrf izolat.
Definiie Un vrf care are gradul 1 se numete vrf terminal.
1
Exemplu: pentru graful din Figura 4: 2 3

d(5)=3
Figura 4.
d(1)=1 (vrf terminal)
5 4
d(3)=0 (vrf izolat)
Definiie Un graf se zice regulat, dac toate vrfurile sale au acelai grad.
Exemplu: graful din figura 5 2

d(1)=d(2)=d(3)=1 Figura 5.
1
3

Prop. Dac un graf G=(X,U) are n vrfuri i m muchii, iar X={x1, x2, , xn} atunci
d(xi)=2m, i=1,n. (suma gradelor vrfurilor unui graf este 2m)
Definiie Ordinul unui graf este numrul nodurilor sale.
Definiie Se numete graf complet cu n vrfuri un graf care are proprietatea c oricare dou noduri
diferite sunt adiacente.
1 2
Obs. 1. Un graf complet are n(n-1)/2 muchii.
2. d(i)=n-1 i={1,2,3,4}
Figura 6.
Exemplu: graful din figura 6 3
4
.
Definiie Fie un graf G=(X,U) cu vrfurile X={x 1, x2,, xn}. Se numete lan n graful G
succesiunea de vrfuri

10
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

L=[ x1, x2,, xk] cu proprietatea c dou vrfuri consecutive din L sunt adiacente, adic
muchiile
[ x1, x2], [x2,x3] [xik-1,xik] sunt din U.
Definiie Vrfurile x1 i xk se numesc extremitile lanului.
Definiie Numrul de muchii al unui lan reprezint lungimea lanului.

Figura 7

Exemplu:
L1=[3,2,4,5,6,3,1] (de lungime 6)
L2=[1,2,3,1,]; (de lungime 3)
L3=[7,5,6,3,1,2]; (de lungime 5)

Definiie Un lan este elementar dac toate vrfurile sale sunt distincte. Altfel este neelementar.
Definiie Un lan este simplu dac are toate muchiile distincte. n caz contrar se zice compus.
Obs. Un lan compus este neelementar.
Exemplu: pentru graful din Figura 11:
L1, L2 sunt lanuri neelementare
L3 este lan elementar, simplu;
Definiie Se numete ciclu n G un lan L pentru care x 1=xk i toate muchiile [x1, x2], [x2,x3] [xk-
1,xk] sunt diferite dou cte dou.
Definiie Se numete ciclu elementar un ciclu care are proprietatea c oricare dou vrfuri ale sale
su excepia primului i ultimului sunt diferite dou cte dou. Altfel se zice neelementar.
Exemplu: pentru graful din Figura 11:
C1=[1,2,4,5,6,3,1] este un ciclu elementar
C2=[3,7,5,6,3,1,2,4,5,6,3] este un ciclu neelementar
Definiie Lungimea unui ciclu este dat de numrul su de muchii.
Obs. Un ciclu are lungimea minim de trei muchii.
Definiie Fiecrei muchii a unui graf neorientat i se poate asocia o valoare real pozitiv care
reprezint costul acelei muchii.
Definiie Un graf neorientat n care fiecrei muchii i s-a asociat o valoare se numete graf ponderat
sau graf valoric.

11
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

Definiie Fie un graf neorientat G=(X, U) i o funcie L: UR+, care asociaz fiecrei muchii
uU un numr real numit costul (ponderea) sa L(u). Costul unui graf reprezint suma costurilor
muchiilor sale.
3
Exemplu: n figura 8 este un graf ponderat 1
2
Figura 8. 6

2.2 Modaliti de reprezentare 3 5

1 8
Pentru a desemna un graf (exemplu: figura 9) exist mai multe tipuri
4 de reprezentare:
1. Reprezentare grafica:
5
2
3
Figura 9
1 4 6
.

2. Specificarea mulimilor:
G=(V,U)
V={1,2,3,4,5,6}
U={[1,2], [2,3], [2,5], [5,6]}
3. Matricea de adiacen (si a costurilor)
Matricea de adiacen asociat acestui graf este o matrice ptratic A de dimensiune N cu
proprietatea c:
1, dac exist muchia [i, j] cu ij
a[i , j] =
0, altfel

Pentru graful de la fig 9:


1 2 3 4 5 6
1 0 1 0 0 0 0
2 1 0 1 0 0 0
3 0 1 0 0 0 0
4 0 0 0 0 1 0
5 0 0 0 1 0 1
6 0 0 0 0 1 0
Obs: 1. Pentru grafurile ponderate matricea de adiacen se numete matricea costurilor i
are urmatoarele proprieti:
x, dac exist muchia [i, j] cu ij, x cost muchiei [i, j]
a[i , j] =
, altfel

12
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

2. Matricea de adiacen i matricea costurilor este simetrica fa de diagonala


principala.
4. Matricea noduri-muchii
1, dac j incident cu i
a[i , j] =
0, altfel
1 2 3 4
1 1 0 0 0
2 1 1 0 0
3 0 1 0 0
4 0 0 1 0
5 0 0 1 1
6 0 0 0 1
5. Listele de adiacen
nod: lista nodurilor adiacen
Pentru graful din figura 9:
1: 2
2: 1, 3
3: 2
4: 5
5: 4, 6
6: 5
6. Vector de muchii (si cost)
Implementarea grafului ca vector de muchii presupune definirea unei structuri Muchie cu
dou cmpuri reprezentnd extremitile unei muchii. Graful este implementat printr-un vector G
ale crui elemente sunt de tip Muchie. Elementul de pe poziia i din vector va contine dou
informatii (G[i].v1, G[i].v2)corespunztoare extremitilor muchiei i: v1 i v2.
Pentru grafurl din figura 9:
G.v1: 1 2 4 5

G.v2: 2 3 5 6
Obs: n cazul grafurilor ponderate, structurii muchie I se mai adauga inca un camp cost
reprezentand costul muchiei (G[i].cost = costul muchiei [G[i].v1, G[i].v2])

3. Algoritmi eseniali grafuri neorientate

13
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

3.1Citirea grafurilor
Grafurile pot fi citite sub diferite mijloace n funcie modul de reprezentare. Pentru a se
putea lucra cu grafuri, de obicei acestea se memoreaza ca matrice de adiacen, matrice a costurilor
sau ca vector de muchii.

3.2Afisarea grafurilor
La fel ca i citirea, afisarea grafurilor variaza n funcie de modul de reprezentare pe care il
dorim.

3.3Parcurgerea grafurilor
Parcurgerea unui graf presupune examinarea sistematic a vrfurilor grafului, cu scopul
prelucrrii informaiilor asociate vrfurilor.
Exist dou metode fundamentale de parcurgere a grafurilor:
1. Parcurgerea n adncime (DFS Depth First Search)
2. Parcurgerea n lime (BFS Breadth First Search)
a. Parcurgerea n adncime
Parcurgerea n adncime se caracterizeaz prin faptul c se merge n adncime ori de
cte ori este posibil.
~Parcurgerea ncepe cu vrful iniial, denumit vrful de start, care este i vizitat.
~Se viziteaz apoi primul vecin nevizitat al vrfului de start. Vrful y este considerat vecin
al vrfului x dac exist muchia [x,y].
~Se viziteaz n continuare primul vecin nevizitat al primului vecin al vrfului de start, i
aa mai departe, mergnd n adncime, pn cnd ajungem ntr-un vrf care nu mai are vecini
nevizitai. Cnd ajungem ntr-un astfel de vrf, revenim la vrful su printe (vrful din care acest
nod a fost vizitat). Dac acest nod mai are vecini nevizitai, alegem primul vecin nevizitat al su i
continum parcurgerea n acelai mod. Dac nici acest vrf nu mai are vecini nevizitai, revenim n
vrful su printe i continum n acelai mod, pn cnd toate vrfurile accesibile din vrful de
start sunt vizitate.
b. Parcurgerea n lime

14
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

~Parcurgerea n lime ncepe cu vrful iniial, denumit i vrful de start. Se viziteaz mai
nti vrful de start.
~Se viziteaz n ordine toi vecinii nevizitai ai vrfului de start.
~Apoi se viziteaz n ordine toi vecinii nevizitai ai vecinilor vrfului de start i aa mai
departe, pn la epuizarea tuturor vrfurilor accesibile din vrful de start.
Observaii
1. Parcurgerea n lime are o proprietate remarcabil: fiecare vrf este vizitat pe cel mai
scurt lan/drum, ncepnd din vrful de start.
2. Complexitatea timp a algoritmilor de parcurgere n adncime i n lime a unui graf
depinde de modalitatea de reprezentare a acestuia. n cazul reprezentrii prin liste de adiacen,
complexitatea este O(n+m). n cazul reprezentrii prin matrice de adiacen este (O(n*n)).

Parcurgerea n adancime

Parcurgerea n latime

Figura 10

3.4 Lan. Lan elementar. Ciclu. Ciclu elementar.

15
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

Se verifica daca o succesine de numere (de obicei un vector) poate reprezenta nodurile
unui graf astfel incat acestea sa formeze:
- lan
- lan elementar
- ciclu
- ciclu elementar
-
3.5 Graf complementar
Definitie: Fie G=(X,U).Se numete graf complementar al grafului G graful G'=(X,U') cu
proprietatea ca dou vrfuri sunt adiacente n G' daca ele nu sunt grupuri adiacente n G.
Exemplu:
Fie un graf neorientat G = ( X,U ) cu
X = {1, 2,3,4,5}
si
U = {{1,2},{1,3},{1,4},{2,5},{4,5}} .
Cum U = 5 i numrul maxim de muchii este 10 rezult c graful
complementar are 5 muchii i astfel avem
V = CU = {{1,5},{2,3},{2,4},{3,4},{3,5}},
Obtinandu-se graful
CG = ( X,CU ) .
Grafurile din acest exemplu au urmtoarele imagini:

Figura 11

3.6 Graf bipartit

16
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

Definiie. Fie G = ( X,U ) un graf. Dac exist X1 i X2 astfel nct X1 X2 = i X = X1


X2 ( X admite o partiie din dou blocuri X1 i X2 ) i orice muchie din G uneste un nod din X1
cu unul din X2 (oricare ar fi e = {x, y}U , dac x X1 , atunci y X2 ) spunem c G este graf
bipartit.
Exemplul Graful din Figura 12:
Considerm graful neorientat G = ( X,U ) , n care mulimea
de vrfuri este X = {1,2,3, 4,5,6,7} i mulimea de muchii este
U = {{1,2},{1,6},{2,3},{2,7},{4,5},{4,6},{5,7}} .
Se observ c putem realiza partiia X = X1 X2 , X1 X2 = , cu
{ } 1 X = 1,3, 4,7 i { } 2 X = 2,5,6 , deoarece pentru orice muchie {x, y}U avem
x X1 i y X2 .

Figura 12

3.7 Graf conex. Numarul de component conexe


Definiie Un graf se zice conex dac pentru oricare dou vrfuri x i y distincte exist un lan care
le leag.
Exemplu: graful din figura 12 este conex.
Definiie Se numete component conex a grafului G=(X,U) un subgraf G=(X,U) conex cu
proprietatea c nu exist nici un lan n G care s lege un vrf din X cu un vrf din X\X.
5
Exemplu: graful alturat are dou componente conexe:
2
3
Figura13
C1=(X1,V1), X1={1,2,3}, V1={[1,2], [2,3]}
.
1 4 6

17
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

C2=(X2,V2), X2={4,5,6}, V2={[5,4], [5,6]}


Obs. Un graf cu n noduri i n componente conexe are numai vrfuri izolate. Graful format
dintr-un singur nod este conex.
Se tie c n urma parcurgerii BF (parcurgerea n lungime) a unui graf neorientat obinem o
list a vrfurilor care, de fapt, reprezint mulimea tuturor vrfurilor care sunt legate prin lanuri de
un vrf dat. Dac n urma parcurgerii BF rmn vrfuri nevizitate, graful nu este conex. n acest
caz, putem afia componentele conexe ale grafului. Analog putem proceda utiliznd metoda de
parcurgere DF (parcurgerea inlatime) pentru un graf neorientat. n ambele cazuri, pentru fiecare
vrf rmas nevizitat se apeleaz metoda de parcurgere, vrful respectiv fiind primul dintr-o nou
component conex. Astfel se poate determin daca un graf este conex i se pot afla componentele
conexe.

3.8 Graf hamiltonian.


Definiie Se numete lan hamiltonian un lan elementar care conine toate vrfurile grafului.
Definiie ntr-un graf neorientat G=(X,U) se numete ciclu hamiltonian un ciclu elementar care
conine toate vrfurile grafului.
Definiie Se numete graf hamiltonian un graf care conine un ciclu hamiltonian.
Exemplu: graful alturat este hamiltonian:
2 3 Figura 14
C1=[1,2,5,4,3,6,1] 1
1
4
C2=[1,2,3,4,5,6,1] 1
6 5
sunt cicluri hamiltoniene 1 1

Teorem. Graful complet este hamiltonian.


Teorem. (condiie suficient ca un graf s fie hamiltonian) Dac G=(X,U) este un graf cu
n3 vrfuri astfel nct gradul fiecrui vrf satisface condiia: d(x)n/2 atunci este hamiltonian.

3.9 Graf eulerian


Definiie Se numete lan eulerian un lan elementar care conine toate muchiile grafului.
Definiie ntr-un graf G=(X,U) se numete ciclu eulerian un ciclu care conine toate muchiile
grafului.
Definiie Se numete graf eulerian un graf care conine un ciclu eulerian.
3
Exemplu: graful alturat este eulerian: 2
1
8

7
1
1 4
18 1
6 5 9 Figura 15
1 1
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

C1=[1,2,7,5,4,8,9,4,3,7,6,1]
C2=[7,2,1,6,7,3,4,9,8,4,5,7]
sunt cicluri euleriene
Teorem. Un graf G=(X,U) fra vrfuri izolate este eulerian dac i numai dac este conex
i gradele tuturor vrfurilor sunt numere pare.

3.10 Algoritmul Bellman-Ford


Algoritmul Bellman-Ford este folosit n grafurile ponderate pentru a obtine lanurile de
cost minim de la x la cecacalcte noduri.
Modul de funcionare
Se consider c exist soluie doar n cazul n care din vrful de start nu se ajunge la un
circuit de cost negatv, deoarece acesta ar duce la minimizarea drumului la infinit.
Algoritmul ncearc s minimizeze succesiv costul drumului de la vrful ales la orice
vrf din graf pn la obinerea costului minim.
Operaia de minimizare a distanelor se repet de n ori.
n final muchille ce aparin drumurilor de cost minim vor fi colorate diferit
Exemplu:

Figura 16

Pentru graful prezentat se va calcula drumurile de cost minim din nodul 1:

Se construiete un vector viz de dimensiune egala cu numarul nodurilor :

19
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

viz:
1 2 3 4 5 6
n acest caz nodul 1 cum este nod de plecare se marcheaz n viz cu valoarea 0.
viz: 0
1 2 3 4 5 6
Pasul urmtor const n iniializarea restului valorilor din viz cu valori foarte mari.
viz: 0
1 2 3 4 5 6
Se construiete o coad cu numele c.
Pentru c s-a ales nodul 1 ca nod de plecare se noteaz n coad.
c: 1
Se alege nodul adiacent , n acest caz 5.
Se marchez n viz pe poziia 5 cu 1 pentru a evidenia costul.
viz: 0 1
1 2 3 4 5 6
Urmtorul nod adiacent al lui 1 care este 3; astfel se marchez n viz pe poziia 3 cu 4 i se
adaug n coad nodul 3.
c:1,5,3
viz: 0 4 1
1 2 3 4 5 6
Se ia n continuare urmtorul nod adiacent al lui 1, care este 2 i se marcheaz n viz pe
poziia 2 cu 5, iar n coad se aduag 2.
c:1,5,3,2
viz: 0 5 4 1
1 2 3 4 5 6
Urmtorul nod adiacent al lui 1 este 6 i astfel se marcheaz n viz pe poziia 6 cu 6, iar n
coad se adaug nodul 6.
c:1,5,3,2,6
viz: 0 5 4 1 6
1 2 3 4 5 6
Pentru c nodul 1 nu mai are adiaceni se trece la nodul urmtor, 5 i se marcheaz n coad
cu rou pentru a evidenia.
c:1,5,3,2,6
Se ia primul adiacent al lui 5,1.

20
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

Pentru c n vectorul viz costul pn la nodul 5 este 1,iar costul de la 5 la nodul 1 este 1,n
vector nu se va face nici o modificare deoarece valoarea costului obinut prin nsumarea
lor nu este o valoare mai mic decat n viz.
Urmtorul nod adiacent al lui 5 este 4.
Costul pn la nodul 5 este 1,iar de la 5 la 4 este 2.n vectoul viz se trece pe poziia 4 3
doarece acesta este costul obinut prin nsumare. Astfel se adaug i n coad nodul 4.
c:1,5,3,2,6,4
viz:0 5 4 3 1 6
1 2 3 4 5 6
Urmtorul nod adiacent al lui 5. ns nu sunt modificri n viz deoarece costul lui 5 pn la 1
este 1 i de la 5 la 6 este 9 i astfel, prin nsumare costul de la 5 la 6 devine 10 i este mai
mare decat era iniial.
Nodul urmtor din coad, 3.Se evideniaz cu rou n coad.
c:5,3,2,6,4
Primul adiacent al lui 3.Acesta fiind 1, nu exist modificri.
Urmtorul adiacent al lui 3 este 2. ns nici de data aceasta nu sunt modificri deoarece prin
nsumare(4+7=11) noul cost ar fi mai mare decat cel iniial,5.
Urmtor adiacent al lui 3 este 4. Noul cost ar deveni 7 prin nsumare(4+3=7) i astfel nu
sunt modificri.
Pentru c nu mai sunt adiaceni ai lui 3 se trece la nodul urmtor,2 i se n eviden cu rou
n coad.
c:1,5,3,2,6,4
Primul adiacent al lui 1.Nu sunt modificri n acest caz.
Urmtorul adiacent al lui 2 este 3. Prin nsumare noul cost al lui 3 ar deveni 12 i astfel nu
sunt modificri.
Urmtorul adiacent al lui 2 fiind 4 se afl ct ar deveni noul cost al lui 4. Prin nsumare ar
deveni i deci nu sunt modificri.
Urmtorul adiacent al lui 2 6, cu noul cost 9, care este mai mare dect 6 i deci nici de data
aceasta nu sunt modificri.
Se trece la urmtorul nod din coad pentru c nu mai sunt adiaceni ai lui 2.
c:1,5,3,2,6,4
Modificri nu sunt pentru acest nod.

21
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

Se trece la urmtorul din coad,4.


c:1,5,3,2,6,4
Nu este nicio modificare.
Vectorul la fel ca i coada se va ncheia cu ultimul nod din vector deoarece s-a realizat
ntreaga parcurgere a cozii.
c:1,5,3,2,6,4

3.11Algoritmul lui Kruskal


Algoritmul lui este un algoritm n teoria grafurilor care gsete arborele parial de cost
minim pentru un graf conex ponderat. Cu alte cuvinte, gsete submulimea muchiilor care
formeaz un arbore care include toate vrfurile i care este minimizat din punct de vedere al
costului. Dac graful nu este conex, atunci algoritmul gsete un arbore parial de cost minim pentru
fiecare component conex. Algoritmul lui Kruskal este un exemplu de algoritm greedy. Este
preferabil sa reprezentam graful ca o lista de muchii cu costul asociat lor, astfel incat sa putem
ordona aceasta lista n funcie de cost.
Mecanismul algoritmului
date de intrare: un graf neorientat conex
date de iesire:un arbore de cost minim
pentru a forma arborele trebuie alese n-1 muchii(n fiind numarul de noduri al grafului)
creeaz o mulime de arbori, unde fiecare vrf din graf este un arbore separat
creeaz o mulime U care conine toate muchiile din graf
att timp ct U este nevid i nu s-au ales cele n-1 muchii:
elimin o muchie de cost minim din U cu extremitatile nemarcate sau marcate diferit
dac acea muchie unifica doi arbori distinci, atunci adaug muchia, unificand cei doi
arbori ntr-unul singur
la sfarsit, vom avea o singura componenta conexa, care este arborele partial de cost minim al
grafului.
Algoritmul lui Kruskal. Exemplu

22
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

Figura 17

Iniial:
viz:
Costul=0
Se alege muchia [2,4]
viz:
Costul=0+1costul=1;
Se alege muchia [5,6]
viz:
Costul=1+1costul=2
Se alege muchia [7,8]
viz:
Costul=2+1costul=3
Se alege muchia [2,6]
viz:
Costul=3+2costul=5

23
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

Se alege muchia [3,8]


viz:
Costul=5+2costul=7
Se alege muchia [4,8]
viz:
Costul=7+2costul=9
Se alege muchia [1,2]
viz:
Costul=9+3costul=12

3.12 Algoritmul lui Prim


Algoritmul lui Prim este un algoritm din teoria grafurilor care gsete arborele parial de
cost minim al unui graf conex ponderat. nseamn c gsete submulimea muchiilor care formeaz
un arbore care include toate vrfurile i al crui cost este minimizat.
Modul de funcionare:

4
2 3 Figura 18
5 6

1 3
4
1
8
4
6 2 5

s:
1 2 3 4 5 6
viz:
1 2 3 4 5 6
t:
1 2 3 4 5 6
Pasul 1:
Se alege un nod x de start: 2
Se marcheaz vrful ca fiind vizitat (viz[2]=1)
Se completeaza valoarea n vectorul de tati
Se iniializeaz vectorul s astfel:

24
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

s[x]=0;
s[i]=x; ,i x
Dup executarea pasului 1:
s: 2 0 2 2 2 2
1 2 3 4 5 6
viz: 1
1 2 3 4 5 6
t: 0
1 2 3 4 5 6

Pasul 2:
Se allege cea mai mica muchie cu un capat selectat.
Se marcheaz capatul neselectat
Se actualizeaza vectorii viz, t i s.
Se reia pasul 2 de (n-2) ori.
Dup prima executie a pasului 2:
s: 2 0 2 5 2 5
1 2 3 4 5 6
viz: 1 1
1 2 3 4 5 6
t: 0 2
1 2 3 4 5 6
Dup a dou executie a pasului 2:
s: 2 0 6 5 2 5
1 2 3 4 5 6
viz: 1 1 1
1 2 3 4 5 6
t: 0 2 5
1 2 3 4 5 6
Dup a treia executie a pasului 2:
s: 2 0 6 5 2 5
1 2 3 4 5 6
viz: 1 1 1 1
1 2 3 4 5 6
t: 0 6 2 5
1 2 3 4 5 6
Dup a patra executie a pasului 2:
s: 2 0 6 5 2 5
1 2 3 4 5 6

25
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

viz: 1 1 1 1 1
1 2 3 4 5 6
t: 0 6 5 2 5
1 2 3 4 5 6
Dup a cincea executie a pasului 2:
s: 2 0 6 5 2 5
1 2 3 4 5 6
viz: 1 1 1 1 1 1
1 2 3 4 5 6
t: 2 0 6 5 2 5
1 2 3 4 5 6

3.13 Grafuri izomorfe


Definitie. Fie G = ( X,U ) i G = ( X,U) dou grafuri neorientate.
Spunem c G i G sunt izomorfe, notm G G , dac exist o funcie bijectiv
f : X X astfel nct {x, y}U dac i numai dac { f ( x), f ( y)}U .
Din definitie rezult c dou grafuri sunt izomorfe dac au acelasi numr de vrfuri i se
poate obtine unul din cellalt printr-o renumerotare a vrfurilor.
Exemplu: G izomorf cu H

Figura 19

3.14 Supraincarcarea operatorilor

26
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

Funciile operator constituie un tip special de funcii, care se pot utiliza pentru redefinirea
operatorilor de baza care apar n C++. O clasa se poate defini mpreuna cu un set de operatori
asociati, obtinuti prin suprancarcarea operatorilor existenti. n acest fel, se efectueaza operatii
specifice noului tip, la fel de simplu ca n cazul tipurilor standard.
Supradefinirea se realizeaza astfel:
tip_val_intoarsa operator op (lista_declar_parametri)
{
// . . . . corpul funciei
}
Supraincarcarea operatorului ,,+:
1. Graf +nr ( numar) adauga graficului nr noduri izolate
2. Graf + muchie adauga graficului muchia adunata, daca aceasta nu exist
Supraincarcarea operatorului ,,-:
1. Graf - nr scade graficului nodul nr, daca acesta exist. Totodata nodurile mai mari ca nr scad
cu o unitate pentru ca nodurile graficului sa fie consecutive
2. Graf - muchie scade graficului muchia adunata, daca aceasta exist

4. Clasa graf

Legenda:
n-numarul de noduri/vrfuri ale unui graf
m-numarul de muchii
ma-matricea de adiacen
mc-matricea costurilor
vm-vectorul de muchii (si cost)
viz-vectorul vizitat (margheaza muchiile care au fost deja utilizate n algoritm)

Observaii:
1. Pentru grafurile neponderate costul fiecarei muchii se considera 1

27
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

2. Odata cu citirea matricei de adiacen, vom creea n memorie i matricea costurilor i


vectorul de muchii - costuri. La fel vom proceda i daca vom citi un graf printr-un alt mijloc.
3. Funciile de verificare returneaza 1 pentru cazul afirmativ i 0 pentru cel negativ

4.1 n fiierul graf.h

#define inf 9999


typedef struct{int x; int y; int cost;}muchii;
class graf{
int n, ma[50][50], m, mc[50][50], viz[51];
muchii vm[1225];
public:
graf(); //iniializeaz un graf cu 0 noduri i 0 muchii
graf(unsigned); // iniializeaz un graf cu n noduri i 0 muchii
void citire_f_n_ma(char*); //citete din fiier n, ma i creeaz mc i vm (costul muchiilor fiind 1)
void citire_f_n_m_muchii(char*); //citete din fiier n,m i vm i creeaz ma i mc (costul muchiilor fiind 1)
void citire_f_n_mc(char*); //citete din fiier n, mc i creeaz ma i vm
void citire_f_n_m_muchii_cost(char*); //citete din fiier n, m, vm i creeaz mc i ma
void citire_t_n_ma(); //citete de la tastatur n, ma i creeaz mc i vm
void citire_t_n_m_muchii(); //citete de la tastatur n,m i vm i creeaz ma i mc (costul muchiilor fiind 1)
void citire_t_n_mc(); //citete de la tastatur n, mc i creeaz ma i vm
void citire_t_n_m_muchii_cost(); //citete de la tastatur n, m, vm i creeaz mc i ma
void afisare_viz(); //afieaz vectorul viz
void afisare_ma(); // afieaz ma
void afisare_mc(); // afieaz mc (pentru cost=infinit se afieaz 0)
void afisare_vm(); // afieaz vm
void afisare(); // afieaz ma, mc i vm
void afisare_muchii(); //afieaz perechile de muchii i costuri
void set_viz(int); //umple vectorul viz cu valoarea primit ca parametru
void set_m(); //din ma determin valoarea lui m
void set_m(int); //fixeaz valoarea lui m ca fiind valorea primit ca parametru
void set_vm(); //genereaz vm din mc

28
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

void set_mc(); //genereaz mc din ma


void set_ma(); //genereaz ma din mc
void set_i_j_ma(int, int, int); //pentru x=1, adauga n graf muchia [i,j]
pentru x=0, sterge din graf muchia [i,j]
void set_i_j_mc(int, int, int); //adauga n graf muchia [i,j] de cost x (daca muchia exist deja costul ei
devine x)
void set_i_vm(muchii);// adauga n graf muchia primit ca parametru
void set_n(int); //fixeaz valoarea lui n ca fiind valoarea primit ca parametru
int get_n(); //returneaza valoarea lui n
int get_m(); // returneaza valoarea lui m
int get_i_j_ma(int, int); // returneaza valoarea pozitiei ma[i][j]
int get_i_j_mc(int, int); // returneaza valoarea pozitiei mc[i][j]
muchii get_i_vm(int); //returneaza muchia de pe pozitia i din vm
void get_muchie_i(int,int&,int&,int&); // muchia de pe pozitia nr se inlocueste cu muchia a carei capete (i,
j) i cost (c) sunt primite ca parametri
void ordonare_vm(); //ordoneaza vm crescator dup cost
int adiacen(int, int); //verifica daca exist muchie intre dou numere primite prin parametrii x i y
void lista_adiacanta(int); //afieaz adiacenii nodului primit ca parametru
int grad(int); //returneaza gradul nodului primit ca parametru
int lant(int*, int); //verifica daca un vectorul primit ca parametru este lan
int lant_elementar(int*, int); // verifica daca un vectorul primit ca parametru este lan elementar
int ciclu(int*, int); // verifica daca un vectorul primit ca parametru este ciclu
int ciclu_elementar(int*, int); // verifica daca un vectorul primit ca parametru este ciclu elementar
int complementar(graf); //verifica daca graful primit ca parametru este complementar cu graful iniial
int conex(); //verifica conexitatea grafului
int eulerian(); //verifica daca graful este eulerian
int hamiltonian(); //verifica daca graful este hamiltonian
void componente_conexe(); //afieaz numarul de componente conexe i le afieaz
void bf(int,int); //adiacenii lui x (directi sau indirecti) sunt marcati n viz cu valoarea k (parcurgerea n
lungime)
void df_auxiliar(int); //funtie ajutatoare (pentru void df(int) )
void df(int); //pargurge graful n adancime
void prim(int); //afieaz costul arborelui de cost minim i vectorul de tati (Algoritmul lui Prim)
void kruskal(); //afieaz muchiile alese de Algoritmul Kruskal i costul minim
void bellman_ford(int); //realizeaza algoritmul Bellman Ford i afieaz vectorul de costuri minime de la
nodul start la celalate noduri precum i vectorul de precedenta
int graf_partial(graf); //verifica daca graful primit ca parametru este un graf partial al grafului iniial
int izomorf(graf); //verifica daca graful primit ca parametru este izomorf cu graful iniial
int complet(); //verifica daca graful este complet
int bipartit(); //verifica daca un graf este bipartit
friend graf operator+(graf, int); //adauga graficului nr noduri izolate (nr fiind valoarea adunata la grafic)
friend graf operator+(graf, muchii); //adauga graficului muchia adunata graficului, daca aceasta nu exist
friend graf operator-(graf, int); //elimina din graf nodul nr iar toate nodurile de dup nr scad cu o valoare
friend graf operator-(graf, muchii); // scade graficului o muchie, daca aceasta exist
};

4.2 n fiierul graf.cpp

#include<iostream.h>

29
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

#include<fstream.h>
#include"graf.h"
#define inf 9999
int i, c[50], p=1, ca[50], cb[50], t[50], s[50], v[50], wr;
graf::graf()
{
n=0;
m=0;
}
graf::graf(unsigned x)
{
int i, j;
n=x;
m=0;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
ma[i][j]=0;
mc[i][j]=inf;
}
}
void graf::afisare_ma()
{
int i, j;
cout<<"\n Matricea de adiacenta:\n";
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
cout<<ma[i][j]<<" ";
cout<<'\n';
}
}
void graf::afisare_viz()
{
for(i=1;i<=n;i++)
cout<<viz[i]<<" ";
}
void graf::afisare_mc()
{
int i, j;
cout<<"\n Matricea costurilor:\n";
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
if(mc[i][j]==inf)
cout<<"0 ";
else
cout<<mc[i][j]<<" ";
cout<<'\n';
}
}

30
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

void graf::afisare()
{
int i, j;
cout<<"\n Numarul de noduri: "<<n<<"\n Numarul de muchii: "<<m;
cout<<"\n Matricea de adiacenta:\n";
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
cout<<ma[i][j]<<" ";
cout<<'\n';
}
cout<<"\n Matricea costurilor:\n";
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
if(mc[i][j]==inf)
cout<<"0 ";
else
cout<<mc[i][j]<<" ";
cout<<'\n';
}
cout<<"\n Vectorul de muchii si costuri:\n";
cout<<"x: ";
for(i=1;i<=m;i++)
cout<<vm[i].x<<" ";
cout<<"\ny: ";
for(i=1;i<=m;i++)
cout<<vm[i].y<<" ";
cout<<"\ncost: ";
for(i=1;i<=m;i++)
cout<<vm[i].cost<<" ";
cout<<'\n';
}
void graf::afisare_muchii()
{
int i, j;
cout<<"\n Muchii si costuri: \n";
for(i=1;i<=m;i++)
cout<<"("<<vm[i].x<<","<<vm[i].y<<") "<<"de cost "<<vm[i].cost<<'\n';
}
void graf::afisare_vm()
{
int i, j;
cout<<"\n Vectorul de muchii si costuri:\n";
cout<<"x: ";
for(i=1;i<=m;i++)
cout<<vm[i].x<<" ";
cout<<"\ny: ";
for(i=1;i<=m;i++)
cout<<vm[i].y<<" ";
cout<<"\ncost: ";

31
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

for(i=1;i<=m;i++)
cout<<vm[i].cost<<" ";
}
void graf::citire_f_n_ma(char *c)
{
int i, j;
m=0;
ifstream f(c);
f>>n;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
f>>ma[i][j];
ma[j][i]=ma[i][j];
if(ma[i][j]==0)
{
mc[i][j]=inf;
mc[j][i]=inf;
}
else
{
mc[i][j]=1;
mc[j][i]=1;
if(i<j)
{
m++;
vm[m].x=i;
vm[m].y=j;
vm[m].cost=1;
}
}
}
}
void graf::citire_f_n_m_muchii(char *c)
{
int i, j;
int x, y;
ifstream f(c);
f>>n>>m;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
ma[i][j]=0;
ma[j][i]=0;
mc[i][j]=inf;
mc[j][i]=inf;
}
for(i=1;i<=m;i++)
{
f>>x>>y;
ma[x][y]=1;

32
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

ma[y][x]=1;
mc[x][y]=1;
mc[y][x]=1;
vm[i].x=x;
vm[i].y=y;
vm[i].cost=1;
}
}
void graf::citire_f_n_mc(char *c)
{
int i, j;
ifstream f(c);
f>>n;
m=0;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
f>>mc[i][j];
if(mc[i][j]==0)
{
ma[i][j]=0;
ma[j][i]=0;
mc[i][j]=inf;
mc[j][i]=inf;
}
else
{
mc[j][i]=mc[i][j];
ma[i][j]=1;
ma[j][i]=1;
if(i<j)
{
m++;
vm[m].x=i;
vm[m].y=j;
vm[m].cost=mc[i][j];
}
}
}
}
void graf::citire_f_n_m_muchii_cost(char *c)
{
int i, j;
ifstream f(c);
f>>n>>m;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
ma[i][j]=0;
ma[j][i]=0;
mc[i][j]=inf;

33
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

mc[j][i]=inf;
}
for(i=1;i<=m;i++)
{
f>>vm[i].x>>vm[i].y>>vm[i].cost;
ma[vm[i].x][vm[i].y]=1;
ma[vm[i].y][vm[i].x]=1;
mc[vm[i].x][vm[i].y]=vm[i].cost;
mc[vm[i].y][vm[i].x]=vm[i].cost;
}
}
void graf::citire_t_n_ma()
{
int i, j;
m=0;
cout<<"\n Numarul de noduri: ";
cin>>n;
cout<<"\n Introduceti matricea de adiacenta.\n";
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
cin>>ma[i][j];
if(ma[i][j]==0)
mc[i][j]=inf;
else
{
mc[i][j]=1;
if(i<j)
{
m++;
vm[m].x=i;
vm[m].y=j;
vm[m].cost=1;
}
}
}
}
void graf::citire_t_n_m_muchii()
{
int i, j;
int x, y;
cout<<"\ Nnumarul de noduri: ";
cin>>n;
cout<<"\ Nnumarul de muchii: ";
cin>>m;
for(i=1;i<=n;i++)
for(j=i;j<=n;j++)
{
ma[i][j]=0;
ma[j][i]=0;
mc[i][j]=inf;

34
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

mc[j][i]=inf;
}
cout<<" Tastati "<<m<<" perechi de cate doua numere reprezentand capetele muchiilor: \n";
for(i=1;i<=m;i++)
{
cin>>x>>y;
ma[x][y]=1;
ma[y][x]=1;
mc[x][y]=1;
mc[y][x]=1;
vm[i].x=x;
vm[i].y=y;
vm[i].cost=1;
}
}
void graf::citire_t_n_mc()
{
int i, j;
cout<<"\n Numarul de noduri: ";
cin>>n;
m=0;
cout<<"\n Tastati matricea costurilor.\n";
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
cin>>mc[i][j];
if(mc[i][j]==0)
{
ma[i][j]=0;
mc[i][j]=inf;
}
else
{
ma[i][j]=1;
if(i<j)
{
m++;
vm[m].x=i;
vm[m].y=j;
vm[m].cost=mc[i][j];
}
}
}
}
void graf::citire_t_n_m_muchii_cost()
{
int i, j;
cout<<"\n Numarul de noduri: ";
cin>>n;
cout<<"\n Numarul de muchii: ";
cin>>m;

35
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

for(i=1;i<=n;i++)
for(j=i;j<=n;j++)
{
ma[i][j]=0;
ma[j][i]=0;
mc[i][j]=inf;
mc[j][i]=inf;
}
cout<<"\n Tastati "<<m<<" triplete de numere reprezentand capetele muchiilor si respectiv costul
lor. \n";
for(i=1;i<=m;i++)
{
cin>>vm[i].x>>vm[i].y>>vm[i].cost;
ma[vm[i].x][vm[i].y]=1;
ma[vm[i].y][vm[i].x]=1;
mc[vm[i].x][vm[i].y]=vm[i].cost;
mc[vm[i].y][vm[i].x]=vm[i].cost;
}
}
int graf::adiacenta(int x, int y)
{
return ma[x][y];
}
void graf::lista_adiacanta(int x)
{
int i, j;
if(x>n)
cout<<"\n Nu exista nodul "<<x<<" deci nu are adiacenti";
else
{
cout<<"\n Lista adiacentilor nodului "<<x<<": ";
for(i=1;i<=n;i++)
if(ma[x][i]==1)
cout<<i<<" ";
}
cout<<'\n';
}
int graf::grad(int x)
{
int i, j;
int gr=0;
for(i=1;i<=n;i++)
gr+=ma[x][i];
return gr;
}
void graf::set_m()
{
int i, j;
m=0;
for(i=1;i<n;i++)
for(j=i+1;j<=n;j++)

36
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

m+=ma[i][j];
}
void graf::set_viz(int nr)
{
int i;
for(i=1;i<=n;i++)
viz[i]=nr;
}
void graf::set_m(int x)
{
m=x;
}
void graf::set_vm()
{
int i, j;
m=0;
for(i=1;i<n;i++)
for(j=i+1;j<=n;j++)
if(mc[i][j]!=inf)
{
m++;
vm[m].x=i;
vm[m].y=j;
vm[m].cost=mc[i][j];
}
}
void graf::set_n(int x)
{
n=x;
}
void graf::set_mc()
{
int i, j;
cout<<"\n";
for(i=1;i<=n;i++)
for(j=i;j<=n;j++)
if(ma[i][j]==0)
{
mc[i][j]=inf;
mc[j][i]=inf;
}
else
{
mc[i][j]=1;
mc[j][i]=1;
}
}
void graf::set_ma()
{
int i, j;
for(i=1;i<=n;i++)

37
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

for(j=i;j<=n;j++)
if(mc[i][j]==inf)
{
ma[i][j]=0;
ma[j][i]=0;
}
else
{
ma[i][j]=1;
ma[j][i]=1;
}
}
void graf::set_i_j_ma(int i, int j, int x)
{
ma[i][j]=x;
ma[j][i]=x;
if(x==0)
{
mc[j][i]=inf;
mc[i][j]=inf;
}
else
{
mc[j][i]=1;
mc[i][j]=1;
m++;
vm[m].x=i;
vm[m].y=j;
vm[m].cost=1;
}
}
void graf::set_i_j_mc(int i, int j, int x)
{
if(x==0)
{
ma[i][j]=0;
ma[j][i]=0;
mc[j][i]=inf;
mc[i][j]=inf;
}
else
{
m++;
mc[i][j]=x;
mc[j][i]=x;
ma[j][i]=1;
ma[i][j]=1;
vm[m].x=i;
vm[m].y=j;
vm[m].cost=x;
}

38
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

}
void graf::set_i_vm(muchii aux)
{
m++;
vm[m]=aux;
ma[aux.x][aux.y]=1;
ma[aux.y][aux.x]=1;
mc[aux.x][aux.y]=aux.cost;
mc[aux.y][aux.x]=aux.cost;
}
int graf::get_n()
{
return n;
}
int graf::get_m()
{
return m;
}
muchii graf::get_i_vm(int i)
{
return vm[i];
}
int graf::get_i_j_ma(int i, int j)
{
return ma[i][j];
}
int graf::get_i_j_mc(int i, int j)
{
return mc[i][j];
}
void graf::get_muchie_i(int nr,int& i,int& j,int& c)
{
i=vm[nr].x;
j=vm[nr].y;
c=vm[nr].cost;
}
void graf::ordonare_vm()
{
int i, j;
int p=1;
muchii aux;
while(p<m)
{
if(vm[p].cost>vm[p+1].cost)
{
aux=vm[p];
vm[p]=vm[p+1];
vm[p+1]=aux;
p--;
}
else

39
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

p++;
if(p==0)
p++;
}
}
int graf::lant(int v[], int x)
{
int i, j;
for(i=1;i<x;i++)
if(ma[v[i]][v[i+1]]==0)
return 0;
return 1;
}
int graf::lant_elementar(int v[], int x)
{
int i, j;
if(this->lant(v,x)==0)
return 0;
for(i=1;i<x;i++)
for(j=i+1;j<=x;j++)
if(v[i]==v[j])
return 0;
return 1;
}
int graf::ciclu(int v[], int x)
{
int i, j;
if(v[1]!=v[x])
return 0;
if(this->lant(v,x)==0)
return 0;
for(i=1;i<x-1;i++)
for(j=i+1;j<x;j++)
if((v[i]==v[j]&&v[i+1]==v[j+1])||(v[i+1]==v[j]&&v[i]==v[j+1]))
return 0;
return 1;
}
int graf::ciclu_elementar(int v[], int x)
{
int i, j;
if(v[1]!=v[x]||ma[v[x-1]][v[x]]==0||x>n+1)
return 0;
return this->lant_elementar(v,x-1);
}
int graf::complementar(graf g)
{
int i, j;
if(n!=g.get_n())
return 2;
for(i=1;i<n;i++)
for(j=i+1;j<=n;j++)

40
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

if(ma[i][j]+g.get_i_j_ma(i,j)!=1)
return 0;
return 1;
}
void graf::bf(int x, int k)
{
int i, j, p=1, u=1, c[50];
//this->set_viz(0);
c[1]=x;
viz[x]=k;
while(p<=u)
{
x=c[p++];
for(i=1;i<=n;i++)
if(ma[x][i]==1&&viz[i]==0)
{
c[++u]=i;
viz[i]=k;
}
}
}
int graf::conex()
{
int i, j, c[50], p=1, u=1, x=1;
this->set_viz(0);
c[1]=x;
viz[x]=1;
while(p<=u)
{
x=c[p++];
for(i=1;i<=n;i++)
if(ma[x][i]==1&&viz[i]==0)
{
c[++u]=i;
viz[i]=1;
}
}
if(u==n)
return 1;
return 0;
}
int graf::eulerian()
{
int nr, ok=0;
if(this->conex()==0)
cout<<"\n Graful nu este eulerian pentru ca nu este conex.";
for(i=1;i<=n;i++)
{
nr=this->grad(i);
if(nr%2!=0)
{

41
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

if(ok==0)
cout<<"\n Graful nu este eulerian. Nodurile care nu au gradul par sunt:
";
cout<<i<<" ";
ok=1;
}
}
if(ok==0)
cout<<"\n Graful este eulerian.";

return 1;
}
int graf::hamiltonian()
{
int i;
if(this->conex()==0)
return 0;
else
for(i=1;i<=n;i++)
if(this->grad(i)<n/2)
return 0;
return 1;
}
void graf::componente_conexe()
{
int k, i, j;
k=0;
this->set_viz(0);
for(i=1;i<=n;i++)
if(viz[i]==0)
{
k++;
this->bf(i,k);
}
if(k==1)
{
cout<<'\n'<<" O singura componenta conexa: ";
for(i=1;i<=n;i++)
cout<<i<<" ";
}
else
{
cout<<"\n "<<k<<" componente conexe.\n";
for(i=1;i<=k;i++)
{
cout<<" Componenta "<<i<<": ";
for(j=1;j<=n;j++)
if(viz[j]==i)
cout<<j<<" ";
cout<<'\n';
}

42
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

}
}
void graf::df_auxiliar(int x)
{
int wr;
cout<<x<<" ";
v[x]=1;
for(wr=1;wr<=n;wr++)
if(ma[x][wr]==1&&v[wr]==0)
this->df_auxiliar(wr);
}
void graf::df(int x)
{
int i, j;
this->set_viz(0);
this->df_auxiliar(x);
}
void graf::prim(int x)
{
int i, j, p, min,k, c=0;
this->set_viz(0);
viz[x]=1;
t[x]=0;
for(i=1;i<=n;i++)
s[i]=x;
s[x]=0;
for(k=1;k<=n-1;k++)
{
min=inf;
for(i=1;i<=n;i++)
if(viz[i]==0&&mc[i][s[i]]<min)
{
min=mc[i][s[i]];
p=i;
}
t[p]=s[p];
viz[p]=1;
c=c+mc[p][s[p]];
for(i=1;i<=n;i++)
if(!viz[i]&&mc[i][s[i]]>mc[i][p])
s[i]=p;
}
cout<<"\n Costul arborelui de cost minim "<<c<<'\n';
cout<<" Vectorul de tati: ";
for(i=1;i<=n;i++)
cout<<t[i]<<" ";
cout<<'\n';
}
void graf::kruskal()
{
int i=1, j, k, c=0;

43
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

this->set_viz(0);
this->ordonare_vm();
cout<<"\n Kruskal: \n";
cout<<" Muchii alese: \n";
for(k=1;k<=n-1;k++)
{
while(viz[vm[i].x]==viz[vm[i].y]&&viz[vm[i].x]!=0)
i++;
c+=vm[i].cost;
cout<<"("<<vm[i].x<<","<<vm[i].y<<")"<<"de cost "<<vm[i].cost<<'\n';
if(viz[vm[i].x]+viz[vm[i].y]==0)
viz[vm[i].x]=viz[vm[i].y]=vm[i].x;
else
if(viz[vm[i].x]*viz[vm[i].y]==0)
viz[vm[i].x]=viz[vm[i].y]=viz[vm[i].x]+viz[vm[i].y];
else
{
for(j=1;j<=n;j++)
if(viz[j]==viz[vm[i].x]&&j!=vm[i].x)
viz[j]=viz[vm[i].y];
viz[vm[i].x]=viz[vm[i].y];
}
i++;
}
cout<<" Costul arborelui Kruskal: "<<c;
}
void graf::bellman_ford(int x)
{
int pr=1, u=1, i, j, p[51];
this->set_viz(inf);
viz[x]=0;
c[1]=x;
while(pr<=u)
{
x=c[pr];
pr++;
for(i=1;i<=n;i++)
if(mc[x][i]!=0)
if(viz[x]+mc[x][i]<viz[i])
{
viz[i]=viz[x]+mc[x][i];
p[i]=x;
u++;
c[u]=i;
}
}
p[c[1]]=0;
cout<<"\n viz: ";//vizul in acest caz are salvate pe pozitia i, costul minim de a ajunge de la x la
nodul i
for(i=1;i<=n;i++)
cout<<viz[i]<<" ";

44
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

cout<<"\n\n p: ";
for(i=1;i<=n;i++)
cout<<p[i]<<" ";
}
int graf::graf_partial(graf G1)
{
int i, j;
if(n!=G1.get_n())
return 0;
for(i=1;i<n;i++)
for(j=i+1;j<=n;j++)
if(ma[i][j]==0&&G1.get_i_j_ma(i,j)==1)
return 0;
return 1;
}

int a[10],b[10], suma=0;


int verificare(graf G2, int f[], graf G1)
{
int i, j;
if(G1.get_n()!=G2.get_n()||G2.get_n()!=G1.get_n())
return 0;
for(i=1;i<=G2.get_n()-1;i++)
for(j=i+1;j<=G2.get_n();j++)
if(G1.get_i_j_ma(i,j)!=G2.get_i_j_ma(f[i],f[j]))
return 0;
return 1;
}
void back(int k, graf G2, graf G1)
{
if(k-1==G2.get_n())
suma=suma+verificare(G2,a,G1);
else
{
for(int i=1;i<=G2.get_n();i++)
if(!b[i])
{
a[k]=i;
b[i]=1;
back(k+1,G2,G1);
b[i]=0;
}
}
}
int graf::izomorf(graf G2)
{
int i, j;
graf G1(n);
G1.set_m(m);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)

45
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

G1.set_i_j_ma(i, j, ma[i][j]);
back(1, G2,G1);
if(suma==0)
return 0;
return 1;
}
int graf::complet()
{
int i, j;
for(i=1;i<n;i++)
for(j=i+1;j<=n;j++)
if(ma[i][j]==0)
return 0;
return 1;
}
int graf::bipartit()
{
this->set_viz(0);
int pa=0, pb=0, ua=0, ub=0, ok=1, i, j, k, x;
for(i=1;i<=n&&ok==1;i++)
if(viz[i]==0)
{
ca[++ua]=i;
viz[i]=1;
if(ua==1)
pa=1;
while((pa<=ua||pb<=ub)&&ok==1)
{
while(pa<=ua&&ok==1)
{
x=ca[pa];
for(j=1;j<=n&&ok==1;j++)
if(ma[x][j]==1&&viz[j]==0)
{
cb[++ub]=j;
if(ub==1)
pb=1;
for(k=1;k<ub&&ok==1;k++)
if(ma[cb[ub]][cb[k]]==1)
ok=0;
viz[j]=1;
}
pa++;
}
while(pb<=ub&&ok==1)
{
x=cb[pb];
for(j=1;j<=n&&ok==1;j++)
if(ma[x][j]==1&&viz[j]==0)
{
ca[++ua]=j;

46
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

if(ua==1)
pa=1;
for(k=1;k<ua&&ok==1;k++)
if(ma[ca[ua]][ca[k]]==1)
ok=0;
viz[j]=1;
}
pb++;
}
}
}
return ok;
}
graf operator+(graf G1, int nr)
{
int i, j, nnr, mnr=0;
graf G2;
nnr=G1.get_n();
G2.set_n(nnr+nr);
G2.set_m(0);
for(i=1;i<=nnr;i++)
for(j=i;j<=nnr;j++)
if(G1.get_i_j_mc(i,j)!=inf)
G2.set_i_j_mc(i,j,G1.get_i_j_mc(i,j));
else
G2.set_i_j_mc(i,j,0);
for(i=nnr+1;i<=nnr+nr;i++)
for(j=1;j<=nnr+nr;j++)
G2.set_i_j_mc(i,j,0);
return G2;
}
graf operator+(graf G1, muchii aux)
{
int i, j, ma1, mc1, nnr, mnr=0;
graf G2;
muchii aux1;
G2.set_m(0);
nnr=G1.get_n();
G2.set_n(nnr);
for(i=1;i<=nnr;i++)
for(j=i;j<=nnr;j++)
if(G1.get_i_j_mc(i,j)!=inf)
G2.set_i_j_mc(i,j,G1.get_i_j_mc(i,j));
else
G2.set_i_j_mc(i,j,0);
G2.set_i_vm(aux);
return G2;
}
graf operator-(graf G1, int nr)
{
int i, j, nnr;

47
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

graf G2;
nnr=G1.get_n();
G2.set_n(nnr-1);
for(i=1;i<=nr-1;i++)
for(j=i;j<=nr-1;j++)
if(G1.get_i_j_mc(i,j)!=inf)
G2.set_i_j_mc(i,j,G1.get_i_j_mc(i,j));
else
G2.set_i_j_mc(i,j,0);
//G2.afisare();
for(i=1;i<nr;i++)
for(j=nr;j<nnr;j++)
if(G1.get_i_j_mc(i,j+1)!=inf)
G2.set_i_j_mc(i,j,G1.get_i_j_mc(i,j+1));
else
G2.set_i_j_mc(i,j,0);
for(i=nr;i<nnr;i++)
for(j=i;j<nnr;j++)
if(G1.get_i_j_mc(i+1,j+1)!=inf)
G2.set_i_j_mc(i,j,G1.get_i_j_mc(i+1,j+1));
else
G2.set_i_j_mc(i,j,0);
return G2;

}
graf operator-(graf G1, muchii aux)
{
graf G2;
int nnr, mnr, i, j, s, d, f;
nnr=G1.get_n();
G2.set_m(0);
G2.set_n(nnr);
mnr=G1.get_m();
for(i=1;i<=nnr;i++)
for(j=i;j<=nnr;j++)
{
G2.set_i_j_mc(i,j,0);
}
for(i=1;i<=mnr-1;i++)
{

if((G1.get_i_vm(i).x==aux.x&&G1.get_i_vm(i).y==aux.y&&G1.get_i_vm(i).cost==aux.cost)||
(G1.get_i_vm(i).x==aux.y&&G1.get_i_vm(i).y==aux.x&&G1.get_i_vm(i).cost==aux.cost))
G2.set_i_vm(G1.get_i_vm(i+1));
else
G2.set_i_vm(G1.get_i_vm(i));
}
return G2;
}

48
D.E.C.: Programare orientat pe obiect. Grafuri neorientate.

5. Bibliografie

http://facultate.regielive.ro
http://www.graf.go.ro/index1.html
http://ro.wikipedia.org/wiki/Graf
http://ro.wikipedia.org/wiki/Programare_orientat%C4%83_pe_obiecte
http://www.aut.upt.ro/~dberian/Labs/POO.pdf
http://ro.wikipedia.org/wiki/Algoritmul_lui_Kruskal
http://ro.wikipedia.org/wiki/Algoritmul_lui_Prim
http://grafurineorientate.wikispaces.com/

49

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