Αλγόριθμοι Γραφημάτων 1. Minimum Spanning Trees 2. Αλγόριθμος Prim 3. Αλγόριθμος Kruskal Εισαγωγή στην Ανάλυση Αλγορίθμων Μάγια Σατρατζέμη
Minimum Spanning Tree Πρόβλημα: Για δοσμένο συνεκτικό, μη προσανατολισμένο, με βάρος γράφημα. 6 4 14 10 2 1 3 8 2
Minimum Spanning Tree Πρόβλημα: Για δοσμένο συνεκτικό, μη προσανατολισμένο, με βάρος γράφημα, να βρεθεί ένα δένδρο κάλυμμα (spanning tree) χρησιμοποιώντας ακμές που ελαχιστοποιούν το συνολικό βάρος. 6 4 14 10 2 1 3 8 3
Ορισμοί Δένδρο κάλυμμα (spanning tree) είναι ένα μερικό γράφημα του συνεκτικού γραφήματος G που είναι δένδρο. Δένδρο: συνεκτικό άκυκλο γράφημα Ισοδύναμες προτάσεις Συνεκτικό με n-1 ακμές Άκυκλο με n-1 ακμές Κάθε ζεύγος κορυφών συνδέεται με ένα μόνο μονοπάτι Αν ενωθούν 2 μη γειτονικές κορυφές με μια ακμή σχηματίζεται κύκλο. 4
Ορισμοί Ένα γράφημα g ονομάζεται μερικό γράφημα (partial graph) του γραφήματος G= (V, E) αν οι κορυφές του g είναι οι κορυφές του G και οι ακμές του g είναι υποσύνολο των ακμών του G, δηλαδή g = (V, E ), όπου Ε Ε. Ελάχιστο Δένδρο Κάλυμμα ή Ελαφρύτατου Συνδετικού Δένδρου (Minimum Spanning Tree) το δένδρο κάλυμμα με το ελάχιστο συνολικό βάρος ακμών.
Minimum Spanning Tree Ποιες ακμές σχηματίζουν Ελάχιστο Δένδρο Κάλυμμα (Minimum Spanning Tree MST) στο παρακάτω γράφημα? A 6 4 H B C 14 10 2 G E 1 D 3 F 8 6
Minimum Spanning Tree Απάντηση: A 6 4 H B C 14 10 2 G E 1 D 3 F 8 7
Επέκταση MST Εστω ένα μη προσανατολισμένο γράφημα G = (V, E) με συνάρτηση βάρους w : E R, και ζητείται να προσδιορίσουμε το MST για το G. Οι 2 αλγόριθμοι που θα μελετήσουμε χρησιμοποιούν μια άπληστη προσέγγιση για την επίλυση του προβλήματος. Η άπληστη στρατηγική αποτυπώνεται στον παρακάτω αλγόριθμο «αρχέτυπο», ο οποίος επεκτείνει το MST κατά μια ακμή κάθε φορά. Ο αλγόριθμος διαχειρίζεται ένα σύνολο ακμών Α τηρώντας την ακόλουθη αναλλοίωτη συνθήκη βρόχου: 8
Επέκταση MST αναλλοίωτη συνθήκη βρόχου : Πριν από κάθε επανάληψη το Α αποτελεί ένα υποσύνολο κάποιου ελαφρύτατου δένδρου καλύμματος (MST). Σε κάθε βήμα προσδιορίζεται η ακμή (u, v) η οποία μπορεί να προστεθεί στο σύνολο Α χωρίς να παραβιαστεί η παραπάνω αναλλοίωτη συνθήκη, με την έννοια ότι το σύνολο Α {(u, v)} αποτελεί επίσης υποσύνολο κάποιου MST. Μια τέτοια ακμή ονομάζεται ασφαλής για το σύνολο Α, διότι μπορεί να προστεθεί χωρίς να πάψει να ισχύει η αναλλοίωτη συνθήκη.
Επέκταση MST Αρχέτυπος αλγόριθμος για MST 1. Α 2. Οσο το Α δεν αποτελεί δένδρο κάλυμμα 3. προσδιόρισε μια ακμή που είναι ασφαλής για το Α 4. Α Α {(u, v)}. Επιστροφή Α Η ύπαρξη ασφαλούς ακμής είναι βέβαιη καθώς όταν εκτελείται η γραμμή 3 η αναλλοίωτη συνθήκη ορίζει ότι υπάρχει ένα ΣΔ Τ τέτοιο ώστε Α Τ. Μέσα στο βρόχο το Α θα πρέπει να είναι γνήσιο υποσύνολο του Τ, και άρα θα πρέπει να υπάρχει ακμή (u, v) Τ τέτοια ώστε (u, v) Α και η (u, v) να είναι ασφαλής για το Α. 10
Επέκταση MST Θεώρημα Εστω συνεκτικό μη προσανατολισμένο γράφημα G = (V, E) με συνάρτηση βάρους w : E R. Εστω Α ένα υποσύνολο του Ε το οποίο εμπεριέχεται σε κάποιο MST για το G, έστω (S, V-S) οποιαδήποτε τομή του G η οποία σέβεται το Α, και έστω (u, v) μια ελαφρά ακμή Α ως προς τη διάσχιση της (S, V-S). Στην περίπτωση αυτή η ακμή (u, v) είναι ασφαλής για το Α. Τομή (cut) (S, V-S) ενός μη προσανατολισμένου γραφήματος είναι μια διαμέριση του V. Η ακμή (u, v) Ε διασχίζει την τομή (cross) (S, V-S) αν ένα από τα άκρα της βρίσκεται στο S και το άλλο στο V-S Μια τομή σέβεται (respect) ένα σύνολο ακμών Α αν καμιά ακμή του συνόλου Α δε διασχίζει την τομή. Μια ακμή που διασχίζει κάποια τομή χαρακτηρίζεται ως ελαφρά (light edge) ως προς τη διάσχιση της τομής αν το βάρος της είναι το ελάχιστο μεταξύ των βαρών όλων των ακμών που διασχίζουν την τομή. 11
Επέκταση MST 12
Επέκταση MST Πόρισμα Εστω συνεκτικό μη προσανατολισμένο γράφημα G = (V, E) με συνάρτηση βάρους w : E R. Εστω Α ένα υποσύνολο του Ε το οποίο εμπεριέχεται σε κάποιο MST για το G, και C= (Vc, Ec) μια συνδεδεμένη συνιστώσα (ένα δένδρο) στο δάσος G A =(V, A). Αν (u, v) είναι μια ελαφρά ακμή ως προς τη σύνδεση της C με κάποια άλλη συνιστώσα του G A, τότε η ακμή (u, v) είναι ασφαλής για το Α. 13
Αλγόριθμοι για το Minimum Spanning Tree Οι 2 αλγόριθμοι για την εύρεση του MST αποτελούν τελειοποιημένες εκδόσεις του αρχέτυπου αλγόριθμου. Καθένας χρησιμοποιεί ένα συγκεκριμένο κανόνα για τον προσδιορισμό μιας ασφαλούς ακμής στη γραμμή 3 του Αρχέτυπου αλγόριθμου για ΕΔΚ. Στον αλγόριθμο του Prim το σύνολο Α συνιστά ένα μοναδικό δένδρο. Η ασφαλής ακμή που προστίθεται στο Α είναι πάντοτε μια ακμή ελαχίστου βάρους στο γράφημα η οποία συνδέει το δένδρο με έναν κόμβο εκτός του δένδρου. Στον αλγόριθμο του Kruskal σύνολο Α είναι ένα δάσος. Η ασφαλής ακμή που προστίθεται στο Α είναι πάντοτε μια ακμή ελαχίστου βάρους η οποία συνδέει δυο διαφορετικές συνιστώσες 14
Prim s Algorithm MST-Prim(G, w, r) Q = V[G]; for each u Q key[u] = ; key[r] = 0; p[r] = NULL; while (Q not empty) u = ExtractMin(Q); w(u, v) βάρος ακμής (u, v) for each v Adj[u] if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 1
Prim s Algorithm Μια βασική ιδιότητα του αλγόριθμου του Prim είναι ότι οι ακμές του συνόλου Α σχηματίζουν πάντα ένα δένδρο ακριβώς. Το δένδρο ξεκινά από έναν αυθαίρετο ριζικό κόμβο r και επεκτείνεται μέχρι να καλύψει όλους τους κόμβους του συνόλου V. Σε κάθε βήμα προστίθεται στο Α μια ελαφρά ακμή ως προς τη σύνδεση του Α με κάποιο απομονωμένο κόμβο του γραφήματος G A =(V, A). Με τον κανόνα αυτόν προστίθενται πάντα ασφαλείς ακμές για το Α, επομένως όταν ο αλγόριθμος τερματίζει οι ακμές του συνόλου Α συνιστούν ένα MST. Η παραπάνω στρατηγική είναι άπληστη γιατί σε κάθε βήμα το δένδρο επεκτείνεται κατά μια ακμή η οποία το επιβαρύνει με την ελάχιστη δυνατή ποσότητα. 16
Prim s Algorithm Βασικός παράγοντας για την ταχεία υλοποίηση του αλγόριθμου είναι να διευκολύνουμε την επιλογή της νέας ακμής που θα προστεθεί στο δένδρο το οποίο σχηματίζεται από τις ακμές του συνόλου Α. Ολοι οι κόμβοι που δεν ανήκουν στο δένδρο είναι καταχωρισμένοι σε μια ουρά προτεραιότητας ελαχίστου (minimum heap) Q με βάση το key. Για κάθε κόμβο v το key[v] ισούται με το ελάχιστο από τα βάρη των ακμών που συνδέουν τον v με κάποιον κόμβο του δένδρου. Αν δεν υπάρχει τέτοια ακμή θεωρούμε key[v] =. To p[v] υποδεικνύει τον προκάτοχο (πρόγονο) του v στο δένδρο. Κατά τη διάρκεια εκτέλεσης το σύνολο Α τηρείται σιωπηρά ως A {( v, p[ v] ) v V { r} Q} = : Όταν ο αλγόριθμος τερματίζει η ουρά προτεραιότητας ελαχίστου Q είναι κενή επομένως το MST Α για το G είναι A {( v, p[ v] ) v V { r } = : 17
MST-Prim(G, w, r) 1. Q = V[G]; 2. for each u Q 3. key[u] = ; 4. key[r] = 0;. p[r] = NULL; 6. while (Q not empty) 7. u = ExtractMin(Q); 8. for each v Adj[u] Prim s Algorithm. if (v Q and w(u,v) < key[v]) 10. p[v] = u; 11. key[v] = w(u,v); Στις γραμμές 1- ορίζεται για όλους τους κόμβους key[u] = εκτός για τον κόμβο r, που τίθεται key[r]=0 αφού θα εξεταστεί πρώτος. Η ουρά προτεραιότητας ελαχίστου Q περιέχει αρχικά το σύνολο των κόμβων. Ο αλγόριθμος τηρεί την τριμερή αναλλοίωτη συνθήκη. 1. {( v, p[ v] ) v V { r} Q} A = : 2. Οι κόμβοι που έχουν περιληφθεί στο MST είναι εκείνοι που ανήκουν στο σύνολο V - Q. 3. Για όλους τους κόμβους v Q αν p[v] NULL τότε key[v]< και key[v] ισούται με το βάρος μιας ελαφράς ακμής (v, p[v]) ως προς τη σύνδεση του v με τους κόμβους που ανήκουν ήδη στο MST Στη γραμμή 7 προσδιορίζεται ως κόμβος u Q το άκρο μιας ελαφράς ακμής ως προς τη διάσχιση της τομής (V-Q, Q) (εκτός από την 1 η επανάληψη, όπου λόγω της γραμμής 4 έχουμε u = r). Με την αφαίρεση του κόμβου u από το σύνολο Q, ο u προστίθεται αυτομάτως στο σύνολο V-Q των κόμβων που ανήκουν στο δένδρο, ενώ η ακμή (u, p[u]) προστίθεται στο Α. Ο βρόχος for στις γραμμές 8-11 ενημερώνει τα key και p όλων των κόμβων που γειτνιάζουν με τον u αλλά δεν ανήκουν στο MST. Η ενημέρωση αυτή εξασφαλίζει την τήρηση του 3 ου μέρους της αναλλοίωτης συνθήκης. 18
Prim s Algorithm MST-Prim(G, w, r) Q = V[G]; 6 4 for each u Q key[u] = ; 14 10 2 key[r] = 0; 1 p[r] = NULL; 3 8 while (Q not empty) u = ExtractMin(Q); Τρέχοντας ένα παράδειγμα for each v Adj[u] if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 1
Prim s Algorithm MST-Prim(G, w, r) 6 4 Q = V[G]; for each u Q key[u] = ; 14 10 2 key[r] = 0; 1 p[r] = NULL; 3 while (Q not empty) 8 u = ExtractMin(Q); Τρέχοντας ένα παράδειγμα for each v Adj[u] if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 20
Prim s Algorithm MST-Prim(G, w, r) Q = V[G]; for each u Q key[u] = ; 14 key[r] = 0; r p[r] = NULL; while (Q not empty) u = ExtractMin(Q); for each v Adj[u] 6 4 10 2 1 0 if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 3 8 Επιλέξτε μια οποιαδήποτε κορυφή ως αρχική r 21
Prim s Algorithm MST-Prim(G, w, r) Q = V[G]; for each u Q key[u] = ; 14 key[r] = 0; u p[r] = NULL; while (Q not empty) u = ExtractMin(Q); for each v Adj[u] 6 4 10 2 1 0 if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 3 8 Κόκκινες κορυφές έχουν απομακρυνθεί από την Q 22
Prim s Algorithm MST-Prim(G, w, r) Q = V[G]; for each u Q key[u] = ; 14 key[r] = 0; u p[r] = NULL; while (Q not empty) u = ExtractMin(Q); for each v Adj[u] 6 4 10 2 1 0 if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 3 3 8 Κόκκινες κορυφές έχουν απομακρυνθεί από την Q 23
Prim s Algorithm MST-Prim(G, w, r) 6 4 Q = V[G]; 14 for each u Q key[u] = ; 14 10 2 key[r] = 0; 1 u 0 p[r] = NULL; 3 while (Q not empty) 3 8 u = ExtractMin(Q); for each v Adj[u] if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 24
Prim s Algorithm MST-Prim(G, w, r) 6 4 Q = V[G]; 14 for each u Q key[u] = ; 14 10 2 key[r] = 0; 1 0 p[r] = NULL; 3 while (Q not empty) 3 8 u u = ExtractMin(Q); for each v Adj[u] if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 2
Prim s Algorithm MST-Prim(G, w, r) 6 4 Q = V[G]; 14 for each u Q key[u] = ; 14 10 2 key[r] = 0; 1 0 8 p[r] = NULL; 3 while (Q not empty) 3 8 u u = ExtractMin(Q); for each v Adj[u] if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 26
Prim s Algorithm MST-Prim(G, w, r) 6 4 Q = V[G]; 10 for each u Q key[u] = ; 14 10 2 key[r] = 0; 1 0 8 p[r] = NULL; 3 while (Q not empty) 3 8 u u = ExtractMin(Q); for each v Adj[u] if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 27
Prim s Algorithm MST-Prim(G, w, r) 6 4 Q = V[G]; 10 for each u Q key[u] = ; 14 10 2 key[r] = 0; 1 0 8 p[r] = NULL; 3 while (Q not empty) 3 8 u u = ExtractMin(Q); for each v Adj[u] if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 28
Prim s Algorithm MST-Prim(G, w, r) 6 4 Q = V[G]; 10 2 for each u Q key[u] = ; 14 10 2 key[r] = 0; 1 0 8 p[r] = NULL; 3 while (Q not empty) 3 8 u u = ExtractMin(Q); for each v Adj[u] if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 2
Prim s Algorithm MST-Prim(G, w, r) 6 4 Q = V[G]; 10 2 for each u Q key[u] = ; 14 10 2 key[r] = 0; 1 0 8 p[r] = NULL; 3 while (Q not empty) 3 8 u 1 u = ExtractMin(Q); for each v Adj[u] if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 30
Prim s Algorithm MST-Prim(G, w, r) 6 4 u Q = V[G]; 10 2 for each u Q key[u] = ; 14 10 2 key[r] = 0; 1 0 8 p[r] = NULL; 3 while (Q not empty) 3 8 1 u = ExtractMin(Q); for each v Adj[u] if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 31
Prim s Algorithm MST-Prim(G, w, r) 6 4 u Q = V[G]; 10 2 for each u Q key[u] = ; 14 10 2 key[r] = 0; 1 0 8 p[r] = NULL; 3 while (Q not empty) 3 8 1 u = ExtractMin(Q); for each v Adj[u] if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 32
Prim s Algorithm MST-Prim(G, w, r) 6 4 4 u Q = V[G]; 10 2 for each u Q key[u] = ; 14 10 2 key[r] = 0; 1 0 8 p[r] = NULL; 3 while (Q not empty) 3 8 1 u = ExtractMin(Q); for each v Adj[u] if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 33
Prim s Algorithm MST-Prim(G, w, r) 6 4 4 u Q = V[G]; 2 for each u Q key[u] = ; 14 10 2 key[r] = 0; 1 0 8 p[r] = NULL; 3 while (Q not empty) 3 8 1 u = ExtractMin(Q); for each v Adj[u] if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 34
Prim s Algorithm u MST-Prim(G, w, r) 6 4 4 Q = V[G]; 2 for each u Q key[u] = ; 14 10 2 key[r] = 0; 1 0 8 1 p[r] = NULL; 3 while (Q not empty) 3 8 u = ExtractMin(Q); for each v Adj[u] if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 3
Prim s Algorithm MST-Prim(G, w, r) u 6 4 4 Q = V[G]; 2 for each u Q key[u] = ; 14 10 2 key[r] = 0; 1 0 8 p[r] = NULL; 3 while (Q not empty) 3 8 1 u = ExtractMin(Q); for each v Adj[u] if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 36
Prim s Algorithm u MST-Prim(G, w, r) 6 4 4 Q = V[G]; 2 for each u Q key[u] = ; 14 10 2 key[r] = 0; 1 0 8 1 p[r] = NULL; 3 while (Q not empty) 3 8 u = ExtractMin(Q); for each v Adj[u] if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 37
Prim s Algorithm MST-Prim(G, w, r) 6 4 4 Q = V[G]; 2 for each u Q key[u] = ; 14 10 2 u key[r] = 0; 1 0 8 1 p[r] = NULL; 3 while (Q not empty) 3 8 u = ExtractMin(Q); for each v Adj[u] if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); 38
Ανάλυση: Prim s Algorithm MST-Prim(G, w, r) Q = V[G]; for each u Q key[u] = ; key[r] = 0; p[r] = NULL; while (Q not empty) u = ExtractMin(Q); for each v Adj[u] Ποιο είναι το κρυμμένο κόστος στον αλγόριθμο? if (v Q and w(u,v) < key[v]) p[v] = u; key[v] = w(u,v); Αντικαθιστά την τιμή του key του κόμβου v με την τιμή w(u,v) η οποία θα πρέπει να είναι μικρότερη ή ίση της τρέχουσας τιμής του key[v] 3
Ανάλυση: Prim s Algorithm MST-Prim(G, w, r) Q = V[G]; for each u Q key[u] = ; key[r] = 0; p[r] = NULL; while (Q not empty) u = ExtractMin(Q); for each v Adj[u] if (v Q and w(u,v) < key[v]) p[v] = u; DecreaseKey(v, w(u,v)); H DecreaseKey(v, w(u,v)) Αντικαθιστά την τιμή του key του κόμβου v με την τιμή w(u,v) η οποία θα πρέπει να είναι μικρότερη ή ίση της τρέχουσας τιμής του key[v] 40
Ανάλυση : Prim s Algorithm MST-Prim(G, w, r) Q = V[G]; for each u Q key[u] = ; key[r] = 0; p[r] = NULL; while (Q not empty) u = ExtractMin(Q); for each v Adj[u] Πόσο συχνά καλείται η ExtractMin()? Πόσο συχνά καλείται η DecreaseKey()? if (v Q and w(u,v) < key[v]) p[v] = u; DecreaseKey(v, w(u,v)); 41
Ανάλυση: Prim s Algorithm Θ(V) συνολικά MST-Prim(G, w, r) 1 Q = V[G]; 2 for each u Q 3 key[u] = ; 4 key[r] = 0; p[r] = NULL; 6 while (Q not empty) 7 u = ExtractMin(Q); 8 for each v Adj[u] if (v Q and w(u,v) < key[v]) 10 p[v] = u; 11 key[v] = w(u,v); 42
Ανάλυση : Prim s Algorithm Θ(V) συνολικά V φορές MST-Prim(G, w, r) 1 Q = V[G]; 2 for each u Q 3 key[u] = ; 4 key[r] = 0; p[r] = NULL; 6 while (Q not empty) 7 u = ExtractMin(Q); 8 for each v Adj[u] if (v Q and w(u,v) < key[v]) 10 p[v] = u; 11 key[v] = w(u,v); 43
Ανάλυση : Prim s Algorithm Θ(V) συνολικά V φορές MST-Prim(G, w, r) 1 Q = V[G]; 2 for each u Q 3 key[u] = ; 4 key[r] = 0; p[r] = NULL; 6 while (Q not empty) 7 u = ExtractMin(Q); 8 for each v Adj[u] if (v Q and w(u,v) < key[v]) degree(u) 10 p[v] = u; φορές 11 key[v] = w(u,v); 44
Ανάλυση : Prim s Algorithm Θ(V) συνολικά V φορές MST-Prim(G, w, r) 1 Q = V[G]; 2 for each u Q 3 key[u] = ; 4 key[r] = 0; p[r] = NULL; 6 while (Q not empty) 7 u = ExtractMin(Q); 8 for each v Adj[u] if (v Q and w(u,v) < key[v]) degree(u) 10 p[v] = u; φορές 11 key[v] = w(u,v); v Adj ( v) = deg ( v) = 2 E v Θ(Ε) DecreaseKey 4
Ανάλυση : Prim s Algorithm Χρόνος = Θ(V). Τ ExtractMin + Θ(E). Τ DecreaseKey Q Τ ExtractMin Τ DecreaseKey Συνολικά πίνακας O(V) O(1) O(V 2 ) δυαδικός σωρός Σωρός Fibonacci O(log 2 V) O(log 2 V) O(E log 2 V) O(log 2 V) O(1) O(E+V log 2 V) 46
Ανάλυση πολυπλοκότητας : Prim s Algorithm Απόδειξη: Η επίδοση του αλγορίθμου του Prim εξαρτάται από τον τρόπο υλοποίησης της ουράς προτεραιότητας ελαχίστου Q (min heap). Αν η Q υλοποιηθεί ως δυαδικός σωρός ελαχίστου η απόδοση αρχικών τιμών στις γραμμές 1- μπορεί να επιτευχθεί σε χρόνο Ο(V) μέσω της διαδικασίας Κατασκευή Σωρού Ελαχίστου (Build-min heap αντίστοιχος του Build-max-heap σε σωρό μεγίστων)). Το σώμα του βρόχου while εκτελείται V φορές και δεδομένου ότι κάθε πράξη Εξαγωγής Ελαχίστου (ExtractMin) διαρκεί χρόνο O(log 2 V) ο συνολικός χρόνος για όλες τις κλήσεις Εξαγωγής Ελαχίστου είναι O(V log 2 V). Ο βρόχος for στις γραμμές 8-11 εκτελείται συνολικά Ο(Ε) φορές αφού το άθροισμα των μηκών όλων των λιστών γειτνίασης είναι 2 Ε. Εντός του βρόχου for ο έλεγχος «συμμετοχής» στη ουρά Q στη γραμμή μπορεί να πραγματοποιηθεί σε σταθερό χρόνο μέσω μιας μοναδικής δύφιας μεταβλητής για κάθε κορυφή, που δείχνει αν η κορυφή ανήκει ή όχι στην Q και ενημερώνεται όταν η κορυφή αφαιρείται από την Q. Η ανάθεση τιμής στη γραμμή 11 περιλαμβάνει μια σιωπηρή πράξη Μείωσης Κλειδιού (DecreaseKey(v, w(u,v))) στο σωρό ελαχίστου μπορεί να υλοποιηθεί σε χρόνο O(log 2 V). O συνολικός χρόνος εκτέλεσης του αλγόριθμου του Prim είναι O(V log 2 V + E log 2 V) = O(E log 2 V). 47
Ανάλυση : Prim s Algorithm MST-Prim(G, w, r) Ποιος είναι ο χρόνος εκτέλεσης? 1 Q = V[G]; A: εξαρτάται από την υλοποίηση της Q 2 for each u Q - με δυαδικό σωρό ελαχίστων: O(E log 2 V) 3 key[u] = ; - με σωρό Fibonacci : O(V log 2 V + E) 4 key[r] = 0; p[r] = NULL; 6 while (Q not empty) 7 u = ExtractMin(Q); 8 for each v Adj[u] if (v Q and w(u,v) < key[v]) 10 p[v] = u; 11 key[v] = w(u,v); 48
Kruskal s Algorithm Ο αλγόριθμος του Kruskal βασίζεται στο αλγόριθμο αρχέτυπο του MST. Προσδιορίζει μια ασφαλή ακμή που θα προστεθεί στο επεκτεινόμενο δάσος εντοπίζοντας, από όλες τις ακμές που συνδέουν 2 οποιαδήποτε δένδρα του δάσους, μια ακμή (u, v) ελαχίστου βάρους. Εστω C1 και C2 τα δένδρα που συνδέονται μεταξύ τους μέσω της ακμής (u, v). Δεδομένου ότι η ακμή (u, v) πρέπει να είναι μια ελαφρά ακμή ως προς τη σύνδεση του C1 με κάποιο άλλο δένδρο, από το Πόρισμα συνεπάγεται ότι η (u, v) είναι ασφαλής για το C1. Ο αλγόριθμος του Kruskal ανήκει στην κατηγορία των άπληστων αλγόριθμων γιατί σε κάθε βήμα προσθέτει στο δάσος μια ακμή με το ελάχιστο βάρος. 4
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); sort E by increasing edge weight w for each (u,v) E (in sorted order) if FindSet(u) FindSet(v) T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 0
Kruskal() { 1. T = ; 2. for each v V 3. MakeSet(v); Kruskal s Algorithm 4. sort E by increasing edge weight w. for each (u,v) E (in sorted order) 6. if FindSet(u) FindSet(v) 7. T = T U {{u,v}}; 8. Union(FindSet(u), FindSet(v)); } Στις γραμμές 1-3 ορίζεται ένα αρχικό σύνολο Τ κενό και δημιουργούνται V δένδρα καθένα απ αυτά περιέχει 1 κόμβο. Στην 4 διατάσσονται οι ακμές του σε αύξουσα διάταξη ως προς το βάρος. 1
Kruskal() { 1. T = ; 2. for each v V 3. MakeSet(v); Kruskal s Algorithm 4. sort E by increasing edge weight w. for each (u,v) E (in sorted order) 6. if FindSet(u) FindSet(v) 7. T = T U {{u,v}}; 8. Union(FindSet(u), FindSet(v)); } Ο βρόχος στις γραμμές -8 ελέγχει για κάθε (u, v) αν τα άκρα της u και v ανήκουν στο ίδιο δένδρο. Αν ανήκουν τότε η προσθήκη της (u, v) θα δημιουργήσει κύκλο και άρα απορρίπτεται. Διαφορετικά οι 2 κόμβοι ανήκουν σε διαφορετικά δένδρα η ακμή (u, v) προστίθεται στο Τ στη γραμμή 7 και οι κόμβοι των 2 δένδρων συγχωνεύονται στη γραμμή 8. 2
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1 3
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1 4
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1? 6
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1 7
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2? 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1 8
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v));? 1 60
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1 61
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8? Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1 62
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1 63
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v));? 1 64
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1 6
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17 13? T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1 66
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1 67
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 14? sort E by increasing edge weight w for each (u,v) E (in sorted order) 21 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1 68
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1 6
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17? 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1 70
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1? sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1 71
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21? 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1 72
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2? if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1 73
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1 74
Kruskal s Algorithm Kruskal() { } T = ; for each v V MakeSet(v); 8 Εκτέλεση αλγόριθμου: 2 1 sort E by increasing edge weight w for each (u,v) E (in sorted order) 14 21 2 if FindSet(u) FindSet(v) 17 13 T = T U {{u,v}}; Union(FindSet(u), FindSet(v)); 1 7
Kruskal s Algorithm: Χρόνος Εκτέλεσης Kruskal() { 1 T = ; 2 for each v V 3 MakeSet(v); 4 sort E by increasing edge weight w for each (u,v) E (in sorted order) 6 if FindSet(u) FindSet(v) 7 T = T U {{u,v}}; 8 Union(FindSet(u), FindSet(v)); } Τι επηρεάζει το χρόνο εκτέλεσης? 76
Ανάλυση πολυπλοκότητας Kruskal s Algorithm Απόδειξη: Ο χρόνος εκτέλεσης του αλγόριθμου του Kruskal εξαρτάται από την υλοποίηση της δομής δεδομένων ξένων συνόλων. Υποθέτουμε ότι ακολουθείται η υλοποίηση του δάσους ξένων συνόλων (κεφ 21 CLRS). Ο αρχικός ορισμός του συνόλου T στην γραμμή 1 απαιτεί χρόνο Ο(1) και η ταξινόμηση των ακμών στην 4 απαιτεί O(Elog 2 E). Ο βρόχος στις γραμμές -8 εκτελεί Ο(Ε) FindSet και Union πράξεις στο δάσος ξένων συνόλων. Μαζί με τις V MakeSet πράξεις, οι εργασίες αυτές απαιτούν συνολικό χρόνο Ο((V + E) α(v)) όπου α βραδύτατα αύξουσα συνάρτηση που ορίζεται στην υλοποίηση του δάσους ξένων συνόλων ( 21.4 CLRS). Δεδομένου ότι το G είναι συνεκτικό έχουμε E V - 1 και επομένως οι πράξεις ξένων συνόλων απαιτούν Ο(Ε α(v)) χρόνο. Επιπλέον α( V ) = Ο(log 2 V)=O(log 2 E) ο συνολικός χρόνος εκτέλεσης του Kruskal είναι Ο(Ε log 2 E). Δεδομένου ότι E < V 2, έχουμε log 2 E =O(log 2 V) και επομένως ο χρόνος εκτέλεσης του αλγορίθμου Kruskal μπορεί να γραφεί O(Ε log 2 V) 77
Kruskal s Algorithm: Χρόνος Εκτέλεσης Kruskal() { 1 T = ; 2 for each v V 3 MakeSet(v); 4 sort E by increasing edge weight w for each (u,v) E (in sorted order) 6 if FindSet(u) FindSet(v) 7 T = T U {{u,v}}; 8 Union(FindSet(u), FindSet(v)); } Τι επηρεάζει το χρόνο εκτέλεσης? 1 Sort O(V) MakeSet() κλήσεις O(E) FindSet() κλήσεις O(V) Union() κλήσεις (πόσες ακριβώς Union()?) 78
Kruskal s Algorithm: Χρόνος Εκτέλεσης Συνοψίζοντας: Sort edges: O(E lοg 2 E) O(V) MakeSet() s O(E) FindSet() s O(V) Union() s Τελικό συμπέρασμα: Ο καλύτερος αλγόριθμος για disjoint-set union εκτελεί τις παραπάνω 3 πράξεις σε O(E α(e,v)), α σχεδόν σταθερή Τελικώς O(E lοg 2 E) O(E lοg 2 V) 7