1.1 Εισαγωγή 1. Ο ΑΤΔ ΓΡΑΦΗΜΑ Σε προηγούμενα κεφάλαια είδαμε γραμμικές δομές δεδομένων (στοίβα, ουρά, λίστα), στις οποίες κάθε στοιχείο μπορεί να έχει το πολύ ένα επόμενο και το πολύ ένα προηγούμενο, αλλά και μη γραμμική δομή (δένδρο), όπου κάθε στοιχείο μπορεί να έχει περισσότερα του ενός επόμενα στοιχεία αλλά το πολύ ένα προηγούμενο στοιχείο (ιεραρχική δομή). Η γενίκευση της ιεραρχικής δομής επιτυγχάνεται αν επιτραπεί σε κάθε στοιχείο να έχει περισσότερα του ενός προηγούμενα στοιχεία. Ένα γράφημα αποτελεί μια τέτοια δομή όπου κάθε στοιχείο μπορεί να μην έχει κανένα να έχει ένα ή να έχει πολλά προηγούμενα και επόμενα στοιχεία. Στην καθημερινότητα συναντάμε πολύ συχνά την έννοια του γραφήματος. Γράφημα μπορούμε να θεωρήσουμε ένα σύνολο τοποθεσιών που θέλουμε να επισκεφτούμε για παράδειγμα, με τις διαδρομές που ενώνουν τις τοποθεσίες αυτές. Οι λίστες και τα δένδρα πρακτικά αποτελούν πρακτικά υποσύνολα των γραφημάτων αφού μπορούν να αναπαραχθούν από αυτά. Σε πρακτικό επίπεδο στην πληροφορική, τα γραφήματα μπορούν να βοηθήσουν σε πολλούς τομείς, με εκτεταμένη χρήση να υπάρχει στα δίκτυα όπως είναι λογικό αλλά και στο χώρο του web, σε ιστοσελίδες όπου αντιστοιχεί κάθες κόμβος του γραφήματος με μια ιστοσελίδα και κάθε ακμή σε μια υπερσύνδεση από μια σελίδα σε μια άλλη. 1.2 Ορισμός Ο ΑΤΔ Γράφημα ορίζεται ως μια συλλογή ομοίων αντικειμένων με δικτυακή δομή, εκ των οποίων το καθένα μπορεί να συνδέεται με όσα άλλα από τα υπόλοιπα χρειάζεται, με αμφίδρομη ή μονόδρομη σχέση. 1.2.1 Δεδομένα Ο ΑΤΔ Γράφημα G (V, E) αποτελείται από ένα σύνολο V, μια σχέση E και ένα σύνολο πράξεων που επιδρούν πάνω στα 2 αυτά σύνολα. Το V είναι το σύνολο των κορυφών του γραφήματος ενώ το E το σύνολο των ακμών του γραφήματος. 1.2.2 Πράξεις Οι βασικές πράξεις του ΑΤΔ Γράφημα είναι: Graph_dimioyrgia: Δημιουργεί ένα κενό γράφημα. Graph_geitoniki: ελέγχει αν 2 κόμβοι του γραφήματος συνδέονται μεταξύ τους με ακμή, εκτός και αν οι κόμβοι ή ένας από τους κόμβους δεν υπάρχει. Graph_enimerosi: αλλάζει τα δεδομένα που είναι αποθηκευμένα σε ένα κόμβο του γραφήματος, εκτός και αν ο κόμβος δεν υπάρχει. Graph_anaktisi: επιστρέφει τα δεδομένα που είναι αποθηκευμένα σε ένα κόμβο του γραφήματος, εκτός και αν κόμβος δεν υπάρχει. Graph_eisagogi_korifis: εισάγει ένα νέο κόμβο στην λίστα των κόμβων του γραφήματος, εκτός και αν δεν υπάρχει χώρος (για τις υλοποιήσεις με λίστα κορυφών και πίνακα). Δ.Μήλιος 1
Graph_diagrafi_korifis: διαγράφει ένα κόμβο από την λίστα των κόμβων του γραφήματος, εκτός και αν δεν υπάρχει ο κόμβος. Graph_eisagogi_akmis: εισάγει μια ακμή μεταξύ 2 κόμβων στο γράφημα, εκτός και αν υπάρχει ήδη ή δεν υπάρχουν οι κόμβοι ή ένας από τους 2 κόμβους δεν υπάρχει. Graph_diagrafi_akmis: διαγράφει μια ακμής μεταξύ 2 κόμβων από το γράφημα, εκτός και αν δεν υπάρχει η ακμή ή δεν υπάρχουν οι κόμβοι ή δεν υπάρχει ένας από τους 2 κόμβους. 1.3 Υλοποιήσεις Θα παρουσιαστούν 3 τρόποι υλοποίησης του ΑΤΔ Γράφημα, με πίνακα, με λίστα ακμών και τέλος με λίστα κορυφών. Διευκρινίζεται ότι και στις 3 υλοποιήσεις υπάρχουν υλοποιημένες στα αρχεία Δοκιμής της καθεμιάς υλοποίησης συναρτήσεις για αναζήτηση κατά βάθος και κατά πλάτος του γραφήματος. 1.3.1 Υλοποίηση 1 η : Υλοποίηση μη Κατευθυνόμενο Γράφημα χωρίς βάρη με πίνακα Σε αυτή την υλοποίηση χρησιμοποιείται μια δομή που περιέχει ένα δισδιάστατο πίνακα για το ρόλο του γειτονικού πίνακα, ένα μονοδιάστατο πίνακα τύπου στοιχείου γραφήματος που αντιστοιχεί στους κόμβους του γραφήματος και αποθηκεύει ότι δεδομένα θέλουμε να βρίσκονται σε κάθε κόμβο και μια μεταβλητή τύπου int που κρατάει τον αριθμό των κόμβων που βρίσκονται στο γράφημα ανά πάσα στιγμή. 1.3.1.1 Αρχεία Διεπαφής-Υλοποίησης Στο αρχείο Διεπαφής ορίζεται η δομή που επεξηγήθηκε από πάνω αλλά κυρίως εντοπίζεται το include του τύπου στοιχείου γραφήματος το οποίο δεν περιλαμβάνει συγκεκριμένο μονοπάτι που να προσδιορίζει το αρχείο του τύπου στοιχείου γραφήματος αλλά περιγράφει τον ρόλο του συγκεκριμένου include. Τέλος δηλώνεται και ο μέγιστος αριθμός στοιχείων του γραφήματος. Προφανώς υπάρχουν και οι δηλώσεις των συναρτήσεων-πράξεων του γραφήματοςπράγμα αυτονόητο για ένα αρχείο Διεπαφής, όμως καλό είναι να διευκρινιστεί πως στην συγκεκριμένη υλοποίηση υπάρχει μια extra συνάρτηση-πράξη που δεν έχει αναφερθεί στις βασικές πράξεις και αφορά μόνο την υλοποίηση με πίνακα (δεν έχει υλοποιηθεί στις άλλες 2 υλοποιήσεις). Αυτή η συνάρτηση είναι η Graph_metavatiko_graphima η οποία παίρνει παραμέτρους 2 γραφήματα και κάνει το δεύτερο μεταβατικό γράφημα του πρώτου. Ακολουθεί ο κώδικας του αρχείου Διεπαφής: #ifndef GARRAY #define GARRAY #include "to antistoixo.h typou stoixeiou" /*edo analoga tin efarmogi i to test tou tipou stoixeiou mpainei to antoistixo.h tou tipou stoixeiou */ Δ.Μήλιος 2
/*dhlwseis typwn*/ #define PLITHOS 100 typedef int typos_pinaka[plithos][plithos]; typedef TStoixeioyGraph data_arr[plithos]; typedef struct { typos_pinaka geit_pin; /*pinakas geitonikon koryfon*/ data_arr dedomena; /*dedomena kathe korifis tou grafhmatos*/ int ar_koryfon; graphima; /*dhlwseis synarthsewn*/ /*dhmioyrgia*/ void Graph_dimiourgia(graphima *G); /*prakseis elegxoy*/ int Graph_geitoniki(graphima G, int p, int q, int *error); /*prakseis pros8eshs/apomakrynshs*/ void Graph_eisagogi_akmis(graphima *G, int p, int q, int *error); int Graph_diagrafi_akmis(graphima *G, int p, int q, int *error); void Graph_eisagogi_korifis(graphima *G, int *p,tstoixeioygraph stoixeio, int *error); void Graph_diagrafi_korifis(graphima *G, int p, int *error); void Graph_metavatiko_graphima(graphima *A, graphima *P); /*prakseis dedomenwn*/ void Graph_enimerosi(graphima *G, int p, TStoixeioyGraph stoixeio, int *error); void Graph_anaktisi(graphima G, int p, TStoixeioyGraph *val, int *error); #endif /*#ifndef GARRAY */ Ακολουθεί ο κώδικας του αρχείου Υλοποίησης: #include <stdio.h> #include <stdlib.h> #include "Garray.h" /*orismos synarthsewn*/ Δ.Μήλιος 3
void Graph_dimiourgia(graphima *G) {/* Pro: kamia * Meta: Dhmioyrgia enos kenoy grafhmatos */ G->ar_koryfon=0; int Graph_geitoniki(graphima G, int p, int q, int *error) {/* Pro: Oi koryfes anhkoyn sto synolo twn koryfwn toy grafhmatos G * Meta: An yparxei akmh apo thn koryfh p sthn q tote h synarthsh epistrefei 1 * diaforetika epistrefei -1 */ *error=0; if ( (p<0) (p>g.ar_koryfon-1) (q<0) (q>g.ar_koryfon-1) )//ektos orion { *error=1; G p->q*/ return -1; return (G.geit_pin[p][q]); /*den apaiteitai allagh gia katey8ynomeno Δ.Μήλιος 4
void Graph_eisagogi_akmis(graphima *G, int p, int q, int *error) {/* Pro: Oi koryfes q,p anhkoyn sto synolo twn koryfwn toy grafhmatos G kai h akmh * (p,q) den anhkei sto mh katey8hnomeno grafhma *G * Meta: An h (p,q) den einai akmh toy grafhmatos tote eisagetai sto *G * diaforetika epistrefei error=1 */ *error=0; if ( (p<0) (p>g->ar_koryfon-1) (q<0) (q>(g->ar_koryfon-1)) )//ektos orion { *error=1; return; if (Graph_geitoniki(*G,p,q,error)) //an iparxei idi akmi metaksi auton ton koryfon { *error=1; G p->q*/ return; { *error=0; G->geit_pin[p][q] = 1; G->geit_pin[q][p] = 1;/*afaireitai gia thn ylopoihsh katey8ynomenoy Δ.Μήλιος 5
int Graph_diagrafi_akmis(graphima *G, int p, int q, int *error) {/* Pro: H (p,q) einai akmh toy mh katey8ynomenoy grafhmatos *G * Meta: An h (p,q) einai akmh toy grafhmatos tote diagrafetai h (p,q) * apo to *G kai h synarthsh epistrefei 1, diaforetika epistrefei 0 */ *error=0; if ( (p<0) (p>(g->ar_koryfon-1)) (q<0) (q>(g->ar_koryfon-1)) ) { *error=1; return 0; if (!Graph_geitoniki(*G,p,q,error)) G p->q*/ return 0; { *error=0; G->geit_pin[p][q] = 0; G->geit_pin[q][p] = 0;/*afaireitai gia thn ylopoihsh katey8ynomenoy return 1; void Graph_eisagogi_korifis(graphima *G, int *p,tstoixeioygraph stoixeio, int *error) {/* Pro: to grafhma *G den exei megisto plh8os koryfwn * Meta: Eisagetai sto grafhma *G h koryfh G->arkrfon xwris ayth na synde8ei me tis * alles koryfes, o *p ginetai isos me aythn */ int i; *error=0; if (G->ar_koryfon == PLITHOS) //ksepernaei to megisto plithos stoixeion { *error=1; return; { (G->ar_koryfon)++; *p = G->ar_koryfon -1; /*Teleytaia koryfh*/ for (i=0;i<=*p;i++) { G->geit_pin[*p][i]= 0; /*Nea grammh*/ G->geit_pin[i][*p]= 0; /*Nea sthlh*/ TSgraph_setValue(&(G->dedomena[*p]), stoixeio); Δ.Μήλιος 6
void Graph_diagrafi_korifis(graphima *G, int p, int *error) {/* Pro: H koryfh p anhkein sto synolo twn koryfwn toy grafhmatos *G * Meta: An h koryfh p anhkein sto synolo twn koryfwn toy grafhmatos *G, * tote ayth diagrafetai ka8ws kai oles oi akmes poy thn periexoyn. * Meta apo aytes tis diagrafes to grafhma exei ws koryfes toy tis * 0,1,..., G->arkrfon-1 */ int i,j; *error=0; if ( (p<0) (p>(g->ar_koryfon-1)) )//ektos orion { *error=1; return; { /*metakinhsh ths i+1 grammhs pros ta panw*/ for (i=p;i<=(g->ar_koryfon - 2);i++) for (j=0;j<=(g->ar_koryfon - 1);j++) G->geit_pin[i][j] = G->geit_pin[i+1][j]; /*metakinhsh ths i+1 sthlhs pros ta aristera*/ for (i=p;i<=(g->ar_koryfon - 2);i++) for (j=0;j<=(g->ar_koryfon- 2);j++) G->geit_pin[j][i] = G->geit_pin[j][i+1]; /*metakinhsh twn dedomenwn pros ta aristera*/ for (i=p;i<=(g->ar_koryfon- 2);i++) TSgraph_setValue(&(G->dedomena[i]), G->dedomena[i+1]); G->ar_koryfon--; Δ.Μήλιος 7
void Graph_metavatiko_graphima(graphima *A,graphima *P) {/* Pro: Dhmioyrgia toy grafhmatos A * Meta: To grafhma P einai to metabatiko grafhma toy A */ int i,j,k; typos_pinaka PP; for(i=0;i<=(a->ar_koryfon-1);i++) for(j=0;j<=(a->ar_koryfon-1);j++) (P->geit_pin)[i][j]=(A->geit_pin)[i][j]; for(k=0;k<=(a->ar_koryfon-1);k++) { for(i=0;i<=(a->ar_koryfon-1);i++) for(j=0;j<=(a->ar_koryfon-1);j++) PP[i][j] = (P->geit_pin)[i][j]; for(i=0;i<=(a->ar_koryfon-1);i++) if (PP[i][k]) for(j=0;j<=(a->ar_koryfon-1);j++) if (PP[k][j]) (P->geit_pin)[i][j] = 1; void Graph_enimerosi(graphima *G, int p, TStoixeioyGraph stoixeio, int *error) {/* Pro: Dhmioyrgia toy grafhmatos G * Meta: Enimerosi tis korifis pou deixnei to "p" me tin timi tou "stoixeio" */ *error=0; if ( (p<0) (p>g->ar_koryfon-1) ) //ektos orion { *error=1; return; TSgraph_setValue(&(G->dedomena[p]), stoixeio); 1.3.1.2 Αρχεία Δοκιμής Στα αρχεία δοκιμής περιλαμβάνεται το αρχείο main που χρησιμοποιείται ως αρχείο test για τις πράξεις της ATΔ Γραφήμα. Στο αρχείο main περιλαμβάνονται και οι συναρτήσεις: Δ.Μήλιος 8
episkepsi, vathos, diadromi_v, platos, diadromi_p. Έχει αναφερθεί ήδη πιο πάνω πως και οι 3 Υλοποιήσεις που υπάρχουν σε αυτό το κεφάλαιο δίνουν την δυνατότητα στο χρήστη να κάνει αναζήτηση κατά βάθος και κατά πλάτος, για αυτό το σκοπό υπάρχουν οι 4 τελευταίες συναρτήσεις ενώ η episkepsi απλά εκτυπώνει τα περιεχόμενα του κόμβου του οποίου τον δείκτη παίρνει παράμετρο. Όμως για να υλοποιηθεί συγκεκριμένα η αναζήτηση κατά πλάτος χρησιμοποιούνται και πράξεις του ΑΤΔ Ουρά και συγκεκριμένα στις 3 Υλοποίησεις που παρουσιάζονται γίνεται χρήση των πράξεων της ουράς με κενό (gap). Έτσι στα αρχεία Δοκιμής περιλαμβάνονται και τα αρχεία Υλοποίησης-Διεπαφής του τύπου στοιχείου Ουράς (int) και τα αρχεία Υλοποίησης-Διεπαφής της υλοποίησης της ουράς με κενό (για τον κώδικα των αρχείων αυτών ανατρέχτε στο 4 ο κεφάλαιο στις ενότητες 4. 3. 1 και 4. 3. 4) Ακολουθεί ο κώδικας του αρχείου δοκιμής: void print_options(void); void episkepsi(graphima G,int i); void vathos(graphima G); void diadromi_v(graphima G, int i,int episk[]); void platos(graphima G); void diadromi_p(graphima G, int k,int episk[]); TOuras oura_korifon; int main(void) { int option, i, j,created,out_err; graphima G, A; int p, q, error, apot; TStoixeioyGraph x; error=0; created=0; do{ print_options(); scanf("%d", &option); switch(option) {case 1: case 2: Graph_dimiourgia(&G); created=1; printf("to grafhma dimiourgithike!\n"); { printf("\nden uparxei grafima gia na elegxthei ama iparxoun geitonikes korifes!\n"); Δ.Μήλιος 9
tou!\n"); printf("dwse ton ari8mo ths prwths koryfhs: "); scanf("%d", &p); printf("dwse ton ari8mo ths deyterhs koryfhs: "); scanf("%d", &q); apot=graph_geitoniki(g, p, q, &error); if(error) { printf("\nerror! La8os ari8mos koryfhs!\n"); case 3: { if(apot) printf("oi koryfes einai geitonikes!\n"); printf("oi koryfes DEN einai geitonikes!\n"); { printf("\nden uparxei grafima gia na enimerothei kapoia koryfh printf("dwse ton ari8mo ths koryfhs pou 8es na enhmerwseis: "); scanf("%d", &p); printf("dwse ena stoixeio gia na eisax8ei sthn koryfh: "); out_err=tsgraph_readvalue(stdin,&x); if(!out_err) {printf("\n error stin readvalue!\n"); Graph_enimerosi(&G, p, x, &error); if(error) printf("\nerror! La8os ari8mos koryfhs!\n"); printf("h koryfh enhmerothike!\n"); case 4: { printf("\nden uparxei grafima gia na parthoun ta dedomena apo kapoia koryfh tou!\n"); printf("dwse ton ari8mo ths koryfhs pou 8es ta dedomena: "); Δ.Μήλιος 10
scanf("%d", &p); Graph_anaktisi(G, p, &x, &error); if(error) printf("\nerror! La8os ari8mos koryfhs!\n"); { out_err=tsgraph_writevalue(stdout,x); if(out_err <0) {printf("\n error stin writevalue!\n"); case 5: { printf("\nden uparxei grafima gia na diagrafei kapoia koryfh tou!\n"); printf("dwse ton ari8mo ths koryfhs pou 8es na diagrapseis: "); scanf("%d", &p); Graph_diagrafi_korifis(&G, p, &error); if(error) printf("\nerror! La8os ari8mos koryfhs!\n"); printf("h koryfh diagrafhke!\n"); case 6: { printf("\nden uparxei grafima gia na diagrafei kapoia akmh tou!\n"); printf("dwse ton ari8mo ths 1hs koryfhs ths akmhs pros diagrafh: "); scanf("%d", &p); printf("dwse ton ari8mo ths 2hs koryfhs ths akmhs pros diagrafh: "); scanf("%d", &q); apot=graph_diagrafi_akmis(&g, p, q, &error); if(error) {printf("\nerror! La8os ari8mos koryfhs!\n"); { if(apot) Δ.Μήλιος 11
!\n");!\n"); "); "); printf("h akmh diagrafhke!\n"); printf("den yparxei ayth h akmh!\n"); case 7: { printf("\nden uparxei grafima gia na eisaxthei kapoia koryfh printf("dwse ena stoixeio gia na eisax8ei sth nea koryfh: "); out_err=tsgraph_readvalue(stdin,&x); if(!out_err) { printf("\n error stin readvalue!\n"); Graph_eisagogi_korifis(&G, &p,x,&error); if(error) printf("\nerror! Den yparxei mnhmh!\n"); { printf("eishx8h h koryfh me dedomena "); out_err=tsgraph_writevalue(stdout,x); if(out_err <0) {printf("\n error stin writevalue!\n"); case 8: { printf("\nden uparxei grafima gia na eisaxthei kapoia akmh printf("dwse ton ari8mo ths 1hs koryfhs ths akmhs pros eisagwgh: scanf("%d", &p); printf("dwse ton ari8mo ths 2hs koryfhs ths akmhs pros eisagwgh: scanf("%d", &q); Graph_eisagogi_akmis(&G, p, q, &error); if(error) Δ.Μήλιος 12
hdh!\n"); case 9: printf("\nerror! La8os ari8mos koryfhs 'h h akmh yparxei printf("h akmh eishx8h!\n"); { printf("\nden uparxei grafima gia na dimiourgithei metavatiko grafima pano se auto!\n"); G\n"); Graph_metavatiko_graphima(&G, &A); printf("\nto grafhma A einai twra to metavatiko grafhma toy case 10: { printf("\nden uparxei grafima gia na ektipothei o geitonikos tou pinakas!\n");!\n");!\n"); for(i=0;i<g.ar_koryfon;i++) { printf("\n"); case 11: for(j=0;j<g.ar_koryfon;j++) printf("%d ", G.geit_pin[i][j]); { printf("\nden uparxei grafima gia ginei anazitisi kata vathos vathos(g); case 12: { printf("\nden uparxei grafima gia ginei anazitisi kata platos platos(g); Δ.Μήλιος 13
while(option); return 0; void print_options(void) { printf("\n\n1. Dhmioyrgia grafhmatos\n\ 2. Elegxos geitonikwn koryfwn\n\ 3. Enhmerwsh dedomenwn koryfhs\n\ 4. Anakthsh dedomenwn koryfhs\n\ 5. Diagrafh koryfhs\n\ 6. Diagrafh akmhs\n\ 7. Eisagwgh koryfhs\n\ 8. Eisagwgh akmhs\n\ 9. Dhmioyrgia metavatikoy grafhmatos\n\ 10.Ektypwsh geitonikou pinaka\n\ 11:Anazhthsh prwta kata ba8os\n\ 12:Anazhthsh prwta kata platos\n\ Dwste thn epilogh sas(1-12, 0 gia eksodo):"); void episkepsi(graphima G,int i) { int error; TStoixeioyGraph x; Graph_anaktisi(G, i, &x, &error); TSgraph_writeValue(stdout,x); /*kata ba8os anazhthsh*/ void vathos(graphima G) {/* Pro: Dhmioyrgia toy grafhmatos G * Meta: H synarthsh diadromi paragei thn prwta kata ba8os anazhthsh twn koryfwn */ int episkeftike[plithos]; int i; for(i=0;i<=g.ar_koryfon-1;i++) episkeftike[i] = 0; for (i=0;i<=g.ar_koryfon-1;i++) if (!episkeftike[i]) Δ.Μήλιος 14
diadromi_v(g,i,episkeftike); void diadromi_v(graphima G, int i,int episk[]) {/* Pro: i einai mia koryfh toy grafhmatos * Meta: H episkepsh ths koryfhs i kai twn geitonikwn ths exei teleiwsei me thn * anazhthsh prwta kata ba8os. */ int j,error; error=0; episkepsi(g,i); /*episkepsh ths i koryfhs*/ episk[i]=1; for(j=0;j<=g.ar_koryfon-1;j++) if (Graph_geitoniki(G,i,j,&error) && (!episk[j])) diadromi_v(g,j,episk); void platos(graphima G) {/* Pro: Dhmioyrgia toy grafhmatos G * Meta: H synarthsh diadromi paragei thn prwta kata platos anazhthsh twn koryfwn */ int episkeftike[plithos]; int i; for(i=0;i<=g.ar_koryfon-1;i++) episkeftike[i] = 0; Oyra_dimiourgia(&oura_korifon); for (i=0;i<=g.ar_koryfon-1;i++) if (!episkeftike[i]) diadromi_p(g,i,episkeftike); void diadromi_p(graphima G, int k,int episk[]) {/* Pro: i einai mia koryfh toy grafhmatos * Meta: Ektelesthke h prwta kata platos * diadromh h opoia arxise apo thn koryfh k toy grafhmatos */ int w,i, error; error=0; episk[k] = 1; Δ.Μήλιος 15
Oyra_prosthesi(&oura_korifon,k,&error); while (!Oyra_keni(oura_korifon)) { Oyra_apomakrynsh(&oura_korifon,&i,&error); episkepsi(g,i); for(w=0;w<=g.ar_koryfon-1;w++) if (Graph_geitoniki(G,i,w,&error) && (!episk[w])) { episk[w] = 1; Oyra_prosthesi(&oura_korifon,w,&error); ενώ τα αρχεία Διεπαφής-Υλοποίησης, εκτός πάντα του path για τον τύπο στοιχείου, ίδια με τα πρότυπα αρχεία. 1.3.1.3 Εφαρμογές Η μόνη εφαρμογή που θα δούμε για την υλοποίηση με πίνακα είναι αυτή της εφαρμογής του αλγορίθμου του Dijkstra. 1.3.1.3.1 Dijkstra O Dijkstra εφαρμόζεται σε κατευθυνόμενο γράφημα με βάρη οπότε έχουν τροποποιηθεί όπου χρειάζεται οι συναρτήσεις πράξεις του ΑΤΔ Γράφημα για να υποστηρίξουν το ότι γίνεται αναφορά σε κατευθυνόμενο γράφημα και με βάρη (η υλοποίηση ήταν μη κατευθυνόμενο και χωρίς βάρη). Ο αλγόριθμος του Dijkstra δηλώνεται και υλοποιείται ως συνάρτηση στο αρχείο main της εφαρμογής. Η εφαρμογή αυτή κάνει χρήση και του ΑΤΔ Σύνολο που δεν έχει μελετηθεί στην παρούσα εργασία αλλά κατ εξαίρεση για αυτή την εφαρμογή χρησιμοποιούνται τα αρχεία Διεπαφής-Υλοποίησης της. Ακολουθεί ο κώδικας του αρχείου Εφαρμογής: #include <stdio.h> #include "Garray_Kat.h" #include "TStoixeioyGraph.h" #include "Set.h" void print_options(void); void Dijkstra(graphima G,int korifi,int * error); #define INFINITY 20000 int main(void) { int option, i, j,out_err,created; typos_varoys var; Δ.Μήλιος 16
graphima G, A; int p, q, error, apot; TStoixeioyGraph x; created=0; error=0; var=0; do{ print_options(); scanf("%d", &option); switch(option) {case 1: case 2: Graph_dimiourgia(&G); created=1; printf("to grafhma dimiourgithike!\n"); { printf("\nden uparxei grafima gia na elegxthei ama iparxoun geitonikes korifes!\n"); tou!\n"); printf("dwse ton ari8mo ths prwths koryfhs: "); scanf("%d", &p); printf("dwse ton ari8mo ths deyterhs koryfhs: "); scanf("%d", &q); apot=graph_geitoniki(g, p, q, &error); if(error) printf("\nerror! La8os ari8mos koryfhs!\n"); { if(apot) case 3: printf("oi koryfes einai geitonikes!\n"); printf("oi koryfes DEN einai geitonikes!\n"); { printf("\nden uparxei grafima gia na enimerothei kapoia koryfh printf("dwse ton ari8mo ths koryfhs pou 8es na enhmerwseis: "); Δ.Μήλιος 17
scanf("%d", &p); printf("dwse ena stoixeio gia na eisax8ei sthn koryfh: "); out_err=tsgraph_readvalue(stdin,&x); if(!out_err) { printf("\n error stin readvalue!\n"); Graph_enimerosi(&G, p, x, &error); if(error) printf("\nerror! La8os ari8mos koryfhs!\n"); case 4: printf("h koryfh enhmerothike!\n"); { printf("\nden uparxei grafima gia na parthoun ta dedomena apo kapoia koryfh tou!\n"); tou!\n"); printf("dwse ton ari8mo ths koryfhs pou 8es ta dedomena: "); scanf("%d", &p); Graph_anaktisi(G, p, &x, &error); if(error) printf("\nerror! La8os ari8mos koryfhs!\n"); {out_err=tsgraph_writevalue(stdout,x); if(out_err <0) { printf("\n error stin writevalue!\n"); case 5: { printf("\nden uparxei grafima gia na diagrafei kapoia koryfh printf("dwse ton ari8mo ths koryfhs pou 8es na diagrapseis: "); scanf("%d", &p); Graph_diagrafi_korifis(&G, p, &error); if(error) Δ.Μήλιος 18
!\n"); "); ");!\n"); printf("\nerror! La8os ari8mos koryfhs!\n"); printf("h koryfh diagrafhke!\n"); case 6: { printf("\nden uparxei grafima gia na diagrafei kapoia akmh tou printf("dwse ton ari8mo ths 1hs koryfhs ths akmhs pros diagrafh: scanf("%d", &p); printf("dwse ton ari8mo ths 2hs koryfhs ths akmhs pros diagrafh: scanf("%d", &q); apot=graph_diagrafi_akmis(&g, p, q, &error); if(error) printf("\nerror! La8os ari8mos koryfhs!\n"); {if(apot) printf("h akmh diagrafhke!\n"); printf("den yparxei ayth h akmh!\n"); case 7: { printf("\nden uparxei grafima gia na eisaxthei kapoia koryfh printf("dwse ena stoixeio gia na eisax8ei sth nea koryfh: "); out_err=tsgraph_readvalue(stdin,&x); if(!out_err) { printf("\n error stin readvalue!\n"); Graph_eisagogi_korifis(&G, &p,x,&error); if(error) printf("\nerror! Den yparxei mnhmh!\n"); { printf("eishx8h h koryfh me dedomena "); Δ.Μήλιος 19
!\n"); "); "); hdh!\n"); case 8: out_err=tsgraph_writevalue(stdout,x); if(out_err <0) {printf("\n error stin writevalue!\n"); { printf("\nden uparxei grafima gia na eisaxthei kapoia akmh printf("dwse ton ari8mo ths 1hs koryfhs ths akmhs pros eisagwgh: scanf("%d", &p); printf("dwse ton ari8mo ths 2hs koryfhs ths akmhs pros eisagwgh: scanf("%d", &q); printf("dwse to baros ths akmhs pros eisagwgh: "); scanf("%d", &var); Graph_eisagogi_akmis(&G, p, q, var, &error); if(error) printf("\nerror! La8os ari8mos koryfhs 'h h akmh yparxei printf("h akmh eishx8h!\n"); case 9: { printf("\nden uparxei grafima gia na dimiourgithei metavatiko grafima pano se auto!\n"); G!\n"); Graph_metavatiko_graphima(&G, &A); printf("\nto grafhma A einai twra to metavatiko grafhma toy case 10: { printf("\nden uparxei grafima gia na ektipothei o geitonikos tou pinakas!\n"); Δ.Μήλιος 20
for(i=0;i<g.ar_koryfon;i++) { printf("\n"); case 11: for(j=0;j<g.ar_koryfon;j++) printf("%3d ", G.geit_pin[i][j]); { printf("\nden uparxei grafima gia na efarmostei se kapoia korifi tou o Dijkstra!\n"); printf("dwse ton ari8mo ths koryfhs sthn opoia tha efarmostei o Dijkstra: "); scanf("%d", &p); Dijkstra(G,p,&error); if(error) while(option); return 0; printf("\nerror! La8os ari8mos koryfhs!\n"); void print_options(void) { printf("\n\n1. Dhmioyrgia grafhmatos\n\ 2. Elegxos geitonikwn koryfwn\n\ 3. Enhmerwsh dedomenwn koryfhs\n\ 4. Anakthsh dedomenwn koryfhs\n\ 5. Diagrafh koryfhs\n\ 6. Diagrafh akmhs\n\ 7. Eisagwgh koryfhs\n\ 8. Eisagwgh akmhs\n\ 9. Dhmioyrgia metavatikoy grafhmatos\n\ 10.Ektypwsh geitonikou pinaka\n\ 11.Efarmogh algori8moy Dijkstra\n\n\ Dwste thn epilogh sas(1-11, 0 gia eksodo):"); Δ.Μήλιος 21
void Dijkstra(graphima G,int korifi,int * error) { /* * Pro: To G einai katey8ynomeno grafhma me barh * Meta: Eyresh toy syntomoteroy monopatipy apo thn koryfh 0 toy grafhmatos * G pros ka8e allh koryfh toy kai epistrofh toy apotelesmatos ston */ * pinaka D typos_synolou S; /*to synolo eidikwn koryfwn*/ int i,j,w; int elaxisti_apostasi, apost_w_j; int apostasi[plithos]; int monopati[plithos]; w=infinity; *error=0; if ( (korifi<0) (korifi>g.ar_koryfon-1) ) { *error=1; return; ESdimiourgia(S); ESeisagogi(korifi,S); /*Arxikes times gia ta syntomotera monopatia efoson yparxoyn akmes apo thn koryfh 0*/ for(j=0;j<=g.ar_koryfon-1 ;j++) { if(j!=korifi) {if (G.geit_pin[korifi][j] == 0) { { apostasi[j] = INFINITY; monopati[j] = -1; apostasi[j] = G.geit_pin[korifi][j]; monopati[j] = korifi; Δ.Μήλιος 22
for(i=0;i<=g.ar_koryfon-1;i++) { if(i!=korifi) {/*epilogh mias koryfhs w apo to V-S tetoia wste apostasi[w]=min*/ elaxisti_apostasi = INFINITY; for(j=0,j!=korifi;j<=g.ar_koryfon-1;j++) { if(j!=korifi) { if ((!ESmelos(j,S))&&(0<apostasi[j])&&(apostasi[j]<elaxisti_apostasi)) { { elaxisti_apostasi = apostasi[j]; w = j; /*pros8esh ths w sto S*/ if(eseisagogi(w,s)) /*enhmerwsh twn timwn gia ton pinaka apostasi*/ for(j=0,j!=korifi;j<=g.ar_koryfon-1;j++) { if(j!=korifi) { if(g.geit_pin[w][j]==0) apost_w_j=infinity; apost_w_j=g.geit_pin[w][j]; if ((!ESmelos(j,S))&&((apostasi[w]+apost_w_j)<apostasi[j])) { apostasi[j] = apostasi[w]+apost_w_j; monopati[j] = w; printf("\n\neyresh syntomoteroy monopatioy"); printf("\nkoryfh-mhkos Monopatioy-Prohgoymenh\n"); for(i=0;i<=g.ar_koryfon-1;i++) Δ.Μήλιος 23
{ if(i!=korifi) printf("%6d %17d %11d\n",i,apostasi[i],monopati[i]); Ακολουθεί ο κώδικας του αρχείου Διεπαφής του ΑΤΔ Σύνολο: #ifndef SET #define SET /*dhlwseis typwn*/ #define min_stoixeio 1 #define max_stoixeio 100 #define megisto_plithos max_stoixeio-min_stoixeio+1 typedef int typos_synolou[megisto_plithos]; /*dhlwseis synarthsewn*/ void ESdimiourgia (typos_synolou synolo); void ESkatholiko (typos_synolou synolo); int ESeisagogi (int stoixeio, typos_synolou synolo); int ESdiagrafi (int stoixeio, typos_synolou synolo); int ESmelos (int stoixeio, typos_synolou synolo); int ESkeno_synolo int ESisa_synola int ESyposynolo (typos_synolou synolo); (typos_synolou s1, typos_synolou s2); (typos_synolou s1, typos_synolou s2); void ESenosi_synolou enosi); void EStomi_synolou tomi); (typos_synolou s1, typos_synolou s2, typos_synolou (typos_synolou s1, typos_synolou s2, typos_synolou void ESdiafora_synolou(typos_synolou s1, typos_synolou s2, typos_synolou diafora); #endif /*#ifndef SET */ Ακολουθεί ο κώδικας του αρχείου Υλοποίησης του ΑΤΔ Σύνολο: #include <stdio.h> Δ.Μήλιος 24
#include <stdlib.h> #include "Set.h" /*orismos synarthsewn*/ /**************************************************************************** ** Skopos: Dhmioyrgia synolwn ***************************************************************************** */ void ESdimiourgia(typos_synolou synolo) /*Dhmioyrgei ena keno synolo*/ { int i; for (i=min_stoixeio;i<=max_stoixeio;i++) ESdiagrafi(i, synolo); void ESkatholiko(typos_synolou synolo) /*Dhmioyrgei to ka8oliko synolo*/ { int i; for (i=min_stoixeio;i<=max_stoixeio;i++) ESeisagogi(i,synolo); /**************************************************************************** ** Skopos : Prakseis panw sto synolo Dexontai : ena stoixeio kai ena synolo Epistrefoyn : >0 (true) sthn periptwsh epityxias kai 0 diaforetika ***************************************************************************** */ int ESeisagogi(int stoixeio, typos_synolou synolo) /*Eisagwgh enos stoixeioy sto synolo*/ { if ( ( min_stoixeio<= stoixeio )&&( stoixeio<=max_stoixeio ) ) { synolo[stoixeio-min_stoixeio]=1; return 1; Δ.Μήλιος 25
return 0; int ESdiagrafi(int stoixeio, typos_synolou synolo) /*Diagrafh enos stoixeioy apo to synolo*/ { if ( (min_stoixeio <= stoixeio) && (stoixeio <= max_stoixeio) ) { synolo[stoixeio-min_stoixeio]=0; return 1; return 0; int ESmelos(int stoixeio, typos_synolou synolo) /*Elegxei an ena stoixeio einai melos toy synoloy*/ { if ( (min_stoixeio <= stoixeio) && (stoixeio <= max_stoixeio) ) return synolo[stoixeio-min_stoixeio]; return 0; /**************************************************************************** ** Skopos Dexontai : synola Epistrefoyn : Sxeseis, elegxoi synolwn : 1(true)/0(false) ***************************************************************************** */ int ESkeno_synolo(typos_synolou synolo) /*Elexgei an ena synolo einai keno*/ { int i; for(i = min_stoixeio; i<=max_stoixeio; i++) { if (ESmelos(i,synolo)) return 0; return 1; Δ.Μήλιος 26
int ESisa_synola(typos_synolou s1, typos_synolou s2) /*Elegxei an dyo synola einai isa*/ { int i; for(i = min_stoixeio; i<=max_stoixeio; i++) { if ( ESmelos(i,s1)!= ESmelos(i,s2) ) return 0; /*kapoio stoixeio den einai koino*/ return 1; int ESyposynolo(typos_synolou s1,typos_synolou s2) /*Elegxei an ena synolo einai yposynolo enos alloy*/ { int i; for(i = min_stoixeio; i<=max_stoixeio; i++) { if ( ESmelos(i,s1) &&!ESmelos(i,s2) ) return 0; /*false*/ return 1; /**************************************************************************** ** Skopos Dexontai : dyo synola Epistrefoyn : Prakseis metaksy synolwn : ena synolo ***************************************************************************** */ void ESenosi_synolou(typos_synolou s1,typos_synolou s2,typos_synolou enosi) /*Dhmioyrgei thn enwsh 2 synolwn*/ { int i; for (i=min_stoixeio;i<=max_stoixeio;i++) enosi[i-min_stoixeio] = ESmelos(i,s1) ESmelos(i,s2); Δ.Μήλιος 27
void EStomi_synolou(typos_synolou s1,typos_synolou s2,typos_synolou tomi) /*Dhmioyrgei thn tomh 2 synolwn*/ { int i; ESkeno_synolo(tomi); for (i=min_stoixeio;i<=max_stoixeio;i++) tomi[i-min_stoixeio] = ESmelos(i,s1) && ESmelos(i,s2); void ESdiafora_synolou(typos_synolou s1,typos_synolou s2,typos_synolou diafora) /*Dhmioyrgei th diafora 2 synolwn*/ { int i; for (i=min_stoixeio;i<=max_stoixeio;i++) diafora[i-min_stoixeio] = ESmelos(i,s1) &&!ESmelos(i,s2); Ακολουθεί ο κώδικας του αρχείου Διεπαφής του ΑΤΔ κατευθυνόμενο Γράφημα με βάρη: #ifndef GARRAY #define GARRAY #include "TStoixeioyGraph.h" /*dhlwseis typwn*/ #define PLITHOS 100 typedef int typos_pinaka[plithos][plithos]; typedef TStoixeioyGraph data_arr[plithos]; typedef struct { typos_pinaka geit_pin; /*pinakas geitonikon koryfon*/ data_arr dedomena; /*dedomena kathe korifis tou grafhmatos*/ int ar_koryfon; graphima; typedef int typos_varoys; Δ.Μήλιος 28
/*dhlwseis synarthsewn*/ /*dhmioyrgia*/ void Graph_dimiourgia(graphima *G); /*prakseis elegxoy*/ int Graph_geitoniki(graphima G, int p, int q, int *error); /*prakseis pros8eshs/apomakrynshs*/ void Graph_eisagogi_akmis(graphima *G, int p, int q, typos_varoys varos, int *error); int Graph_diagrafi_akmis(graphima *G, int p, int q, int *error); void Graph_eisagogi_korifis(graphima *G, int *p,tstoixeioygraph stoixeio, int *error); void Graph_diagrafi_korifis(graphima *G, int p, int *error); void Graph_metavatiko_graphima(graphima *A, graphima *P); /*prakseis dedomenwn*/ void Graph_enimerosi(graphima *G, int p, TStoixeioyGraph stoixeio, int *error); void Graph_anaktisi(graphima G, int p, TStoixeioyGraph *val, int *error); #endif /*#ifndef GARRAY */ Ακολουθεί ο κώδικας του αρχείου Υλοποίησης του ΑΤΔ κατευθυνόμενο Γράφημα με βάρη: #include <stdio.h> #include <stdlib.h> #include "Garray_Kat.h" /*orismos synarthsewn*/ void Graph_dimiourgia(graphima *G) {/* Pro: kamia * Meta: Dhmioyrgia enos kenoy grafhmatos */ G->ar_koryfon=0; Δ.Μήλιος 29
int Graph_geitoniki(graphima G, int p, int q, int *error) {/* Pro: Oi koryfes anhkoyn sto synolo twn koryfwn toy grafhmatos G * Meta: An yparxei akmh apo thn koryfh p sthn q tote h synarthsh epistrefei 1 * diaforetika epistrefei -1 */ *error=0; if ( (p<0) (p>g.ar_koryfon-1) (q<0) (q>g.ar_koryfon-1) )//ektos orion { *error=1; G p->q*/ return -1; return (G.geit_pin[p][q]); /*den apaiteitai allagh gia katey8ynomeno void Graph_eisagogi_akmis(graphima *G, int p, int q, typos_varoys varos, int *error) {/* Pro: Oi koryfes q,p anhkoyn sto synolo twn koryfwn toy grafhmatos G kai h akmh * (p,q) den anhkei sto mh katey8hnomeno grafhma *G * Meta: An h (p,q) den einai akmh toy grafhmatos tote eisagetai sto *G * diaforetika epistrefei error=1 */ *error=0; if ( (p<0) (p>g->ar_koryfon-1) (q<0) (q>g->ar_koryfon-1) ) //ektos orion { *error=1; return; if (Graph_geitoniki(*G,p,q,error)) //an iparxei idi akmi metaksi auton ton koryfon { *error=1; return; { *error=0; G->geit_pin[p][q] = varos; /*G->geit_pin[q][p] = 1;*/ /*afaireitai gia thn ylopoihsh katey8ynomenoy G p->q*/ Δ.Μήλιος 30
int Graph_diagrafi_akmis(graphima *G, int p, int q, int *error) {/* Pro: H (p,q) einai akmh toy mh katey8ynomenoy grafhmatos *G * Meta: An h (p,q) einai akmh toy grafhmatos tote diagrafetai h (p,q) * apo to *G kai h synarthsh epistrefei 1, diaforetika epistrefei 0 */ *error=0; if ( (p<0) (p>g->ar_koryfon-1) (q<0) (q>g->ar_koryfon-1) ) //ektos orion { *error=1; return 0; if (!Graph_geitoniki(*G,p,q,error)) //an den iparxei akmi return 0; { *error=0; G->geit_pin[p][q] = 0; /*G->geit_pin[q][p] = 0;*/ /*afaireitai gia thn ylopoihsh katey8ynomenoy G p->q*/ return 1; Δ.Μήλιος 31
void Graph_eisagogi_korifis(graphima *G, int *p,tstoixeioygraph stoixeio, int *error) {/* Pro: to grafhma *G den exei megisto plh8os koryfwn * Meta: Eisagetai sto grafhma *G h koryfh G->arkrfon xwris ayth na synde8ei me tis * alles koryfes, o *p ginetai isos me aythn */ int i; *error=0; if (G->ar_koryfon == PLITHOS) //an kseperna to megisto plithos stoixeion { *error=1; return; { (G->ar_koryfon)++; *p = G->ar_koryfon -1; /*Teleytaia koryfh*/ for (i=0;i<=*p;i++) { G->geit_pin[*p][i]= 0; /*Nea grammh*/ G->geit_pin[i][*p]= 0; /*Nea sthlh*/ TSgraph_setValue(&(G->dedomena[*p]), stoixeio); Δ.Μήλιος 32
void Graph_diagrafi_korifis(graphima *G, int p, int *error) {/* Pro: H koryfh p anhkein sto synolo twn koryfwn toy grafhmatos *G * Meta: An h koryfh p anhkein sto synolo twn koryfwn toy grafhmatos *G, * tote ayth diagrafetai ka8ws kai oles oi akmes poy thn periexoyn. * Meta apo aytes tis diagrafes to grafhma exei ws koryfes toy tis * 0,1,..., G->arkrfon-1 */ int i,j; *error=0; if ( (p<0) (p>g->ar_koryfon-1) )//ektos orion { *error=1; return; { /*metakinhsh ths i+1 grammhs pros ta panw*/ for (i=p;i<=g->ar_koryfon - 2;i++) for (j=0;j<=g->ar_koryfon - 1;j++) G->geit_pin[i][j] = G->geit_pin[i+1][j]; /*metakinhsh ths i+1 sthlhs pros ta aristera*/ for (i=p;i<=g->ar_koryfon - 2;i++) for (j=0;j<=g->ar_koryfon - 2;j++) G->geit_pin[j][i] = G->geit_pin[j][i+1]; /*metakinhsh twn dedomenwn pros ta aristera*/ for (i=p;i<=g->ar_koryfon - 2;i++) TSgraph_setValue(&(G->dedomena[i]), G->dedomena[i+1]); G->ar_koryfon--; Δ.Μήλιος 33
void Graph_metavatiko_graphima(graphima *A,graphima *P) {/* Pro: Dhmioyrgia toy grafhmatos A * Meta: To grafhma P einai to metabatiko grafhma toy A */ int i,j,k; typos_pinaka PP; for(i=0;i<=(a->ar_koryfon-1);i++) for(j=0;j<=plithos-1;j++) (P->geit_pin)[i][j]=(A->geit_pin)[i][j]; for(k=0;k<=(a->ar_koryfon-1);k++) { for(i=0;i<=(a->ar_koryfon-1);i++) for(j=0;j<=(a->ar_koryfon-1);j++) PP[i][j] = (P->geit_pin)[i][j]; for(i=0;i<=(a->ar_koryfon-1);i++) if (PP[i][k]) for(j=0;j<=(a->ar_koryfon-1);j++) if (PP[k][j]) (P->geit_pin)[i][j] = 1; Δ.Μήλιος 34
void Graph_enimerosi(graphima *G, int p, TStoixeioyGraph stoixeio, int *error) {/* Pro: Dhmioyrgia toy grafhmatos G * Meta: Enimerosi tis korifis pou deixnei to "p" me tin timi tou "stoixeio" */ int out_err; *error=0; if ( (p<0) (p>g->ar_koryfon-1) ) //ektos orion { *error=1; return; TSgraph_setValue(&(G->dedomena[p]), stoixeio); void Graph_anaktisi(graphima G, int p, TStoixeioyGraph *val, int *error) {/* Pro: Dhmioyrgia toy grafhmatos G * Meta: Anaktisi ton dedomenon tis korifis pou deixnei to "p" stin timi "val" */ *error=0; if ( (p<0) (p>g.ar_koryfon-1) ) //ektos orion *error=1; TSgraph_setValue(val, G.dedomena[p]); 1.3.2 Υλοποίηση 2 η : Υλοποίηση μη Κατευθυνόμενο Γράφημα χωρίς βάρη με λίστα ακμών Στην υλοποίηση αυτή έχουμε μια λίστα κόμβων του γραφήματος (korifi) όπου κάθε κόμβος εξυπηρετεί και σαν κεφαλή για μια λίστα ακμών που συνδέονται με τον συγκεκριμένο κόμβο. Κάθε κόμβος ακμής (akmi) περιέχει 2 δείκτες. Ένα προς τον επόμενο κόμβο της ακμής (epomenos) και ένα προς ένα κόμβο του γραφήματος για να δηλώσει το άλλο άκρο της ακμής που αναπαριστά (akro). Η δομή που αναπαριστά κόμβους κορυφών (korifi) περιέχει τα δεδομένα του κόμβου που είναι τύπου στοιχείου γραφήματος, ένα δείκτη στον επόμενο κόμβο του γραφήματος και ένα στον πρώτο κόμβο της λίστας ακμών της συγκεκριμένης κορυφής (kefali) και ένα ακέραιο (episkeftike) που δείχνει αν ο κόμβος έχει επισκεφτεί για περιπτώσεις αναζήτησης (βάθος, πλάτος). Δ.Μήλιος 35
1.3.2.1 Αρχεία Διεπαφής-Υλοποίησης Στο αρχείο Διεπαφής ορίζονται 2 δομές (korifi, akmi) που εξηγήθηκαν περιγραφικά από πάνω και 2 δείκτες σε αυτές τις δομές (kdktis για την λίστα κόμβων και adktis για την λίστα ακμών) αλλά κυρίως εντοπίζεται το include του τύπου στοιχείου γραφήματος το οποίο δεν περιλαμβάνει συγκεκριμένο μονοπάτι που να προσδιορίζει το αρχείο του τύπου στοιχείου γραφήματος αλλά περιγράφει τον ρόλο του συγκεκριμένου include. Τέλος δηλώνεται και ο μέγιστος αριθμός στοιχείων του γραφήματος. Προφανώς υπάρχουν και οι δηλώσεις των συναρτήσεων-πράξεων του γραφήματοςπράγμα αυτονόητο για ένα αρχείο Διεπαφής, όμως καλό είναι να διευκρινιστεί πως στην συγκεκριμένη υλοποίηση υπάρχουν κάποιες extra συναρτήσεις-πράξεις που δεν έχουν αναφερθεί στις βασικές πράξεις και αφορούν μόνο την υλοποίηση με λίστα ακμών. Αυτές οι συναρτήσεις είναι οι εξής: Graph_keni_k, Graph_keni_a, Graph_proxorise_k, Graph_proxorise_a, Graph_diagrafi_listas, Graph_katastrofi. Περιληπτικά μπορούμε να πούμε πως οι συναρτήσεις με την σειρά που αναφέρθηκαν αφορούν: έλεγχο για κενή λίστα κόμβων ( Graph_keni_k), έλεγχο για κενή λίστα ακμών ( Graph_keni_a), μετάβαση στον επόμενο κόμβο λίστας κόμβων (Graph_proxorise_k), μετάβαση στον επόμενο κόμβο λίστας ακμών (Graph_proxorise_a), διαγραφή μιας λίστας ακμών (Graph_diagrafi_listas), καταστροφή του γραφήματος (Graph_katastrofi). Ακολουθεί ο κώδικας του αρχείου Διεπαφής: #ifndef GEDGE #define GEDGE #include "to antistoixo.h typou stoixeiou" /*edo analoga tin efarmogi i to test tou tipou stoixeiou mpainei to antoistixo.h tou tipou stoixeiou */ /*dhlwseis typwn*/ typedef struct korifi typedef struct akmi *kdktis; *adktis; typedef struct korifi { TStoixeioyGraph dedomena; int episkeftike; kdktis epomenos; /*epomenos kombos listas koryfwn*/ adktis kefali; /*deikths listas akmwn*/ korifi; typedef struct akmi { kdktis akro; /*akro akmhs*/ adktis epomenos;/*epomenos kombos listas akmwn*/ akmi; /*lista akmon*/ Δ.Μήλιος 36
typedef kdktis graphima; /*dhlwseis syanrthsewn*/ /*prakseis listwn*/ int Graph_keni_k(kdktis lista); int Graph_keni_a(adktis lista); void Graph_proxorise_k(kdktis *p); void Graph_proxorise_a(adktis *p); void Graph_enimerosi(TStoixeioyGraph stoixeio, kdktis p); void Graph_anaktisi(kdktis p, TStoixeioyGraph *val); void Graph_diagrafi_komvou(kdktis v, adktis *kefali); void Graph_diagrafi_listas(adktis *kefali); /*dhmioyrgia/katastrofi*/ void Graph_dimiourgia(graphima *G); void Graph_katastrofi(graphima * G); /*Prakseis elegxoy*/ int Graph_geitoniki(graphima G, kdktis p, kdktis q); /*prakseis pros8eshs/apomakrynshs*/ void Graph_diagrafi_korifis(graphima *G, kdktis p); void Graph_eisagogi_korifis(graphima *G, TStoixeioyGraph stoixeio); int Graph_eisagogi_akmis(graphima *G, kdktis p, kdktis q); int Graph_diagrafi_akmis(graphima *G, kdktis p, kdktis q); #endif /*#ifndef GEDGE */ Ακολουθεί ο κώδικας του αρχείου Υλοποίησης: #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include "Gedge.h" /*orismos synarthsewn*/ Δ.Μήλιος 37
int Graph_keni_k(kdktis lista) {/* Pro: Dhmioyrgia listas * Meta: epistrefei 1 an h lista einai kenh, diaforetika 0 */ return ( lista == NULL ); int Graph_keni_a(adktis lista) {/* Pro: Dhmioyrgia listas * Meta: epistrefei 1 an h lista einai kenh, diaforetika 0 */ return ( lista == NULL ); void Graph_proxorise_k(kdktis *p) {/* Pro: O deikths p deixnei ena kombo sth lista * Meta: O deikths p deixnei ston epomeno kombo sth lista */ *p = (*p)->epomenos; void Graph_proxorise_a(adktis *p) {/* Pro: O deikths p deixnei ena kombo sth lista * Meta: O deikths p deixnei ston epomeno kombo sth lista */ *p = (*p)->epomenos; void Graph_enimerosi(TStoixeioyGraph stoixeio, kdktis p) {/* Pro: O deikths p deixnei ena kombo koryfh * Meta: Eisagei to stoixeio ston kombo pou deixnei o p */ TSgraph_setValue(&(p->dedomena), stoixeio); void Graph_anaktisi(kdktis p, TStoixeioyGraph *val) {/* Pro: O deikths p deixnei ena kombo koryfh * Meta: h synarthsh epistrefei to periexomeno toy komboy poy deixnei o p */ TSgraph_setValue(val, p->dedomena); void Graph_dimiourgia(graphima *G) {/* Pro: kamia * Meta: Dhmioyrgia enos kenoy grafhmatos */ *G=NULL; Δ.Μήλιος 38
void Graph_katastrofi(graphima * G) {/* Pro: exei dhmioyrgh8ei to grafhma *G * Meta: exei katastrafei olokliro to grafhma *G */ kdktis trexon; trexon= *G; while (!Graph_keni_k(trexon)) { Graph_diagrafi_korifis(G,trexon); trexon=*g; int Graph_geitoniki(graphima G, kdktis p, kdktis q) {/* Pro: Oi koryfes anhkoyn sto synolo twn koryfwn toy grafhmatos G * Meta: An yparxei akmh apo thn koryfh p sthn q tote h synarthsh epistrefei 1 * diaforetika epistrefei 0. * SHMEIWSH: H synarthsh paramenei ws exei se periptwsh Katey8ynomenoy G p- >q */ int telos; /*elegxos gia th sarwsh ths listas akmwn toy p*/ adktis trexon; /*deikths gia th sarwsh ths listas akmwn toy p*/ int geit; geit=0; trexon = p->kefali; /*afethria apo thn kefalh ths listas akmwn toy p*/ telos = 0; while( (!telos) && (!Graph_keni_a(trexon)) ) { if (trexon->akro == q ) /*bre8hke to tairi toy q sth lista akmwn*/ { telos = 1; geit = 1; Graph_proxorise_a(&trexon); return geit; Δ.Μήλιος 39
void Graph_diagrafi_korifis(graphima *G, kdktis p) {/* Pro: exei dhmioyrgh8ei to grafhma *G * Meta: exei diagrafei apo to grafhma *G h koryfh poy deixnei o p */ kdktis trexon,protrexon,prop; prop=null; protrexon=null; trexon = *G; /*o trexon diatrexei th lista koryfwn*/ while (!Graph_keni_k(trexon)) { /*den xreiazetai h anazhthsh ths (p,p) akmhs*/ if (p!=trexon) /*diagrafh ths (trexon,p) an yparxei*/ Graph_diagrafi_komvou(p,&(trexon->kefali)); prop=protrexon; protrexon=trexon; Graph_proxorise_k(&trexon); /*proxwrhse sthn epomenh koryfh*/ Graph_diagrafi_listas(&(p->kefali)); if(prop!=null) prop->epomenos=p->epomenos; *G=p->epomenos; free(p); p=null; Δ.Μήλιος 40
void Graph_diagrafi_komvou(kdktis v, adktis *kefali) {/* Pro: O deikths v deixnei ena kombo koryfh * Meta: Entopizei kai diagrafei ton kombo ths listas akmwn poy 3ekina * apo ton *kefali toy opoioy to akro einai iso me v */ adktis pros; if (!Graph_keni_a(*kefali)) { if ((*kefali)->akro==v)/*diagrafh komboy*/ { pros = *kefali; Graph_proxorise_a(kefali); free(pros); /*de bre8hke o kombos synexizetai h anazhthsh*/ Graph_diagrafi_komvou(v,&((*kefali)->epomenos)); void Graph_diagrafi_listas(adktis *kefali) {/* Pro: O deikths kefalh exei mia timh * Meta: diagrafei oloys toys komboys mias listas akmwn poy 3ekina * apo ton *kefali */ if (!Graph_keni_a(*kefali)) { Graph_diagrafi_listas(&((*kefali)->epomenos)); free(*kefali); *kefali = NULL; void Graph_eisagogi_korifis(graphima *G, TStoixeioyGraph stoixeio) {/* Pro: exei dhmioyrgh8ei to grafhma *G * Meta: Eisagetai enas neos kombos sthn arxh ths listas koryfwn me dedomena stoixeio */ kdktis p; p = malloc(sizeof(struct korifi)); TSgraph_setValue(&(p->dedomena), stoixeio); /*Syndeei ton kombo sthn arxh ths listas koryfwn toy G*/ p->epomenos = *G; p->kefali = NULL; /*H lista akmwn toy p einai kenh*/ *G = p; /*o kombos poy deixnei o p einai h nea kefalh ths listas koryfwn toy *G*/ Δ.Μήλιος 41
int Graph_eisagogi_akmis(graphima *G, kdktis p, kdktis q) {/* Pro: Oi deiktes p,q deixnoyn se komboys koryfes toy grafhmatos G kai h akmh * (p,q) den anhkei sto grafhma *G * Meta: An h (p,q) den einai akmh toy grafhmatos tote eisagetai sto *G */ adktis pros; if (!Graph_geitoniki(*G,p,q)) { /*Diathreitai h kefalh ths listas akmwn ths p*/ pros = p->kefali; /*Dhmioyrgia kefalhs gia nea lista akmwn*/ p->kefali = malloc(sizeof(struct akmi)); /*Syndesh aytoy toy komboy me to p*/ p->kefali->akro = q; /*Syndesh me thn kefalh ths listas akmwn toy q*/ p->kefali->epomenos = pros; /*Epanalambanontai ta parapanw gia to q. Afairountai se periptwsh Katey8ynomenoy G p->q*/ pros = q->kefali; q->kefali = malloc(sizeof(struct akmi)); q->kefali->akro = p; q->kefali->epomenos = pros; return 1; return 0; Δ.Μήλιος 42
int Graph_diagrafi_akmis(graphima *G, kdktis p, kdktis q) {/* Pro: exei dhmioyrgh8ei to grafhma *G. Oi p,q deixnoyn koryfes * toy grafhmatos *G. * Meta: diagrafei mia akmh metaksy twn koryfwn poy deixnoyn oi p,q * toy grafhmatos *G */ if (Graph_geitoniki(*G,p,q)) { /*Diagrafh apo th lista akmwn toy p*/ Graph_diagrafi_komvou(q,&(p->kefali)); /*Diagrafh apo th lista akmwn toy q Afaireitai se periptwsh Katey8ynomenoy G p->q*/ Graph_diagrafi_komvou(p,&(q->kefali)); return 1; return 0; 1.3.2.2 Αρχεία Δοκιμής Στα αρχεία Δοκιμής περιλαμβάνεται το αρχείο main που χρησιμοποιείται ως αρχείο test για τις πράξεις της ATΔ Γραφήμα. Στο αρχείο main περιλαμβάνονται και οι συναρτήσεις: episkepsi, vathos, diadromi_v, platos, diadromi_p, ektos_orion. Ο ρόλος όλων εκτός της τελευταίας έχει αναλυθεί και στην προηγούμενη υλοποίηση. Η ektos_orion όμως είναι μια συνάρτηση που καλείται όπου θεωρείται απαραίτητο στο αρχείο Δοκιμής για να ελέγξει αν ο αριθμός του κόμβου που δίνει ο χρήστης για να γίνει οποιαδήποτε πράξη πάνω του ανήκει στο γράφημα. Στα αρχεία Δοκιμής περιλαμβάνονται και τα αρχεία Υλοποίησης-Διεπαφής του τύπου στοιχείου Ουράς (int) και τα αρχεία Υλοποίησης-Διεπαφής της υλοποίησης της ουράς με κενό (για τον κώδικα των αρχείων αυτών ανατρέχτε στο 4 ο κεφάλαιο στις ενότητες 4. 3. 1 και 4. 3. 4) Ακολουθεί ο κώδικας του αρχείου Δοκιμής: #include <stdio.h> #include "Gedge.h" #include "../../TS/TStoixeioyGraph.h" #include "Qgap.h" #include "TStoixeioyOyras.h" void print_options(void); int ektos_orion(int i,int korifes); void episkepsi(kdktis i); void vathos(graphima G); void diadromi_v(kdktis p); Δ.Μήλιος 43
void platos(graphima G); void diadromi_p(kdktis p); TOuras oura_korifon; int main(void) { int option,created,out_err,num_korifon; graphima G; kdktis p, q; int p_num, q_num, error, apot; TStoixeioyGraph x; num_korifon=0; error=0; created=0; p=g; q=g; do{ print_options(); scanf("%d", &option); switch(option) {case 1: case 2: Graph_dimiourgia(&G); created=1; printf("to grafima dimiourgithike!\n"); { printf("\nden uparxei grafima gia na elegxthei ama iparxoun geitonikes korifes!\n"); printf("dwse ton ari8mo ths prwths koryfhs: "); scanf("%d", &p_num); printf("dwse ton ari8mo ths deyterhs koryfhs: "); scanf("%d", &q_num); if(ektos_orion(p_num,num_korifon) ektos_orion(q_num,num_korifon) ) { printf("\nerror! La8os ari8mos koryfhs!\n"); p=g; Δ.Μήλιος 44
tou!\n"); q=g; for(;q_num>0;q_num--) q=q->epomenos; for(;p_num>0;p_num--) p=p->epomenos; apot=graph_geitoniki(g, p, q); if(apot) case 3: printf("oi koryfes einai geitonikes!\n"); printf("oi koryfes DEN einai geitonikes!\n"); { printf("\nden uparxei grafima gia na enimerothei kapoia koryfh printf("dwse ton ari8mo ths koryfhs pou 8es na enhmerwseis: "); scanf("%d", &p_num); if(ektos_orion(p_num,num_korifon) ) p=g; { printf("\nerror! La8os ari8mos koryfhs!\n"); for(;p_num>0;p_num--) p=p->epomenos; printf("dwse ena stoixeio gia na eisax8ei sthn koryfh: "); out_err=tsgraph_readvalue(stdin,&x); if(!out_err) { printf("\n error stin readvalue!\n"); Graph_enimerosi(x, p); printf("h koryfh enhmerothike!\n"); case 4: { printf("\nden uparxei grafima gia na parthoun ta dedomena apo kapoia koryfh tou!\n"); printf("dwse ton ari8mo ths koryfhs pou 8es ta dedomena: "); Δ.Μήλιος 45
scanf("%d", &p_num); if(ektos_orion(p_num,num_korifon) ) { printf("\nerror! La8os ari8mos koryfhs!\n"); p=g; for(;p_num>0;p_num--) p=p->epomenos; Graph_anaktisi(p, &x); printf("ta dedomena toy komboy einai:"); out_err=tsgraph_writevalue(stdout,x); if(out_err <0) { printf("\n error stin writevalue!\n"); case 5: { printf("\nden uparxei grafima gia na diagrafei kapoia koryfh tou!\n"); printf("dwse ton ari8mo ths koryfhs pou 8es na diagrapseis: "); scanf("%d", &p_num); if(ektos_orion(p_num,num_korifon) ) { printf("\nerror! La8os ari8mos koryfhs!\n"); p=g; for(;p_num>0;p_num--) p=p->epomenos; Graph_diagrafi_korifis(&G, p); printf("h koryfh diagrafhke!\n"); num_korifon--; case 6: { printf("\nden uparxei grafima gia na diagrafei kapoia akmh tou!\n"); printf("dwse ton ari8mo ths 1hs koryfhs ths akmhs pros diagrafh: "); Δ.Μήλιος 46
"); scanf("%d", &p_num); printf("dwse ton ari8mo ths 2hs koryfhs ths akmhs pros diagrafh: scanf("%d", &q_num); if(ektos_orion(p_num,num_korifon) ektos_orion(q_num,num_korifon) )!\n");!\n"); "); "); p=g; q=g; { printf("\nerror! La8os ari8mos koryfhs!\n"); for(;q_num>0;q_num--) q=q->epomenos; for(;p_num>0;p_num--) p=p->epomenos; apot=graph_diagrafi_akmis(&g, p, q); if(apot) case 7: printf("h akmh diagrafhke!\n"); printf("den yparxei ayth h akmh!\n"); { printf("\nden uparxei grafima gia na eisaxthei kapoia koryfh printf("dwse ena stoixeio gia na eisax8ei sth nea koryfh: "); TSgraph_readValue(stdin,&x); Graph_eisagogi_korifis(&G, x); printf("h koryfh eishx8h!\n"); num_korifon++; case 8: { printf("\nden uparxei grafima gia na eisaxthei kapoia akmh printf("dwse ton ari8mo ths 1hs koryfhs ths akmhs pros eisagwgh: scanf("%d", &p_num); printf("dwse ton ari8mo ths 2hs koryfhs ths akmhs pros eisagwgh: Δ.Μήλιος 47
scanf("%d", &q_num); if(ektos_orion(p_num,num_korifon) ektos_orion(q_num,num_korifon) )!\n");!\n"); {printf("\nerror! La8os ari8mos koryfhs!\n"); p=g; q=g; for(;q_num>0;q_num--) q=q->epomenos; for(;p_num>0;p_num--) p=p->epomenos; apot=graph_eisagogi_akmis(&g, p, q); if(apot) case 9: printf("h akmh eishx8h!\n"); printf("yparxei hdh ayth h akmh!\n"); { printf("\nden uparxei grafima gia ginei anazitisi kata vathos vathos(g); case 10: { printf("\nden uparxei grafima gia ginei anazitisi kata platos platos(g); case 11: { printf("\nden uparxei grafima gia katastrafei!\n"); Graph_katastrofi(&G); created=0; printf("to grafima katastrafike!\n"); Δ.Μήλιος 48
while(option); return 0; void print_options(void) { printf("\n\n1. Dhmioyrgia grafhmatos\n\ 2. Elegxos geitonikwn koryfwn\n\ 3. Enhmerwsh dedomenwn koryfhs\n\ 4. Anakthsh dedomenwn koryfhs\n\ 5. Diagrafh koryfhs\n\ 6. Diagrafh akmhs\n\ 7. Eisagwgh koryfhs\n\ 8. Eisagwgh akmhs\n\ 9. Anazhthsh prwta kata va8os\n\ 10.Anazhthsh prwta kata platos\n\ 11.Katastrofi grafhmatos\n\ Dwste thn epilogh sas(1-10, 0 gia eksodo):"); int ektos_orion(int i,int korifes) { if ( (i<0) (i>korifes-1)) return 1; return 0; void episkepsi(kdktis i) { TSgraph_writeValue(stdout,i->dedomena); /*kata ba8os anazhthsh*/ void vathos(graphima G) { /* * Pro: Dhmioyrgia toy grafhmatos G * Meta: H synarthsh diadromi paragei thn prwta kata ba8os anazhthsh twn koryfwn */ Δ.Μήλιος 49
kdktis p = G; while(!graph_keni_k(p)) { p->episkeftike = 0; Graph_proxorise_k(&p); p=g; while(!graph_keni_k(p)) { if (!p->episkeftike) diadromi_v(p); Graph_proxorise_k(&p); void diadromi_v(kdktis p) { /* * Pro: i einai mia koryfh toy grafhmatos * Meta: H episkepsh ths koryfhs i kai twn geinonikwn ths exei teleiwsei me */ * thn anazhthsh prwta kata ba8os. adktis trexon; kdktis q; episkepsi(p); p->episkeftike = 1; /*Proetoimasia gia thn episkepsh twn kombwn ths listas akmwn ths koryfhs sthn opoia deixnei prwta o p*/ trexon = p->kefali; while(!graph_keni_a(trexon)) { q = trexon->akro; /*h q einai geitonikh ths p*/ if (!q->episkeftike) diadromi_v(q); Graph_proxorise_a(&trexon); Δ.Μήλιος 50