Γράφοι Ορολογία γράφος ή γράφηµα (graph) Ορισµός: G = (V, E) όπου V:ένα σύνολο E:µια διµελής σχέση στο V Ορολογία (συνέχεια) κάθε v V ονοµάζεται κορυφή (vertex) ή κόµβος (node) κάθε (v 1, v 2 ) Ε ονοµάζεται ακµή (edge) ή τόξο (arrow) v 2 v 4 v 1 (i) v 3 v 5 v 6 v 7 V = { v 1, v 2, v 3, v 4, v 5, v 6, v 7 E = { (v 1, v 2 ), (v 1, v 3 ), (v 2, v 4 ), (v 3, v 4 ), (v 5, v 2 ), (v 5, v 3 ), (v 1, v 5 ), (v 6, v 7 ), (v 7, v 6 ), (v 7, v 7 ) 1
Γράφοι Είδη γράφων Κατευθυνόµενος (directed) γράφος, αν (v 1, v 2 ) Ε είναι διατεταγµένο ζεύγος Μη κατευθυνόµενος (undirected) γράφος, αν (v 1, v 2 ) και (v 2, v 1 ) ταυτόσηµα Ορισµοί ύο κορυφές v 1 και v 2 ονοµάζονται γειτονικές (adjacent) αν (v 1, v 2 ) Ε (ii) v 1 v 2 v 3 v 4 v 5 v 6 v 7 κατευθυνόµενος w 1 w 2 w 4 w 3 µη κατευθυνόµενος 2
Γράφοι Ορισµοί (συνέχεια) Βαθµός (degree) µιας κορυφής v V είναι οαριθµός των γειτονικών κορυφών της deg(w 1 )=2, deg(w 2 )=1 Για κατευθυνόµενους γράφους: µέσα-βαθµός (in-degree) και έξω-βαθµός (out-degree) indeg(v 1 )=0, outdeg(v 1 )=3, indeg(v 2 )=2, outdeg(v 2 )=1 (iii) v 1 v 2 v 3 v 4 v 5 v 6 v 7 κατευθυνόµενος w 1 w 2 w 4 w 3 µη κατευθυνόµενος 3
Γράφοι (iv) Ορισµοί (συνέχεια) Μονοπάτι (path) είναι µια ακολουθία κορυφών v 1, v 2,... v n V τέτοια ώστε (v i, v i+1 ) Ε, i Μήκος µονοπατιού Κύκλος (cycle) είναι ένα µονοπάτι µε v 1 = v n Ακυκλικός (acyclic) γράφος: δεν περιέχει κύκλους b d a c e Μονοπάτι: a, b, c, e, g b d a c e µήκος=4 f g f g Κύκλος: b, c, e, d, b 4
Γράφοι (v) Ορισµοί (συνέχεια) Υπογράφος (subgraph) του G = (V, E) είναι ένας γράφος G = (V, E ) τέτοιος ώστε V V και E E b d a c e G f g a b c f b c f d e g d e G 2 υπογράφος του G G 1 υπογράφος του G 5
Γράφοι Ορισµοί (συνέχεια) Συνδεδεµένος (connected) ή συνεκτικός γράφος: για κάθε ζεύγος κορυφών v 1, v 2 V υπάρχει µονοπάτι από την v 1 στη v 2 Συνδεδεµένα συστατικά (connected components): συνδεδεµένοι υπογράφοι που περιέχουν όλες τις κορυφές και τις ακµές (vi) a b d c e f g συνδεδεµένος a b d c e f g µη συνδεδεµένος 6
Γράφοι Ορισµοί (συνέχεια) Ισχυρά συνδεδεµένος (strongly connected) κατευθυνόµενος γράφος: όπως προηγουµένως Ασθενώς συνδεδεµένος (weakly connected) κατευθυνόµενος γράφος: συνδεδεµένος, αν αγνοήσουµε τις κατευθύνσεις των ακµών (vii) a b d c e f g ισχυρά συνδεδεµένος a b c f? d e g ασθενώς συνδεδεµένος 7
Γράφοι ως ΑΤ Υποθέτουµε ότι προϋπάρχει: Τύπος κορυφής: vertex Πράξεις ΑΤ : graph void empty (graph *g, int n); int isadjacent (graph g, vertex v1, vertex v2); void join (graph *g, vertex v1, vertex v2); void remove (graph *g, vertex v1, vertex v2); 8
Αναπαράσταση γράφων µε ΣΤ ύο από τους κυριότερους τρόπους αναπαράστασης Πίνακας γειτονικών κορυφών (adjacency matrix) Λίστα γειτονικών κορυφών (adjacency list) Άλλοι τρόποι αναπαράστασης Λίστα ακµών (edge list) 9
Πίνακας γειτονικών κορυφών (i) Τρόπος αναπαράστασης Έστω ο γράφος G = (V, E) και n = V Ο γράφος G αναπαρίσταται µε έναν πίνακα a διαστάσεων n n τα στοιχεία του οποίου είναι TRUE ή FALSE a[i, j] = TRUE αν και µόνο αν (v i, v j ) E v 0 v 1 v 3 v 2 0 0 1 1 0 0 1 0 0 0 0 0 0 0 1 0 v 0 v 1 v 3 v 2 0 0 1 1 0 0 1 0 1 1 0 1 1 0 1 0 10
Πίνακας γειτονικών κορυφών (ii) Μέγιστο πλήθος κορυφών #define MAX 10 Τύπος κορυφής typedef unsigned vertex; Τύπος για τις λογικές τιµές typedef enum { FALSE=0, TRUE=1 bool; Ορισµός τύπου graph typedef bool graph[max][max]; 11
Πίνακας γειτονικών κορυφών (iii) Κενός γράφος void empty (graph *g, int n) { vertex v1, v2; for (v1=0; v1<n; v1++) for (v2=0; v2<n; v2++) (*g)[v1][v2] = FALSE; Έλεγχος ύπαρξης ακµής bool isadjacent (graph g, vertex v1, vertex v2) { return g[v1][v2]; 12
Πίνακας γειτονικών κορυφών (iv) Προσθήκη ακµής void join (graph *g, vertex v1, vertex v2) { (*g)[v1][v2] = TRUE; Αφαίρεση ακµής void remove (graph *g, vertex v1, vertex v2) { (*g)[v1][v2] = FALSE; 13
Λίστα γειτονικών κορυφών Τρόπος αναπαράστασης Έστω ο γράφος G = (V, E) και n = V Ο γράφος G αναπαρίσταται µε έναν πίνακα a διάστασης n τα στοιχεία του οποίου είναι γραµµικές λίστες που περιέχουν κορυφές η λίστα a[i] περιέχει την κορυφή j αν και µόνο αν (v i, v j ) E a[0] a[1] a[2] a[3] (i) v 0 v 1 v 3 v 2 2 3 2 2 14
Λίστα γειτονικών κορυφών (ii) Τύπος κορυφής typedef unsigned vertex; Ορισµός τύπου graph typedef struct node_tag { vertex v; struct node_tag * next; node, * graph[]; 15
Λίστα γειτονικών κορυφών (iii) Κενός γράφος void empty (graph *g, int n) { vertex v; *g = malloc(n * sizeof(node *)); if (*g == NULL) { fprintf(stderr, "Out of memory\n"); exit(1); for (v=0; v<n; v++) (*g)[v] = NULL; 16
Λίστα γειτονικών κορυφών (iv) Έλεγχος ύπαρξης ακµής bool isadjacent (graph g, vertex v1, vertex v2) { node * n; for (n=g[v1]; n!= NULL; n=n->next) if (n->v == v2) return TRUE; return FALSE; 17
Λίστα γειτονικών κορυφών (v) Προσθήκη ακµής void join (graph *g, vertex v1, vertex v2) { node * new = malloc(sizeof(node)); if (new == NULL) { fprintf(stderr, "Out of memory\n"); exit(1); new->v = v2; new->next = (*g)[v1]; (*g)[v1] = new; 18
Λίστα γειτονικών κορυφών (vi) Αφαίρεση ακµής void remove (graph *g, vertex v1, vertex v2) { node ** temp = &((*g)[v1]); while (*temp!= NULL) if ((*temp)->v == v2) { node * del = *temp; *temp = (*temp)->next; free(del); else temp = &((*temp)->next); 19
ιάσχιση γράφων (i) Κατά βάθος ξεκινώντας από την κορυφή 0: 1 0 4 0, 1, 2, 6, 3, 4, 5, 7 Κατά πλάτος 2 3 5 7 ξεκινώντας από την κορυφή 0: 6 0, 1, 4, 2, 3, 5, 7, 6 20
ιάσχιση γράφων (ii) Υλοποίηση διάσχισης κατά βάθος σε παράσταση λίστας γειτονικών κορυφών void traversedfs (graph g) { bool visited[n]; vertex v; for (v=0; v<n; v++) visited[v] = false; traversedfs_aux(g, visited, 0); 21
ιάσχιση γράφων (iii) void traversedfs_aux (graph g, bool visited[n], vertex current) { node * adj; printf("vertex %d\n", current); visited[current] = true; for (adj = g[current]; adj!= NULL; adj = adj->next) if (!visited[adj->vertex]) traversedfs_aux(g, visited, adj->vertex); 22
ιάσχιση γράφων (iv) Υλοποίηση διάσχισης κατά πλάτος σε παράσταση λίστας γειτονικών κορυφών void traversebfs (graph g) { node * adj; bool visited[n]; queue q; vertex v; for (v=0; v<n; v++) visited[v] = false; q = queueempty; queueinsert(&q, 0); 23
ιάσχιση γράφων (v) while (!queueisempty(q)) { vertex current = queueremove(&q); printf("vertex %d\n", current); visited[current] = true; for (adj = g[current]; adj!= NULL; adj = adj->next) if (!visited[adj->vertex]) queueinsert(&q, adj->vertex); 24