11-1 ΜΑΘΗΜΑ 12 ο Γράφοι, Διάσχιση Γράφων Υλικό από τις σημειώσεις Ν. Παπασπύρου, 2006
11-2 Γράφοι(i) Ορολογία –γράφος ή γράφημα (graph) Ορισμός: G = (V, E) όπου –V:ένα σύνολο –E:μια διμελής σχέση στο V Ορολογία (συνέχεια) –κάθε v V ονομάζεται κορυφή (vertex) ή κόμβος (node) –κάθε (v 1, v 2 ) Ε ονομάζεται ακμή (edge) ή τόξο (arrow) 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 ) } v4v4 v3v3 v5v5 v2v2 v1v1 v6v6 v7v7
11-3 Γράφοι(ii) Είδη γράφων –Κατευθυνόμενος (directed) γράφος, αν (v 1, v 2 ) Ε είναι διατεταγμένο ζεύγος –Μη κατευθυνόμενος (undirected) γράφος, αν (v 1, v 2 ) και (v 2, v 1 ) ταυτόσημα Ορισμοί –Δύο κορυφές v 1 και v 2 ονομάζονται γειτονικές (adjacent) αν (v 1, v 2 ) Ε μη κατευθυνόμενος w1w1 w2w2 w4w4 w3w3 κατευθυνόμενος v4v4 v3v3 v5v5 v2v2 v1v1 v6v6 v7v7
11-4 Γράφοι(iii) Ορισμοί (συνέχεια) –Βαθμός (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 μη κατευθυνόμενος w1w1 w2w2 w4w4 w3w3 κατευθυνόμενος v4v4 v3v3 v5v5 v2v2 v1v1 v6v6 v7v7
11-5 Γράφοι(iv) Ορισμοί (συνέχεια) –Μονοπάτι (path) είναι μια ακολουθία κορυφών v 1, v 2,... v n V τέτοια ώστε (v i, v i+1 ) Ε, i –Μήκος μονοπατιού –Κύκλος (cycle) είναι ένα μονοπάτι με v 1 = v n –Ακυκλικός (acyclic) γράφος: δεν περιέχει κύκλους d c e b a f g Μονοπάτι: a, b, c, e, g d c e b a f g Κύκλος: b, c, e, d, b μήκος=4
11-6 Γράφοι(v) Ορισμοί (συνέχεια) –Υπογράφος (subgraph) του G = (V, E) είναι ένας γράφος G´ = (V´, E´) τέτοιος ώστε V´ V και E´ E G d c e b a f g G 2 υπογράφος του G d c e bf g G 1 υπογράφος του G d c e b a f
11-7 Γράφοι(vi) Ορισμοί (συνέχεια) –Συνδεδεμένος (connected) ή συνεκτικός γράφος: για κάθε ζεύγος κορυφών v 1, v 2 V υπάρχει μονοπάτι από την v 1 στη v 2 –Συνδεδεμένα συστατικά (connected components): συνδεδεμένοι υπογράφοι που περιέχουν όλες τις κορυφές και τις ακμές συνδεδεμένος d c e b a f g μη συνδεδεμένος d c e b a f g
11-8 Γράφοι(vii) Ορισμοί (συνέχεια) –Ισχυρά συνδεδεμένος (strongly connected) κατευθυνόμενος γράφος: όπως προηγουμένως –Ασθενώς συνδεδεμένος (weakly connected) κατευθυνόμενος γράφος: συνδεδεμένος, αν αγνοήσουμε τις κατευθύνσεις των ακμών ασθενώς συνδεδεμένος d c e b a f g ισχυρά συνδεδεμένος d c e b a f g ?
11-9 Γράφοι ως ΑΤΔ Υποθέτουμε ότι προϋπάρχει: –Τύπος κορυφής: 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);
11-10 Αναπαράσταση γράφων με ΣΤΔ Δύο από τους κυριότερους τρόπους αναπαράστασης –Πίνακας γειτονικών κορυφών (adjacency matrix) –Λίστα γειτονικών κορυφών (adjacency list) Άλλοι τρόποι αναπαράστασης –Λίστα ακμών (edge list)
11-11 Πίνακας γειτονικών κορυφών(i) Τρόπος αναπαράστασης –Έστω ο γράφος G = (V, E) και n = |V| –Ο γράφος G αναπαρίσταται με έναν πίνακα a διαστάσεων n n τα στοιχεία του οποίου είναι TRUE ή FALSE –a[i, j] = TRUE αν και μόνο αν (v i, v j ) E v0v0 v1v1 v3v3 v2v2 v0v0 v1v1 v3v3 v2v
11-12 Πίνακας γειτονικών κορυφών(ii) Μέγιστο πλήθος κορυφών #define MAX 10 Τύπος κορυφής typedef unsigned vertex; Τύπος για τις λογικές τιμές typedef enum { FALSE=0, TRUE=1 } bool; Ορισμός τύπου graph typedef bool graph[MAX][MAX];
11-13 Πίνακας γειτονικών κορυφών(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]; }
11-14 Πίνακας γειτονικών κορυφών(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; }
11-15 Λίστα γειτονικών κορυφών(i) Τρόπος αναπαράστασης –Έστω ο γράφος G = (V, E) και n = |V| –Ο γράφος G αναπαρίσταται με έναν πίνακα a διάστασης n τα στοιχεία του οποίου είναι γραμμικές λίστες που περιέχουν κορυφές –η λίστα a[i] περιέχει την κορυφή j αν και μόνο αν (v i, v j ) E v0v0 v1v1 v3v3 v2v2 a[0] a[1] a[2] a[3] 2223
11-16 Λίστα γειτονικών κορυφών(ii) Τύπος κορυφής typedef unsigned vertex; Ορισμός τύπου graph typedef struct node_tag { vertex v; struct node_tag * next; } node, * graph[];
11-17 Λίστα γειτονικών κορυφών(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; }
11-18 Λίστα γειτονικών κορυφών(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; }
11-19 Λίστα γειτονικών κορυφών(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; }
11-20 Λίστα γειτονικών κορυφών(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); }
11-21 Διάσχιση γράφων(i) Κατά βάθος –ξεκινώντας από την κορυφή 0: –0, 1, 2, 6, 3, 4, 5, 7 Κατά πλάτος –ξεκινώντας από την κορυφή 0: –0, 1, 4, 2, 3, 5, 7,
11-22 Διάσχιση γράφων(ii) Υλοποίηση διάσχισης κατά βάθος σε παράσταση λίστας γειτονικών κορυφών void traverseDFS (graph g) { bool visited[N]; vertex v; for (v=0; v<N; v++) visited[v] = false; traverseDFS_aux(g, visited, 0); }
11-23 Διάσχιση γράφων(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); }
11-24 Διάσχιση γράφων(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);
11-25 Διάσχιση γράφων(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); }