Sunteți pe pagina 1din 13

Ministerul Educaiei a Republicii Moldova

Universitatea Tehnic a Moldovei

Lucrare de laborator la
Matematica discret

Lucrare de laborator nr. 1

Tema: Pstrarea grafurilor n memoria calculatorului.

A elaborat:

st. gr. TI-046 Chlimari N.

A verificat:

Marchitan

Chiinu 2005

1.

SCOPUL LUCRRII:

Studierea metodelor de definire a unui graf: matrice de inciden, matrice de adiacen, liste;
Elaborarea unor proceduri de introducere, extragere i transformare a diferitor forme de reprezentare
intern a grafurilor cu scoaterea rezultatelor la display sau imprimant.
2. NOTE DE CURS
Metode de reprezentare a grafului
Exist trei metode de baz de definire a unui graf:
1. Matricea de inciden;
2. Matricea de adiacen;
3. Lista de adiacen (inciden).
Vom face cunotin cu fiecare dintre aceste metode.
Matricea de inciden
Este o matrice de tipul mxn, n care m este numrul de muchii sau arce (pentru un graf orientat), iar n este
numrul vrfurilor. La intersecia liniei i cu coloana j se vor considera valori de 0 sau 1 n conformitate cu
urmtoarea regul:
1 - dac muchia i este incident cu vrful j (dac arcul i "intr" n vrful j n cazul unui graf
orientat);
0 - dac muchia (arcul) i i vrful j nu sunt incidente;
-1 - numai pentru grafuri orientate, dac arcul i "iese" din vrful j.
x1
x2
x3
x4
x5
x6
x7
u1
-1
0
1
0
0
0
0
u2
-1
0
0
1
0
0
0
u3
0
0
0
-1
0
0
1
u4
0
0
-1
0
0
0
1
u5
0
-1
1
0
0
0
0
u6
0
-1
0
0
1
0
0
u7
0
-1
0
0
0
1
0
u8
0
0
-1
0
0
1
0
Fig. 3. Exemplu de matrice de inciden
Este uor de observat c aceast metod este de o eficacitate mic n sensul utilizrii memoriei
calculatorului: fiecare linie conine doar dou elemente diferite de zero (o muchie poate fi incident cu nu
mai mult de dou vrfuri).
n limbajul Pascal matricea de inciden poate fi redat printr-un tablou bidimensional mxn:
Matr_Incd: array [1..LinksCount, 1..TopsCount] of integer;

Matricea de adiacen
Este o matrice ptrat nxn, aici n este numrul de vrfuri. Fiecare element poate fi 0, dac vrfurile
respective nu sunt adiacente, sau 1, n caz contrar. Pentru un graf fr bucle putem observa urmtoarele:
diagonala principal este format numai din zerouri;
pentru grafuri neorientate matricea este simetric fa de diagonala principal.
x1
x2
x3
x4
x5
x6
x7
x1
0
0
1
1
0
0
0
x2
0
0
1
0
1
1
0
x3
0
0
0
0
0
1
1
x4
0
0
0
0
0
0
1
x5
0
0
0
0
0
0
0
x6
0
0
0
0
0
0
0
x7
0
0
0
0
0
0
0

Fig. 4. Exemplu de matrice de adiacen


n limbajul Pascal matricea de adiacen poate fi reprezentat n modul urmtor:
Matr_Ad :array [1..TopsCount,1..TopsCount] of byte,

sau
Matr_Ad :array [1..TopsCount,1..TopsCount] of boolean;

Dup cum este lesne de observat i n acest caz memoria calculatorului este utilizat nu prea eficace din
care cauz matricea de adiacen ca i matricea de inciden se vor utiliza de obicei doar n cazul n care se
va rezolva o problem concret pentru care reprezentarea grafului n aceast form aduce unele faciliti
algoritmului respectiv.
Pentru pstrarea grafurilor n memoria calculatorului (n deosebi, memoria extern) se va utiliza una din
posibilitile de mai jos.
Lista de adiacen i lista de inciden
Lista de adiacen este o list cu n linii (dup numrul de vrfuri n), n linia cu numrul i vor fi scrise
numerele vrfurilor adiacente cu vrful i.
Lista de inciden se definete analogic cu deosebirea c n linia i vor fi scrise numerele muchiilor
(arcelor) incidente cu vrful i.
Reprezentarea grafurilor prin intermediul acestor liste permite utilizarea mai eficace a memoriei
calculatorului, ns aceste forme sunt mai complicate att n realizare, ct i n timpul procesrii. Pentru a
lua n consideraie lungimea variabil a liniilor vor fi utilizate variabile dinamice i pointeri.
Vom exemplifica pentru un graf cu n vrfuri. Deoarece fiecare element al listei conine numere de vrfuri
este evident s considerm c vom avea un ir de variabile dinamice de tip INTEGER care se vor afla n
relaia respectiv de precedare (succedare). Aceast relaie se va realiza prin pointeri, unii mpreun cu
variabila de tip ntreg n nregistrarea (Pascal: record). Pentru a pstra indicatorii de intrare n aceste iruri
se va folosi un tablou unidimensional de indicatori de lungime n. n calitate de simbol de terminare a
irului se va utiliza un simbol care nu a fost folosit la numeraia vrfurilor (de exemplu 0), care va fi
introdus n calitate de variabil de tip ntreg al ultimului bloc.
De exemplu, lista de adiacen :
1 - 3, 4, 0
2 - 3, 5, 6, 0
3 - 6, 7, 0
4 7, 0
5-0
6-0
7-0

va avea urmtoarea reprezentare intern:

2
3

variabile dinamice (pointer i variabil de tip ntreg)

masiv de indicatori
Fig. 5. Reprezentarea intern a listei de adiacen

Va fi necesar de realizat urmtoarea declaraie:


Type
BlockPtr = ^BlockType;
BlockType = record;
Number : integer;
Point : BlockPtr;
end;
Var In_Ptr :array [1..TopsCount] of BlockPtr;

Lista de adiacen (i realizarea reprezentrii interne) se va implementa cu ajutorul procedurii New


(BlockPtr_Type_Variable), n care BlockPtr_Type_Variable este o variabil de tip BlockPtr.
3. SARCINA DE BAZ
1. Elaborai procedura introducerii unui graf n memoria calculatorului n form de matrice de inciden,
matrice de adiacen i list de adiacen cu posibiliti de analiz a corectitudinii.
2. Elaborai proceduri de transformare dintr-o form de reprezentare n alta.
3. Folosind procedurile menionate elaborai programul care va permite:
introducerea grafului reprezentat sub oricare din cele trei forme cu posibiliti de corecie a
datelor;
pstrarea grafului n memoria extern n form de list de adiacen;
extragerea informaiei ntr-una din cele trei forme la imprimant sau display.

Listingul
//Lucrare de laborator Nr1.
//
Tema:Memorarea grafului in memorie sub diferite forme.
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
int n,u,m,g[40][20],g1[20][20],i,j,k;
struct lista {
int c;
struct lista *urm;
} start[20],*nod;
//===============================================================
void Virf()
{ clrscr();
_setcursortype(_NORMALCURSOR);
printf("\n\t");
textcolor(3); cprintf("Introduceti numarul de virfuri : ");
scanf("%d",&n);
}
//-------------------------------------------------------------------void Afis()
{ printf("\n\t");
textcolor(30);

}
//------------------------------------------------------------------void Pauza()
{ textcolor(2); cprintf("\n Tastati o tasta pentru a continua...");
textcolor(15);
getch();
}
//------------------------------------------------------------------/* Prezentarea temei */
void Prezt()
{ clrscr();
_setcursortype(_NOCURSOR);
printf("\n\n\n\n\t\t");
textcolor(3); cprintf("Lucrare de laborator Nr1 la Matematica Discreta.");
printf("\r\n\n\t\t");
cprintf("Memorarea grafului in memorie sub diferite forme.");
textcolor(15);
getch();
}
//===============================================================
void InMIn()
{ printf("\n\t");
textcolor(3); cprintf("Introduceti numarul de arce : ");
scanf("%d",&u);
Afis(); cprintf("Introduceti matricea de incidenta:\n\n\n");
textcolor(2); cprintf("\r In ");
textcolor(11);
for(i=1;i<=n;i++) cprintf("%d ",i);
printf("\n ");
for(i=1;i<=n;i++) if(i==1) cprintf(" _");
else cprintf(" _");
printf("\n");
for(i=1;i<=u;i++)
{ cprintf(" u%.2d|",i);
for(j=0;j<n;j++) scanf("%d",&g[i][j]);
}
Pauza();
}
//------------------------------------------------------------------void InMAd()
{ Afis(); cprintf("Introduceti matricea de adiacenta:\n\n\n");
textcolor(2); cprintf("\r Ad ");
textcolor(11);
for(i=1;i<=n;i++) cprintf("%d ",i);
printf("\n ");
for(i=0;i<n;i++) cprintf("_ ");
printf("\n");
for(i=1;i<=n;i++)

{ cprintf(" %d| ",i);


for(j=0;j<n;j++) scanf("%d",&g1[i][j]);
}
Pauza();
}
//------------------------------------------------------------------void InLAd()
{ Afis(); cprintf("Introduceti lista de adiacenta :\n\n");
for(i=0;i<n;i++)
{ textcolor(11); cprintf("\n\r %d| ",i+1);
start[i].urm=NULL;
nod=&start[i];
do
{ nod->urm=(struct lista *)malloc(sizeof(struct lista));
nod=nod->urm;
scanf("%d",&nod->c);
nod->urm=NULL;
}
while((nod->c)!=0);
}
Pauza();
}
//===============================================================
void AfMIn()
{ clrscr();
Afis();
cprintf("Matricea de incidenta:\n"); printf("\n");
textcolor(2); cprintf("In ");
textcolor(11);
for(i=1;i<=n;i++) cprintf("%d ",i);
printf("\n ");
for(i=1;i<=n;i++) if(i==1) cprintf(" _");
else cprintf(" _");
printf("\n");
for(i=1;i<=u;i++)
{ cprintf("u%.2d|",i);
for(j=0;j<n;j++) printf("%2d",g[i][j]);
printf("\n");
}
Pauza();
}
//------------------------------------------------------------------void AfMAd()
{ clrscr();
Afis();
cprintf("Matricea de adiacenta:\n"); printf("\n");
textcolor(2); cprintf("Ad ");
textcolor(11);

for(i=1;i<=n;i++) cprintf("%d ",i);


printf("\n ");
for(i=1;i<=n;i++) cprintf("_ ");
printf("\n");
for(i=1;i<=n;i++)
{ cprintf(" %d|",i);
for(j=0;j<n;j++) printf(" %d",g1[i][j]);
printf("\n");
}
Pauza();
}
//------------------------------------------------------------------void AfLAd()
{ clrscr();
Afis();
cprintf(" Lista de adiacenta:\n"); printf("\n");
for(i=0;i<n;i++)
{ nod=start[i].urm;
textcolor(11); cprintf(" %d| ",i+1);
while(nod->urm)
{ printf("%d ",nod->c);
nod=nod->urm;
}
printf("0\n\n");
}
Pauza();
}
//===============================================================
void In()
{ k=1; u=0;
for(i=1;i<=n;i++)
for(j=0;j<n;j++)
if(g1[i][j]==1) u++;
for(i=1;i<=u;i++)
for(j=0;j<n;j++) g[i][j]=0;
for(i=1;i<=n;i++)
for(j=0;j<n;j++)
if(g1[i][j]==1) { if(i-1==j) g[k][j]=2;
else {g[k][i-1]=-1; g[k][j]=1;}
k++;
}
}
//===============================================================
void Ad()
{ int i1,j1;
for(i=1;i<=n;i++)
for (j=0;j<n;j++) g1[i][j]=0;
for(i=1;i<=u;i++)

{ k=1;
for(j=0;j<n;j++)
{ switch(g[i][j]) {
case 2: g1[j+1][j]=1;k=0; break;
case -1: i1=j+1;k++;
break;
case 1: j1=j;k++;
}
}
if(k==3) g1[i1][j1]=1;
}
}
//------------------------------------------------------------------void LAd()
{ for(i=0;i<n;i++)
{ start[i].urm=NULL;
nod=&start[i];
for(j=0;j<n;j++)
if(g1[i+1][j]==1)
{ nod->urm=(struct lista *)malloc(sizeof(struct lista));
nod=nod->urm;
nod->c=j+1;
nod->urm=NULL;
}
nod->urm=(struct lista *)malloc(sizeof(struct lista));
nod=nod->urm;
nod->c=0;
nod->urm=NULL;
}
}
//===============================================================
void LAd1()
{ for(i=1;i<=n;i++)
for(j=0;j<n;j++) g1[i][j]=0;
for(i=0;i<n;i++)
{ nod=start[i].urm;
while(nod->c!=0)
{ g1[i+1][nod->c-1]=1;
nod=nod->urm;
}
}
}
//===============================================================
void SbMn1()
{ clrscr();
textcolor(15);
_setcursortype(_NOCURSOR);
printf("\n\

\n\

[ MENIU/INTRODUCERE ]
\n\

%c\n\
[1] - In forma de matrice de incidenta. \n\
[2] - In forma de matrice de adiacenta. \n\
[3] - In forma de lista de adiacenta. \n\
Bksp - Inapoi.
\n\
\n",185);
l2:m=getch();
if(m==8) goto l8;
switch (m) {
case 49: Virf();InMIn(); break;
case 50: Virf();InMAd();break;
case 51: Virf();InLAd(); break;
default: goto l2;
}
l8:;
}
//------------------------------------------------------------------void SbMn2()
{ l12:char c;
clrscr();
if(m==49) {Ad(); m=50;}
if(m==51) {LAd1(); m=50;}
_setcursortype(_NOCURSOR);
printf("\n\
\n\

[ MENIU/ADAUGARE ]
\n\
%c\n\

[1] - A unui virf.


\n\

[2] - A unui arc.


\n\

Bksp - Inapoi.
\n\
\n",185);
k=getch();
if(k==8) goto l9;
_setcursortype(_NORMALCURSOR);
if(k==49)
{ l6:clrscr();
printf("\n\n\n\t");
textcolor(3); cprintf("Doriti sa specificati virful [D/N]?: ");
textcolor(15);
scanf("%c",&c);
if(c=='d'||c=='D') u=0;
else if(c=='n'||c=='N') u=1;
else goto l6;

clrscr();
if(u==0)
{ printf("\n\n\n\t");
textcolor(3); cprintf("Introduceti numarul virfului: ");
scanf("%d",&k);
if(k<=n)
{ n=n+1;
for(i=n;i>0;i--)
for(j=n-1;j>=0;j--)
if(i<k&&j<k-1) ;
else if(j+1==k) g1[i][j]=0;
else if(i==k) g1[i][j]=0;
else if(i>k&&j+1<k) g1[i][j]=g1[i-1][j];
else if(i>k) g1[i][j]=g1[i-1][j-1];
else if(i<k&&j>=k) g1[i][j]=g1[i][j-1];
}
else if(k==n+1) goto l7;
else { clrscr();
gotoxy(20,10);
_setcursortype(_NOCURSOR);
textcolor(4+128); cprintf("Asa virf nu poate fi adaugat.\n\n");
cprintf("\r
Respectati ordinea!");
getch();
}
}
else l7:n++;
}
if(k==50)
{ clrscr();
printf("\n\n\n\t");
textcolor(3); cprintf("Introduceti virful initial: ");
scanf("%d",&i);
printf("\n\n\t");
textcolor(3); cprintf("Introduceti virful final : ");
scanf("%d",&k);
if(i<=n&&k<n) g1[i][k-1]=1;
else { clrscr();
gotoxy(20,10);
_setcursortype(_NOCURSOR);
textcolor(4+128); cprintf("Asa arc nu poate fi adaugat.\n\n");
cprintf("\r
Respectati numerotarea virfurilor!");
getch();
}
}
textcolor(15);
goto l12;
l9:;
}

//------------------------------------------------------------------void SbMn3()
{ l11:char c;
clrscr();
if(m==49) {Ad(); m=50;}
if(m==51) {LAd1(); m=50;}
_setcursortype(_NOCURSOR);
printf("\n\
\n\

[ MENIU/STERGERE ]
\n\
%c\n\

[1] - A unui virf.


\n\

[2] - A unui arc.


\n\

Bksp - Inapoi.
\n\
\n",185);
k=getch();
if(k==8) goto l10;
_setcursortype(_NORMALCURSOR);
if(k==49)
{ l5:clrscr();
printf("\n\n\n\t");
textcolor(3); cprintf("Doriti sa stergeti complet virful [D/N]?: ");
textcolor(15);
scanf("%c",&c);
if(c=='d'||c=='D') u=0;
else if(c=='n'||c=='N') u=1;
else goto l5;
clrscr();
printf("\n\n\n\t");
textcolor(3); cprintf("Introduceti numarul virfului: ");
scanf("%d",&k);
if(k<n)
{ if(u==0)
{ for(i=k;i<=n;i++)
for(j=0;j<n;j++) g1[i][j]=g1[i+1][j];
for(i=k;i<n;i++)
for(j=1;j<=n;j++) g1[j][i-1]=g1[j][i];
n--;
}
if(u==1)
{ for(i=0;i<n;i++) g1[k][i]=0;
for(i=1;i<=n;i++) g1[i][k-1]=0;
}
}
else if(k==n) n--;
else { clrscr();
gotoxy(20,10);
_setcursortype(_NOCURSOR);

textcolor(4+128); cprintf("Asa virf nu exista!");


getch();
}
}
if(k==50)
{ clrscr();
printf("\n\n\n\t");
textcolor(3); cprintf("Introduceti virful initial: ");
scanf("%d",&i);
printf("\n\n\t");
textcolor(3); cprintf("Introduceti virful final : ");
scanf("%d",&j);
if(g1[i][j-1]==0) i=100;
if(i<=n&&j<n) g1[i][j-1]=0;
else { l12:clrscr();
gotoxy(20,10);
_setcursortype(_NOCURSOR);
textcolor(4+128); cprintf("Asa arc nu poate fi sters.\n\n");
if(i!=100) cprintf("\r
Respectati numerotarea virfurilor!");
else cprintf("\r
Arcul dat nu exista!");
getch();
}
}
textcolor(15);
goto l11;
l10:;
}
//------------------------------------------------------------------void SbMn4()
{ l3:clrscr();
_setcursortype(_NOCURSOR);
printf("\n\
\n\

[ MENIU/AFISARE ]
\n\

%c\n\
[1] - In forma de matrice de incidenta. \n\
[2] - In forma de matrice de adiacenta. \n\
[3] - In forma de lista de adiacenta. \n\
Bksp - Inapoi.
\n\
\n",185);
k=getch();
if(k==8) goto l4;
if(m==k)
switch (m) {
case 49: AfMIn(); break;

case 50: AfMAd();break;


case 51: AfLAd();
}
else
{ if((m==49)&&(k==50)) {Ad(); AfMAd();}
if((m==50)&&(k==51)) {LAd(); AfLAd();}
if((m==49)&&(k==51)) {Ad(); LAd(); AfLAd();}
if((m==50)&&(k==49)) {In(); AfMIn();}
if((m==51)&&(k==50)) {LAd1(); AfMAd();}
if((m==51)&&(k==49)) {LAd1(); In(); AfMIn();}
}
goto l3;
l4:;
}
//===============================================================
void main()
{ Prezt();
l:clrscr();
_setcursortype(_NOCURSOR);
printf("\n\
\n\

[ MENIU ]
\n\
%c\n\
[1] - Introducerea grafului. \n\
[2] - Adaugarea.
\n\
[3] - Stergerea.
\n\
[4] - Afisarea.
\n\
Esc - Iesirea.
\n\
\n",185);
l1:k=getch();
switch(k) {
case 49: SbMn1();break;
case 50: SbMn2();break;
case 51: SbMn3();break;
case 52: SbMn4();break;
case 27: exit(0); break;
default: goto l1;
}
goto l;
}
//===============================================================

Concluzie : Efectund aceast lucrare de laborator,am opinut cunotine despre modul


de pstrare a unui graf n memoria calculatorului i proprietile fiecrei
forme n ceea ce ine de volumul memoriei necesare i greutatea prelucrrii
acestora acestea find principiile de baz conform crora se alege metoda
cea mai prielnic de implementare.

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