You are on page 1of 18

PROGRAMIRANJE II

A13 – Grafovi

dr Dražen Brđanin (bdrazen@etfbl.net)


Goran Banjac (goran.banjac@etfbl.net)
Danijela Banjac (danijela.banjac@etfbl.net)
Aleksandar Keleč (aleksandar.kelec@etfbl.net)

2016.
A13 GRAFOVI
Napisati program koji omogućava obilazak grafa po dubini (DFS) pri čemu je potrebno
ispisivati informacioni sadržaj čvorova grafa. Potrebno je koristiti matričnu reprezentaciju
grafa. Informacioni sadržaj čvora je znakovni podatak. Dodatno, realizovati funkciju koja
ispisuje matricu susjednosti grafa.
#include <stdio.h> void dfs(GRAF *g) {
#define MAX 10 int visit[MAX] = {};
void dfs_visit(int u) {
typedef struct g { int v;
int n; printf("%c", g->nodes[u]);
char nodes[MAX]; visit[u] = 1;
int ms[MAX][MAX]; for (v = 0; v<g->n; v++)
} GRAF; if (g->ms[u][v] && !visit[v])
dfs_visit(v);
void pisi_ms(GRAF *g) { }
printf("Matrica susjednosti:\n"); dfs_visit(0);
int i, j; }
for (i = 0; i<g->n; i++) {
for (j = 0; j<g->n; j++)
printf("%d ", g->ms[i][j]);
printf("\n");
}
}

Grafovi 2
A13 GRAFOVI
int main() {
1 3 5
GRAF g = { 6, { '1', '2', '3', '4', '5', '6' },
{ { 0, 1, 1, 1, 0, 0 },
{ 1, 0, 0, 1, 0, 0 }, 2 4 6
{ 1, 0, 0, 1, 1, 0 },
{ 1, 1, 1, 0, 1, 0 },
{ 0, 0, 1, 1, 0, 1 },
{ 0, 0, 0, 0, 1, 0 } } }; 1 3 5
pisi_ms(&g);
printf("\nDFS: ");
2 4 6
dfs(&g);
return 0;
}
Matrica susjednosti:
0 1 1 1 0 0
1 0 0 1 0 0
1 0 0 1 1 0
1 1 1 0 1 0
0 0 1 1 0 1
0 0 0 0 1 0

DFS: 124356

Grafovi 3
A13 GRAFOVI
Napisati program koji pronalazi i ispisuje obuhvatno stablo zadatog grafa, obilaskom grafa
po dubini (DFS) pri čemu je potrebno koristiti matričnu reprezentaciju grafa. Informacioni
sadržaj čvora je znakovni podatak. Na standardni izlaz potrebno je ispisati matricu
susjednosti grafa kao i matricu susjednosti obuhvatnog stabla.
#include <stdio.h> void st_dfs(GRAF *g, GRAF *st)
#define MAX 10 {
int visit[MAX] = {};
typedef struct g { void dfs_visit(int u)
int n; {
char nodes[MAX]; int v;
int ms[MAX][MAX]; visit[u] = 1;
} GRAF; for (v = 0; v<g->n; v++)
if (g->ms[u][v] && !visit[v])
void pisi_ms(GRAF *g) { {
int i, j; st->ms[u][v] = st->ms[v][u] = 1;
for (i = 0; i<g->n; i++) { dfs_visit(v);
for (j = 0; j<g->n; j++) }
printf("%d ", g->ms[i][j]); }
printf("\n"); dfs_visit(0);
} }
}

Grafovi 4
A13 GRAFOVI
int main() {
Matrica susjednosti (graf):
GRAF g = { 6, { '1', '2', '3', '4', '5', '6' },
{ { 0, 1, 1, 1, 0, 0 }, 0 1 1 1 0 0
{ 1, 0, 0, 1, 0, 0 }, 1 0 0 1 0 0
{ 1, 0, 0, 1, 1, 0 }, 1 0 0 1 1 0
{ 1, 1, 1, 0, 1, 0 }, 1 1 1 0 1 0
{ 0, 0, 1, 1, 0, 1 }, 0 0 1 1 0 1
{ 0, 0, 0, 0, 1, 0 } } 0
}; 0 0 0 1 0
GRAF st = { 6, { '1', '2', '3', '4', '5', '6' } };
printf("Matrica susjednosti (graf):\n ");
pisi_ms(&g); Matrica susjednosti (obuhvatno stablo):
st_dfs(&g, &st); 0 1 0 0 0 0
1 0 0stablo):\n
printf("\nMatrica susjednosti (obuhvatno 1 0 0 ");
pisi_ms(&st); 0 0 0 1 1 0
return 0; 0 1 1 0 0 0
} 0 0 1 0 0 1
0 0 0 0 1 0

1 3 5 1 3 5

2 4 6 2 4 6

Grafovi 5
A13 GRAFOVI
Napisati program u kojem treba sa standardnog ulaza učitati graf sa odgovarajućim vezama
između čvorova, pri čemu je potrebno koristiti ulančanu reprezentaciju grafa. Graf se
predstavlja pomoću vektora zaglavlja i odgovarajuće ulančane liste susjeda za svaki čvor
grafa. Informacioni sadržaj čvora grafa je indeks vektora zaglavlja koji odgovara tom čvoru
(uvećan za 1). Nakon toga realizovati funkciju koja obilazi graf po širini (BFS) i ispisuje
rezultat na standardni izlaz. Dodatno, realizovati funkciju koja ispisuje sve susjedne
čvorove zadatog čvora. //pomocne funkcije
#include <stdio.h> int isFull(RED *red) { return red->r == MAX; }
#include <stdlib.h>
#define MAX 100 int isEmpty(RED *red) {
return red->f == -1 || red->f == red->r;}
typedef struct cvor {
int info; struct g *sljedeci; int dodaj(RED *red, int podatak) {
} CVOR; if (isFull(red)) return 0;
if (red->f == -1) red->f = 0;
typedef struct graf { red->niz[red->r++] = podatak;
int n; CVOR *cvorovi[MAX]; return 1; }
} GRAF;
int obrisi(RED *red, int *podatak){
typedef struct red { if (isEmpty(red)) return 0;
int niz[MAX]; int f, r; *podatak = red->niz[red->f++];
} RED; return 1; }

Grafovi 6
A13 GRAFOVI
void bfs(GRAF g, int start) { CVOR* dodaj_kraj(CVOR **pglava, int info) {
RED red; red.f = -1; red.r = 0; CVOR *p, *novi = (CVOR *) malloc(sizeof(CVOR));
int v; novi->info = info;
char visit[MAX] = { 0 }; novi->sljedeci = 0;
visit[start] = 1; if (*pglava == 0)
dodaj(&red, start); *pglava = novi;
while (obrisi(&red, &v)) { else {
printf("%d ", v + 1); for (p = *pglava; p->sljedeci; p=p->sljedeci);
CVOR *tekuci=g.cvorovi[v]; p->sljedeci = novi;
while (tekuci) { }
int u = tekuci->info; return novi;
if (!visit[u]) { }
visit[u] = 1;
dodaj(&red, u); void brisi_listu(CVOR **pglava) {
} while (*pglava) {
tekuci = tekuci->sljedeci; CVOR *p = (*pglava)->sljedeci;
} free(*pglava); *pglava = p; }
} }
}
void pisi_susjede(CVOR *glava) { void brisi_graf(GRAF *g) {
while (glava) { int i;
printf(" %d", glava->info + 1); for (i = 0; i<g->n; i++)
glava = glava->sljedeci; brisi_listu(&g->cvorovi[i]);
} }
}
Grafovi 7
A13 GRAFOVI
void ucitaj_graf(GRAF *g){ int i, j, br_susjeda, susjed;
printf("Unesite broj cvorova grafa : "); scanf("%d", &g->n);
for (i = 0; i<g->n; i++) {
g->cvorovi[i] = NULL; Unesite broj cvorova grafa: 4
printf(" Broj susjeda cvora %d: ", i + 1); scanf("%d", &br_susjeda);
Broj susjeda cvora 1: 2
for (j = 0; j<br_susjeda; j++) {
do { 1. susjed cvora 1: 2
printf(" %d. susjed 2. susjed
cvora %d: ",cvora 1:i 3+ 1);
j + 1,
scanf("%d", &susjed);Broj susjeda cvora 2: 2
} while (susjed<1 && susjed>g->n);
1. susjed cvora 2: 3
dodaj_kraj(&g->cvorovi[i],2.susjed - 1);
susjed cvora 2: 4
} Broj susjeda cvora 3: 1
}
}
1. susjed cvora 3: 4
int main() { Broj susjeda cvora 4: 1
GRAF g; int i; 1. susjed cvora 4: 1
ucitaj_graf(&g);
printf("\nSusjedi cvorova:\n");
Susjedi cvorova:
for (i = 0; i<g.n; i++) { 1: 2 3
printf(" %d: ", i + 1); 2: 3 4
pisi_susjede(g.cvorovi[i]); printf("\n");
}
3: 4
printf("BFS: "); bfs(g, 0);4:brisi_graf(&g);
1
return 0; BFS: 1 2 3 4
}
Grafovi 8
A13 GRAFOVI
Napisati program koji iz ulazne tekstualne datoteke čita dimenzije matrice susjednosti, a
potom matricu susjednosti težinskog, usmjerenog grafa. Težine su definisane kao podaci sa
pokretnim zarezom, pri čemu se garantuje da su težine pozitivne, te da je graf potpuno
povezan. Informacioni sadržaj čvora je proizvoljan realni broj. Naziv ulazne datoteke kao i
indeksi dva čvora unose se kao argumenti komandne linije. Na standardni izlaz ispisati
vrijednosti funkcija informacionog sadržaja čvorova na najkraćoj putanji između čvorova
čiji su indeksi uneseni kao argumenti komandne linije. Funkcije koje treba izračunati za
svaki čvor su: sin(x), cos(x), x2, √x. Ispis uraditi tako da se funkcija za pronalaženje
najkraćeg puta između data dva čvora poziva četiri puta, svaki put sa različitom funkcijom
za ispis u argumentu (funkcija za pronalaženje najkraćeg puta prihvata funkciju za ispis kao
argument).
Napomena: za svaku od datih matematičkih funkcija, potrebno je napisati odvojenu
funkciju sa prefiksom t_ (t_sin za sin, t_cos za cos, t_pow2 za pow i t_sqrt za
sqrt) kako bi funkcije koje se prosljeđuju kao argumenti imale isto zaglavlje. Za njihovo
pojedinačno realizovanje dozvoljeno je korištenje biblioteke math.h.

Grafovi 9
A13 GRAFOVI
#include <stdio.h> void floyd(GRAF *g, double d[][MAX], int t[][MAX]) {
#include <stdlib.h> int i, j, k;
#include <math.h> for (k = 0; k<g->n; k++)
#define MAX 10 for (i = 0; i<g->n; i++)
for (j = 0; j<g->n; j++)
typedef struct g { if (d[i][j]>d[i][k] + d[k][j]) {
int n; d[i][j] = d[i][k] + d[k][j];
double nodes[MAX]; t[i][j] = t[k][j];
double ms[MAX][MAX]; }
} GRAF; }

double t_sin(double x){ void putanja(int i, int j, GRAF *g, int t[][MAX],
return sin(x); double(*f)(double))
} {
if (i == j)
double t_cos(double x){ printf("%.2lf ", (*f)(g->nodes[i]));
return cos(x); else if (t[i][j] == -1)
} printf("Nema putanje\n");
else
double t_pow(double x){ {
return x*x; putanja(i, t[i][j], g, t, f);
} printf("%.2lf ", (*f)(g->nodes[j]));
double t_sqrt(double x){ }
return sqrt(x); }
}
Grafovi 10
A13 GRAFOVI
int main(int argc, char **argv) { void init(GRAF *g, int t[][MAX]){
FILE *dat; GRAF g; int i, j;
int i, j, t[MAX][MAX], c1, c2; for (i = 0; i<g->n; i++)
double d[MAX][MAX]; for (j = 0; j<g->n; j++)
if (argc<3) return printf("Greska!"), 1; if (i == j || g->ms[i][j] == 0)
if (dat = fopen(argv[1], "r")) { t[i][j] = -1;
c1 = atoi(argv[2]); c2 = atoi(argv[3]); else
fscanf(dat, "%d", &g.n); t[i][j] = i;
for (i = 0; i<g.n; i++){ }
g.nodes[i] = 1.0 + i;
for (j = 0; j<g.n; j++){
fscanf(dat, "%lf", &g.ms[i][j]);
d[i][j] = i == j ? 0 : (g.ms[i][j] ? g.ms[i][j] : INFINITY);
}
}
init(&g, t);
floyd(&g, d, t);
D:\>najkraci_put.exe
printf("Putanja od cvora %d do cvora %d: ", c1,graf.txt
c2); 1 2
printf("\n sin(x): ");Putanja od cvora
putanja(c1-1, 1 do
c2-1, &g,cvora 2:
t, t_sin);
printf("\n cos(x): "); sin(x):
putanja(c1-1,
0.84c2-1,
0.14&g,
0.91t, t_cos);
printf("\n pow(x): "); cos(x):
putanja(c1-1,
0.54c2-1,
-0.99&g,-0.42
t, t_pow);
printf("\n sqrt(x): "); putanja(c1-1, c2-1, &g, t, t_sqrt);
pow(x): 1.00 9.00 4.00
}
sqrt(x):
else printf("Greska kod otvaranja 1.00 1.73 return
datoteke\n"); 1.41 0;
}
Grafovi 11
A13 GRAFOVI
Napisati program koji iz ulazne datoteke čiji je naziv argument komandne linije učitava
broj n koji predstavlja broj gradova. Potom, iz iste ulazne datoteke, program učitava nazive
n gradova (koji se nalaze u odvojenim linijama tekstualne datoteke). Poslije liste naziva
gradova u ulaznoj datoteci slijedi matrica susjednosti težinskog neusmjerenog grafa kojim
su predstavljeni gradovi i njihova povezanost. Program treba da pronađe najkraće
rastojanje između dva grada čiji se nazivi unose sa standardnog ulaza i ispiše ga na
standardnom izlazu zajedno sa svim gradovima na najkraćoj putanji. Neophodno je
implementirati odvojene funkcije za učitavanje podataka (grafa) iz datoteke i pronalaženje
najkraćeg rastojanja i najkraće putanje između zadata dva grada.
#include <stdio.h> void initT(GRAF *g, int t[][MAX])
#include <stdlib.h> {
#include <string.h> int i, j;
#include <math.h> for (i = 0; i<g->n; i++)
#define MAX 20 for (j = 0; j<g->n; j++)
if (i == j || g->ms[i][j] == 0)
typedef struct { int index; char* naziv; t[i][j] = -1;
} CVOR_GRAFA; else
t[i][j] = i;
typedef struct { int n; CVOR_GRAFA *nodes; }
double** ms;
} GRAF;

Grafovi 12
A13 GRAFOVI
char* readString(FILE* file) {
char *str; int ch;
size_t len = 0;
#define SIZE_INCREMENT 16
size_t size = SIZE_INCREMENT;
str = realloc(NULL, sizeof(char)*size);
if (!str) return str;
while (EOF != (ch = fgetc(file)) && ch != '\n') {
str[len++] = ch;
if (len == size) {
str = realloc(str, sizeof(char)*(size += SIZE_INCREMENT));
if (!str) return str;
}
}
#undef SIZE_INCREMENT
str[len++] = '\0';
return realloc(str, sizeof(char)*len);
}
int indexOfNode(GRAF g, char *naziv) {
int i;
for (i = 0; i < g.n; ++i)
if (!strcmp(g.nodes[i].naziv, naziv)) return i;
fprintf(stderr, "Grad ne postoji.");
exit(500);
return -1;}
Grafovi 13
A13 GRAFOVI
GRAF initG(FILE* file, double d[MAX][MAX], int t[][MAX]) {
int i, j; GRAF gr;
fscanf(file, "%d\n", &gr.n);
gr.nodes = malloc(sizeof(CVOR_GRAFA)*gr.n);
gr.ms = malloc(sizeof(double*)*gr.n);
for (i = 0; i < gr.n; ++i) {
gr.nodes[gr.nodes[i].index = i].naziv = readString(file);
gr.ms[i] = malloc(sizeof(double)*gr.n);
}
for (i = 0; i < gr.n; ++i)
for (j = 0; j < gr.n; ++j) {
fscanf(file, "%lf", &gr.ms[i][j]);
d[i][j] = i == j ? 0 : (gr.ms[i][j] ? gr.ms[i][j] : INFINITY);
}
initT(&gr, t);
return gr;
}
void freeG(GRAF *gr) {
int i;
for (i = 0; i < gr->n; ++i) {
free(gr->nodes[i].naziv); free(gr->ms[i]);
}
free(gr->nodes); free(gr->ms);
gr->ms = NULL; gr->nodes = NULL; gr->n = 0;
}
Grafovi 14
A13 GRAFOVI
void floyd(GRAF *g, double d[][MAX], int t[][MAX])
{
int i, j, k;
for (k = 0; k<g->n; k++)
for (i = 0; i<g->n; i++)
for (j = 0; j<g->n; j++)
if (d[i][j]>d[i][k] + d[k][j])
{
d[i][j] = d[i][k] + d[k][j];
t[i][j] = t[k][j];
}
}

void putanja(int i, int j, GRAF *g, int t[][MAX], int dest)


{
if (i == j)
printf("%s -> ", g->nodes[i].naziv);
else if (t[i][j] == -1)
printf("Nema putanje.");
else {
putanja(i, t[i][j], g, t, dest);
printf("%s", g->nodes[j].naziv);
dest != j ? printf(" -> ") : printf("");
}
}

Grafovi 15
A13 GRAFOVI
int main() {
FILE *dat; GRAF g;
int i, j, t[MAX][MAX], index_start, index_dest;
char *start, *dest;
double d[MAX][MAX];
if (dat = fopen("Cities.txt", "r")) {
g = initG(dat, d, t);
fclose(dat);
printf("Start: ");
start = readString(stdin);
printf("Odrediste: ");
dest = readString(stdin);
floyd(&g, d, t);
index_start = indexOfNode(g, start);
Start: Banjadest);
index_dest = indexOfNode(g, Luka
Odrediste:
printf("Najkraca ruta: "); Prijedor
Najkraca
putanja(index_start, ruta: Banja
index_dest, &g, t,Luka -> Prijedor
index_dest);
printf("\nDuzina: %.2lf 55.00
Duzina: km", d[index_start][index_dest]);
km
free(start); ...
free(dest); Start: Doboj
freeG(&g);
Odrediste: Gradiska
}
Najkraca
else printf("Greska ruta: Doboj
kod otvaranja -> Prnjavor -> Banja Luka -> Gradiska
datoteke\n");
return 0; Duzina: 150.00 km
}
Grafovi 16
A13 ZADACI ZA VJEŽBU
1. Napisati program koji iz ulazne datoteke čiji je naziv argument komandne linije
učitava broj n koji predstavlja broj gradova. Potom, iz iste ulazne datoteke, program
učitava nazive n gradova (koji se nalaze u odvojenim linijama tekstualne datoteke).
Poslije liste naziva gradova u ulaznoj datoteci slijedi matrica susjednosti težinskog
neusmjerenog grafa kojim su predstavljeni gradovi i njihova povezanost. Program
treba da pronađe najkraće rastojanje između dva grada čiji se nazivi unose sa
standardnog ulaza i ispiše ga na standardnom izlazu zajedno sa svim gradovima na
najkraćoj putanji. Neophodno je implementirati odvojene funkcije za učitavanje
podataka (grafa) iz datoteke i pronalaženje najkraćeg rastojanja i najkraće putanje
između zadata dva grada. Za određivanje najkraćeg puta koristiti kombinaciju
algoritama BFS i Dijkstra.

CitySearch.rar

Grafovi 17
A13 ZADACI ZA VJEŽBU
2. Neka je unaprijed definisana matrica susjednosti težinskog, usmjerenog grafa,
dimenzija NxN (pri tome je N konstanta definisana pretprocesorskom direktivom
#define). Težine su definisane kao podaci sa pokretnim zarezom, pri čemu se
garantuje da su težine pozitivne, te da je graf povezan. Napisati funkciju čiji je
prototip sljedeći:
void pronadji_putanje_i_sortiraj(double matrica[][N]).
Zadatak funkcije je da za svaki čvor grafa pronađe najkraću kružnu putanju do istoga.
Nakon toga izvršiti ispis na standardni izlaz čvorova sa dužinama kružnih putanja. Za
sve čvorove koji nemaju kružnu putanju dužina putanje je -1.

Grafovi 18

You might also like