Sunteți pe pagina 1din 22

Clasa Graf Neorientat Olaru Mihai Alexandru

1

Clasa
Graf
Neorientat
(graf neorientat
reprezentat prin liste
de adicenta alocate
dinamic)
Olaru Mihai Alexandru
Clasa a XI a E
Clasa Graf Neorientat Olaru Mihai Alexandru
2

Cuprins

Descrierea clasei
Descrierea functiilor aplicatiei si meniului
Implementarea clasei
Prezentarea clasei
Bibliografia












Clasa Graf Neorientat Olaru Mihai Alexandru
3

Descrierea clasei
Clasa contine:
- date member private : numar de noduri si liste de adiacenta
- metode publice:
constructor implicit,constructor de copier
destructor
citire graf din fisier(nr noduri,nr muchii ,sir de muchii)
afisare graf: nr. noduri si listele de adiacenta ale fiecarui nod
afisare component conexe si nr de component conexe din graf
parcurgerea BFS a grafului
supraincarcarea operatorului < pt 2 grafuri g1 si g2 , pt a
verifica daca graful g1 este graf partial al grafului g2
verificarea grafului: graf eulerian
Definitie: Se numeste graf neorientat o structura G = (V, E) in care V este o multime
finita, iar E o multime de perechi neordonate de elemente din V. Mai exact E {{a, b} | a, b V,
a b}. Multimea V se numeste multimea varfurilor grafului G, iar E multimea muchiilor. Notam
muchiile sub forma [a, b], unde a,b V.
Reprezentare prin lista de adicenta:
Reprezentarea prin liste de adiacen const ntr-un tablou Adj cu |V| liste, una
pentru fiecare vrf din V. Pentru fiecare u din V, lista de adiacen Adj[u] conine
referine ctre toate vrfurile v pentru care exist muchia (u, v) n E. Cu alte
cuvinte, Adj[u] este format din totalitatea vrfurilor adiacente lui u n G.
Aceast reprezentare este preferat pentru grafurile rare ( |E| este mult mai mic
dect |V|x|V|).

Pentru graful de mai sus, lista de adiacen este urmtoarea:
0: 12
1: 0234
2: 013
3: 124
4: 13
Clasa Graf Neorientat Olaru Mihai Alexandru
4

Componente conexe:
Definitie Un graf este conex daca pentru oricare doua varfuri x si y distinct exista
un lant care le leaga.( Lan = este o secven de noduri ale unui graf
neorientat G=(V,E), cu proprietatea c oricare dou noduri consecutive din
secventa lant sunt adiacente).
Definitie Se numeste componenta conexa a grafului G=(X,U) un subgraf G=(X,U)
conex cu proprietatea ca nu exista nici un lant in G care sa lege un varf din X cu un
varf din X\X.






Obs Un graf cu n noduri si n component conexe are numai varfuri isolate .Graful
format dintr-un singur nod este conex.
Parcurgerea n lime

Parcurgerea n lime (Breadth-first Search - BFS) presupune vizitarea
nodurilor n urmtoarea ordine:
Nodul surs (considerat a fi pe nivelul 0)
Vecinii nodului surs (acetia constituind nivelul 1)
Vecinii nc nevizitai ai nodurilor de pe nivelul 1 (acetia constituind
nivelul 2)
Vecinii nc nevizitai ai nodurilor de pe nivelul 2
.a.m.d.
Caracteristica esenial a acestui tip de parcurgere este, deci, c se prefer
explorarea n lime, a nodurilor de pe acelai nivel (aceeai deprtare fa de
surs) n detrimentul celei n adncime, a nodurilor de pe nivelul urmtor.
Pentru implementarea BFS se utilizeaz o coad (Q) n care iniial se afl doar
nodul surs. Se viziteaz pe rnd vecinii acestui nod i se pun i ei n coada. n
momentul n care nu mai exist vecini nevizitai, nodul surs este scos din coad.

Clasa Graf Neorientat Olaru Mihai Alexandru
5

Graf partial
Definitie: Fie G=(X,U). Un graf partial al lui G, este un graf G
1
=(X,V), cu
V U. Altfel spus, un graf partial G
1
este chiar G, sau se obtine din G pastrnd toate
vrfurile si suprimnd niste muchii.
Exemplu:
Pentru graful G=(X,U) de mai jos, construim alaturat graful partial obtinut prin
eliminarea muchiilor ce trec prin vrful 4. Acesta este G
1
=(X,V), unde X=, iar V=(s-
au eliminat muchiile u
3
si u
4
care trec prin nodul 4).

Graf eulerian

Fie G=(V, E) un graf neorientat, unde V are n elemente (n noduri) si E are m
elemente (m muchii).


Lan eulerian = un lan simplu care conine toate muchiile unui graf


Lantul: L=[1.2.3.4.5.3.6.2.5.6] este lant eulerian

Ciclu eulerian = un ciclu simplu care conine toate muchiile grafului
Ciclul: C=[1.2.3.4.5.3.6.2.5.6.1] este ciclu eulerian


Graf eulerian = un graf care conine un ciclu eulerian.

Condiie necesar i suficient: Un graf este eulerian dac i numai dac oricare
vrf al su are gradul par.
Observatie: graful poate fi eulerian si daca contine noduri izolate.
Clasa Graf Neorientat Olaru Mihai Alexandru
6



Descrierea functiilor aplicatiei:
graf(); //initializeaza un graf cu 0 noduri si 0 muchii
graf(unsigned); // initializeaza un graf cu n noduri si 0 muchii
~graf(); //destructor
graf(graf &G);//constructor de copiere
int ret_dim(){return n;}//returneaza nr de noduri ale grafului

void meniu();
void afisare_ma(); // afiseaza ma
void afisare_lista(int);//afiseaza lista de adiacenta

void bfs();//citeste un nod de la tastatura si realizeaza parcurgerea
in latime.
void bf(int,int);//adiacentii lui x (directi sau indirecti) sunt marcati
in viz cu valoarea k (parcurgerea in lungime)

void set_viz(int); //umple vectorul viz cu valoarea primita ca
parametru
int conex(); //verifica conexitatea grafului
int eulerian(); //verifica daca graful este eulerian
int grad(int); //returneaza gradul nodului primit ca parametru

void citire_f_n_m_muchii(char*); //citeste din fisier n,m si vm si
creeaza ma
void creare_liste(char*);// citeste din fisier n,m, si vm si creeaza
lista de adiacenta
void componente_conexe(); //afiseaza numarul de componente
conexe si le afiseaza
int graf_partial(graf); //verifica daca graful primit ca parametru
este un graf partial al grafului initial
int afisare_partial();
graf operator <(graf G1);//supraincarcarea operatorului < : verifica
daca G2 este graf partial al lui G1








Clasa Graf Neorientat Olaru Mihai Alexandru
7

Descrierea meniului

Meniul se acceseaza prin apasarea tastelor:
1.Citirea grafului neorientat din fisierul Graf.in (nr.
noduri,nr. arce,sir de muchii)
2. Afisarea listelor de adiacenta
3. Afisarea componentelor conexe din graf si a numarului
de componente conexe
4. Parcurgerea BF de la un nod dat
5. Supraincarcarea operatorului < pentru 2 grafuri G1 si
G2, pentru a verifica daca graful G2 este graf partial al
grafului G1
6. Verificare graf eulerian
7. Exit

Implementarea clasei
Programul este impartit in trei fisiere:
Main.cpp
Graf.cpp
Graf.h










Clasa Graf Neorientat Olaru Mihai Alexandru
8

Main.cpp
include<iostream>
#include<fstream>
#include"graf.cpp"
using namespace std;
int main()
{
graf G,G1,G2;
int i=0;
G.meniu();
G1.citire_f_n_m_muchii("graf1.1");

G2.citire_f_n_m_muchii("graf2.in");
G1.creare_liste("graf1.1");
G2.creare_liste("graf2.in");
G1.afisare_ma();
G2.afisare_ma();
while(i!=7)
{
cin>>i;int ok=0;

if(i==1)
{

cout<<"Citirea din fisier a grafului orientat a fost realizata;\n";
}


Clasa Graf Neorientat Olaru Mihai Alexandru
9

if(i==2)
{cout<<"alegeti dintre G1 si G2(ok=0 pt ambele ): ok= ";
cin>>ok;
if(ok==1)
{
cout<<"graful 1"<<endl;

for(int j=1; j<=G1.ret_dim();j++)
G1.afisare_lista(j);
}
if(ok==2)
{ cout<<"graful 2"<<endl;
for(int j=1;j<=G2.ret_dim();j++)
G2.afisare_lista(j);}
if(ok==0) {
for(int j=1;j<=G1.ret_dim();j++)
G1.afisare_lista(j);
cout<<endl;
for(int j=1;j<=G2.ret_dim();j++)
G2.afisare_lista(j);
}
}
if(i==3)
{cout<<"alegeti dintre G1 si G2(ok=0 pt ambele ) ok= ";

cin>>ok;
cout<<endl;
if(ok==1)
G1.componente_conexe();
Clasa Graf Neorientat Olaru Mihai Alexandru
10

if(ok==2)
G2.componente_conexe();
if(ok==0){
G1.componente_conexe();
G2.componente_conexe();


}
}
if(i==4)
{
cout<<"\n";
cout<<"alegeti dintre G1 si G2(ok=0 pt ambele ) ok= ";

cin>>ok;
cout<<endl;
if(ok==1)
G1.bfs();
if(ok==2)
G2.bfs();
if(ok==0){
cout<<"Graf 1"<<endl;
G1.bfs();
cout<<endl;
cout<<"Graf 2"<<endl;
G2.bfs();

}
}
Clasa Graf Neorientat Olaru Mihai Alexandru
11



if(i==5)
{
G1<G2;
G2.afisare_partial();
}

if(i==6)
{ cout<<"alegeti dintre G1 si G2(ok=0 pt ambele ) ok= ";

cin>>ok;
cout<<endl;
if(ok==1)
if(G1.eulerian())cout<<"Graful 1 este eulerian;"<<endl;else cout<<"Graful 1
nu este eulerian"<<endl;
cout<<endl;
if(ok==2)
if(G1.eulerian())cout<<"Graful 2 este eulerian;"<<endl;else cout<<"Graful 2
nu este eulerian"<<endl;
if(ok==0){if(G1.eulerian())cout<<"Graful 1 este eulerian;"<<endl;else
cout<<"Graful 1 nu este eulerian"<<endl;
if(G2.eulerian())cout<<"Graful 2 este eulerian;"<<endl;else
cout<<"Graful 2 nu este eulerian"<<endl;

}
}
if(i==7)
break;
} return 0;}
Clasa Graf Neorientat Olaru Mihai Alexandru
12

Graf.h
typedef struct{int x; int y; int cost;}muchii;
struct nod
{int nd;
nod *next;}
;
class graf{
int n, ma[50][50], m, mc[50][50], viz[51];
muchii vm[1225];
nod *L[20];
public:
graf(); //initializeaza un graf cu 0 noduri si 0 muchii
graf(unsigned); // initializeaza un graf cu n noduri si 0 muchii
graf(graf&);
~graf();
int ret_dim(){return n;}
void meniu();
void afisare_ma(); // afiseaza ma
void afisare_lista(int);//afiseaza lista de adiacenta
void bfs();
void bf(int,int);//adiacentii lui x (directi sau indirecti) sunt marcati in viz cu valoarea k
(parcurgerea in lungime
void set_viz(int); //umple vectorul viz cu valoarea primita ca parametru
int conex(); //verifica conexitatea grafului
int eulerian(); //verifica daca graful este eulerian
int grad(int); //returneaza gradul nodului primit ca parametru

void citire_f_n_m_muchii(char*); //citeste din fisier n,m si vm si creeaza ma
void creare_liste(char*);// citeste din fisier n,m, si vm si creeaza lista de adiacenta
void componente_conexe(); //afiseaza numarul de componente conexe si le afiseaza
Clasa Graf Neorientat Olaru Mihai Alexandru
13

int graf_partial(graf); //verifica daca graful primit ca parametru este un graf partial al
grafului initial
int afisare_partial();

graf operator <(graf G1);
};
Graf.cpp
#include<iostream>
#include<fstream>
#include "graf.h"

using namespace std;

ifstream f("graf2.in");
int n,m, c[50], ca[50], cb[50], t[50], s[50], v[50], wr;
int r,l;

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;
Clasa Graf Neorientat Olaru Mihai Alexandru
14

mc[i][j]=inf;
}
}
graf::graf(graf &G)
{
n=G.n;

for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
ma[i][j]=G.ma[i][j];
}
graf::~graf( )
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{ma[i][j]=0;}
//cout<<"s-au eliberat (n*n)"<<" "<<sizeof(int)<<"\n";
}
void graf::meniu()
{
cout<<" *** MENIU APLICATIE *** \n";
cout<<"\n";
cout<<"\n";
cout<<"\n";
cout<<"Tastati cifra corespunzatoare fiecarei cerinte: ";
cout<<"\n";
cout<<"\n";
cout<<"1. Citirea grafului neorientat din fisierul Graf.in (nr. noduri,nr. arce,sir de
muchii);\n";
cout<<"2. Afisarea listelor de adiacenta ;\n";
cout<<"3. Afisarea componentelor conexe din graf si a numarului de componente
conexe;\n";
Clasa Graf Neorientat Olaru Mihai Alexandru
15

cout<<"4. Parcurgerea BF de la un nod dat;\n";
cout<<"5. Supraincarcarea operatorului < pentru 2 grafuri G1 si G2, pentru a verifica daca
graful G2 este graf partial al grafului G1;\n";
cout<<"6. Verificare graf eulerian;\n";
cout<<"7. Exit;\n";

}

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_lista(int nr_nod)
{
nod *p=L[nr_nod];
if(p!=0)
{cout<<"lista vecinilor lui "<<nr_nod<<endl;
nod *c=p;
while(c)
{cout<<c->nd<<" ";
c=c->next;}
cout<<endl;}
}
Clasa Graf Neorientat Olaru Mihai Alexandru
16


void graf::creare_liste(char *c)
{ int i,j;
nod *p,*q;
ifstream f(c);
f>>n>>m;
while(f>>i>>j)
{
{p=new nod; //se adauga j in lista vecinilor lui i
p->nd=j;
p->next=L[i];
L[i]=p;
}
}/*
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
if(ma[i][j]==1){
p->nd=j;
p->next=L[i];
L[i]=p;
}
}*/

}

void graf::citire_f_n_m_muchii(char *c)
{
int i, j;
int x, y;
ifstream f(c);
Clasa Graf Neorientat Olaru Mihai Alexandru
17

f>>n>>m;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
ma[i][j]=0;
ma[j][i]=0;

}
for(i=1;i<=m;i++)
{
f>>x>>y;
ma[x][y]=1;
ma[y][x]=1;

}
}

void graf::bfs()
{
int prim,ultim,C[100];
int ndr;
cout<<endl<<"nodul de inceput ";
cin>>ndr;
viz[ndr]=1;
prim=ultim=1;
C[prim]=ndr;
cout<<endl<<"parcurgere in latime "<<endl;

int varf,nr;
nod *p;
while(prim<=ultim)
Clasa Graf Neorientat Olaru Mihai Alexandru
18

{varf=C[prim];
p=L[varf]; // se parcurge lista elementelor din varful cozii
while(p)
{nr=p->nd;
if(viz[nr]==0) //numai daca nu a fost vizitat
{ultim++; //maresc coada
C[ultim]=nr; //il adaug in coada
viz[nr]=1;}; //il marchez ca fiind vizitat
p=p->next;
}
prim++; //avansez la urmatorul varf din coada
}

for(int i=1;i<=ultim;i++)
cout<<C[i]<<" ";
}

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;
Clasa Graf Neorientat Olaru Mihai Alexandru
19

}
}
}
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_viz(int nr)
{
int i;
for(i=1;i<=n;i++)
viz[i]=nr;
}

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)
{
Clasa Graf Neorientat Olaru Mihai Alexandru
20

c[++u]=i;
viz[i]=1;
}
}
if(u==n)
return 1;
return 0;
}
int graf::eulerian()
{
int nr, ok=0;
if(this->conex()==0)
return 0;
for(int i=1;i<=n;i++)
{
nr=this->grad(i);
if(nr%2!=0)
return 0;
}
return 1;
}

int ma[100][100];
void graf::componente_conexe()
{
int k, i, j;
k=0;
this->set_viz(0);
for(i=1;i<=n;i++)
if(viz[i]==0)
{
Clasa Graf Neorientat Olaru Mihai Alexandru
21

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';
}
}
}
graf graf::operator<( graf G1)
{
if(n==G1.n)
{
for(int i=1;i<=G1.n;i++)
for(int j=1;j<=G1.m;j++)
{
if(ma[i][j]==0)
l++;
Clasa Graf Neorientat Olaru Mihai Alexandru
22

if(G1.ma[i][j]==0 && ma[i][j]==0)
r++;

}
}
else
{r=0;
l=1;
}


}
int graf:: afisare_partial()
{
if(r>=l)
{
cout<<"Graful G2 este graf partial grafului G1 ";
cout<<"\n";}
else
{
cout<<"Graful G2 nu este graf partial grafului Gl";
cout<<"\n";}
}

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