Ειδικά θέματα Αλγορίθμων και Δομών Δεδομένων (ΠΛΕ073) Απαντήσεις 1 ου Σετ Ασκήσεων Άσκηση 1 α) Η δομή σταθμισμένης ένωσης με συμπίεση διαδρομής μπορεί να τροποποιηθεί πολύ εύκολα ώστε να υποστηρίζει τις λειτουργίες εύρεσης αντιπροσώπου ενός συνόλου Για το σκοπό αυτό αρκεί να χρησιμοποιήσουμε ένα επιπλέον πίνακα μεγέθους Αν ένας κόμβος είναι ρίζα ενός συνόλου (δηλαδή ενός δένδρου στο δάσος εύρεσηςένωσης) τότε η τιμή δίνει τον αντιπρόσωπο του συνόλου που περιέχει το Επομένως οι λειτουργίες της δομής υλοποιούνται ως εξής: εύρεση( ) : Όπως η λειτουργία find της αρχική δομή σταθμισμένης ένωσης με συμπίεση διαδρομής Ξεκινώντας από το ακολουθούμε τους δείκτες, εκτελώντας την ανάθεση, μέχρι να φτάσουμε στη ρίζα του δένδρου όπου Για κάθε κόμβο που συναντήσαμε σε αυτή τη διαδρομή από το προς τη ρίζα θέτουμε Τέλος επιστρέφουμε το (Προσοχή: η εύρεση( ) επιστρέφει τη ρίζα του δένδρου που περιέχει το που μπορεί να μην είναι ο ίδιος κόμβος με τον αντιπρόσωπο του συνόλου) σύνδεση( ): Είναι μια παραλλαγή της λειτουργίας union της αρχικής δομής σταθμισμένης ένωσης με συμπίεση διαδρομής Εκτελούμε εύρεση( ) και εύρεση( ) Αν τότε και ήδη βρίσκονται στο ίδιο σύνολο και η λειτουργία τερματίζεται Διαφορετικά ελέγχουμε ποια ρίζα έχει τους περισσότερους απογόνους για να γίνει η ρίζα του δένδρου που προκύπτει από την ένωση Αν θέτουμε, και Αλλιώς, αν, θέτουμε, και αντιπρόσωπος( ): Εκτελούμε εύρεση( ) και επιστρέφουμε την τιμή Ο συνολικός χρόνος για οποιαδήποτε ακολουθία πράξεων είναι ασυμπτωτικά ίσος με το χρόνο της αρχικής δομής σταθμισμένης ένωσης με συμπίεση διαδρομής, δηλαδή β) Εκτελούμε καθοδική διερεύνηση από το χρησιμοποιώντας ένα πίνακα μεγέθους (bits) που καταγράφει την κατάσταση του κάθε κόμβου: αν ο κόμβος δεν έχει ανακαλυφθεί ακόμα και αν έχει ολοκληρωθεί η επίσκεψη σε όλους τους απογόνους του Αρχικά για όλους τους κόμβους Έστω ότι καθοδική διερεύνηση βρίσκεται στον κόμβο Εξετάζουμε τα παιδιά του (Υποθέτουμε ότι το δένδρο είναι αποθηκευμένο με λίστες γειτνίασης) Για κάθε παιδί του, επισκεπτόμαστε αναδρομικά το και μετά εκτελούμε σύνδεση( ) Αφού επεξεργαστούμε όλα τα παιδιά του
θέτουμε και εξετάζουμε τη λίστα Για κάθε με θέτουμε αντιπρόσωπος ( ) Συνοπτικά η αναδρομική ρουτίνα επίσκεψής είναι: για κάθε παιδί του σύνδεση( ) για κάθε κόμβο αν τότε αντιπρόσωπος( ) και καλείται από τη ρουτίνα: για κάθε κόμβο του αρχικοποίησε τη δομή εύρεσης-ένωσης Θα αποδείξουμε τώρα την ορθότητα του παραπάνω αλγορίθμου Για το σκοπό αυτό αρκεί να δείξουμε ότι ο αλγόριθμος υπολογίζει σωστά τον για δύο αυθαίρετους κόμβους και του ( ) Υποθέτουμε, χωρίς βλάβη της γενικότητας, ότι ο αλγόριθμος επισκέφτηκε τον πριν επισκεφτεί τον Διακρίνουμε δύο περιπτώσεις: 1) Ο είναι πρόγονος του στο Τότε έχουμε Έστω το παιδί του που είναι πρόγονος του ( αν ο είναι παιδί του ) Όταν καλείται η έχουμε και επομένως ο υπολογίζεται όταν ολοκληρωθούν οι επισκέψεις στα παιδιά του Αμέσως πριν την κλήση αντιπρόσωπος( ) έχουμε, και βρίσκονται στο ίδιο σύνολο στη δομή εύρεσης-ένωσης και έχει εκτελεστεί η σύνδεση( ) Επομένως αντιπρόσωπος( ) 2) Οι και δεν έχουν σχέση προγόνου-απογόνου στο
Έστω Επιπλέον, έστω το παιδί του που είναι πρόγονος του και έστω το παιδί του που είναι πρόγονος του Όταν καλείται η έχουμε και επομένως ο υπολογίζεται όταν ολοκληρωθούν οι επισκέψεις στα παιδιά του Αμέσως πριν την κλήση αντιπρόσωπος( ) έχουμε, και βρίσκονται στο ίδιο σύνολο στη δομή εύρεσης-ένωσης και έχει εκτελεστεί η σύνδεση( ) Επιπλέον, αφού δεν έχει ολοκληρωθεί η επίσκεψη στον δεν έχει εκτελεστεί η σύνδεση του με το γονέα του στο Επομένως αντιπρόσωπος( ) Τέλος, αναλύουμε το χρόνο εκτέλεσης του αλγορίθμου Ο χρόνος που απαιτείται για τη διάσχιση του (καθοδική διερεύνηση) χωρίς τις πράξεις της δομής εύρεσης-ένωσης είναι Επιπλέον, εκτελούνται πράξεις σύνδεσης και πράξεις εύρεσης αντιπροσώπου Επομένως, ο συνολικός χρόνος είναι, όπου Άσκηση 2 α) Έστω ότι έχουμε αποθηκεύσει στοιχεία Η δομή μας διατηρεί μετά από κάθε πράξη εισαγωγής την ακόλουθη αναλλοίωτη συνθήκη Αναλλοίωτη συνθήκη: Έστω η δυαδική αναπαράσταση του, όπου Η δομή μας έχει διατεταγμένους πίνακες,, όπου ο αποθηκεύει στοιχεία αν, διαφορετικά (όταν ) ο είναι κενός Καθένα από τα στοιχεία αποθηκεύεται σε ένα μόνο πίνακα Για την αναζήτηση ενός στοιχείου στην παραπάνω δομή πρέπει να εκτελέσουμε δυαδική αναζήτηση σε κάθε πίνακα Η δυαδική αναζήτηση στον εκτελείται σε χρόνο για, και σε χρόνο για Επομένως, ο συνολικός χρόνος αναζήτησης είναι β) Για να διευκολύνουμε την πράξη εισαγωγής ενός νέου στοιχείου, διατηρούμε ένα δυαδικό μετρητή της τιμής του και ένα bit κρατούμενου Όταν εισάγεται ένα νέο στοιχείο δημιουργούμε ένα νέο πίνακα που αποθηκεύει το νέο στοιχείο και θέτουμε Στη συνέχεια εξετάζουμε τα bit του μετρητή, ξεκινώντας από το λιγότερο σημαντικό bit προς το πιο σημαντικό bit και
σταματάμε όταν Στην πορεία συγχωνεύουμε πίνακες της δομής ώστε να αποκαταστήσουμε την αναλλοίωτη συνθήκη, ως εξής Έστω ότι Τότε θέτουμε,, και, οπότε και τερματίζει η διαδικασία εισαγωγής Διαφορετικά, αν, συγχωνεύουμε τους πίνακες και δημιουργώντας ένα νέο διατεταγμένο πίνακα με δύο στοιχεία και θέτουμε, και Συνεχίζουμε με το επόμενο bit Γενικά όταν εξετάζουμε το bit έχουμε ένα προσωρινό πίνακα με στοιχεία και Αν τότε θέτουμε,, και, οπότε και τερματίζει η διαδικασία εισαγωγής Διαφορετικά, αν, συγχωνεύουμε τους πίνακες και δημιουργώντας ένα νέο διατεταγμένο πίνακα με στοιχεία και θέτουμε, και Συνεχίζουμε με το επόμενο bit Στη χειρότερη περίπτωση έχουμε αρχικά για όλα τα Επομένως, για κάθε, συγχωνεύουμε δύο πίνακες μεγέθους Αυτό γίνεται σε χρόνο (Θυμηθείτε ότι η συγχώνευση διατεταγμένων ακολουθιών είναι η βασική υπορουτίνα του αλγόριθμου ταξινόμησης mergesort) Επομένως, ο χρόνος εισαγωγής στη χειρότερη περίπτωση είναι Αναλύουμε τώρα τον αντισταθμιστικό χρόνο εισαγωγής χρησιμοποιώντας την αθροιστική μέθοδο (Μπορείτε να δοκιμάσετε μόνοι σας και τις άλλες δύο μεθόδους) Η ανάλυση είναι ανάλογη του παραδείγματος επαύξησης δυαδικού μετρητή Υποθέτουμε ότι η δομή μας είναι αρχικά κενή Παρατηρούμε ότι το bit του μετρητή αλλάζει μετά από επαυξήσεις Άρα συγχωνεύουμε δύο πίνακες μεγέθους κάθε εισαγωγές, δηλαδή συνολικά φορές μετά από εισαγωγές Επομένως ο συνολικός χρόνος εκτέλεσης για εισαγωγές είναι ανάλογος του Άρα ο αντισταθμιστικός χρόνος εισαγωγής είναι γ) Η διαγραφή μας προκαλεί κάποια προβλήματα σε αυτή τη δομή Αν προσπαθήσουμε να διατηρήσουμε την αναλλοίωτη συνθήκη τότε ο αντισταθμιστικός χρόνος εισαγωγής ή διαγραφής γίνεται (Σκεφτείτε πχ να έχουμε για όλα τα και στη συνέχεια να διαγράφουμε και να εισάγουμε διαδοχικά ένα στοιχείο) Μια ιδέα είναι να χαλαρώσουμε τη δομή μας ώστε να επιτρέπει την αποθήκευση στοιχείων που έχουν διαγραφεί Ονομάζουμε τέτοια στοιχεία μη ενεργά Ονομάζουμε τα υπόλοιπα στοιχεία της δομής που δεν έχουν διαγραφεί ενεργά Μαζί με κάθε πίνακα αποθηκεύουμε και έναν αντίστοιχο πίνακα μεγέθους με bit σήμανσης: Αν το στοιχείο
στη θέση του πίνακα είναι μη ενεργό τότε θέτουμε, διαφορετικά Έτσι η διαγραφή ενός στοιχείου [j] γίνεται σε χρόνο αφού απλά θέτει (Υποθέτουμε ότι είναι γνωστή η θέση του στοιχείου που διαγράφουμε, διαφορετικά πρέπει να προηγηθεί αναζήτηση) Παρατηρούμε ότι η δυαδική αναζήτηση στον δεν επηρεάζεται από την παραπάνω αλλαγή: Ένα μη ενεργό στοιχείο μπορεί ακόμα να χρησιμοποιηθεί κατά την αναζήτηση αφού δεν καταστρέφει τη διάταξη των στοιχείων στο Η μόνη διαφορά είναι ότι αν η αναζήτηση επιστρέψει ένα μη ενεργό στοιχείο [j] τότε δηλώνουμε ότι το δε βρέθηκε στη δομή Παρατηρούμε ακόμα ότι η παραπάνω υλοποίηση διατηρεί την αναλλοίωτη συνθήκη με τη διαφορά ότι το είναι τώρα ένα άνω φράγμα των ενεργών στοιχείων της δομής Έστω το πλήθος των ενεργών στοιχείων Οι χρόνοι αναζήτησης και εισαγωγής είναι καλοί μόνο εφόσον δεν έχουν διαγραφεί πολλά στοιχεία Για να αντιμετωπίσουμε αυτό το πρόβλημα πρέπει να έχουμε για κάποια σταθερά (πχ ) Μπορούμε να κατασκευάζουμε από την αρχή όλη τη δομή για τα ενεργά μόνο στοιχεία μετά από αρκετές διαγραφές Πχ αν μετά από μια διαγραφή έχουμε τότε καταστρέφουμε όλη τη δομή και εισάγουμε ξανά (σε αρχικά κενή δομή) μόνο τα ενεργά στοιχειά (οπότε μετά από αυτό έχουμε ) Άσκηση 3 α) Μετατρέπουμε το παραπάνω πρόβλημα σε ένα πρόβλημα ανίχνευσης κύκλων αρνητικού βάρους Δημιουργούμε ένα κατευθυνόμενο γράφημα αντιστοιχώντας ένα κόμβο σε κάθε νόμισμα Για κάθε ζεύγος νομισμάτων τοποθετούμε μια ακμή με βάρος Εάν υπάρχει ακολουθία νομισμάτων τέτοια ώστε τότε το γράφημα περιέχει κύκλο με συνολικό βάρος Με τον ίδιο τρόπο δείχνουμε ότι εάν το περιέχει κύκλο αρνητικού βάρους τότε Άρα υπάρχει ευκαιρία για αρμπιτράζ εάν και μόνο εάν το περιέχει κύκλο αρνητικού βάρους, κάτι που μπορεί να ανιχνευτεί σε χρόνο χρησιμοποιώντας τον αλγόριθμο Bellman-Ford με οποιοδήποτε κόμβο ως αφετηρία (Αυτό ισχύει επειδή το γράφημα περιέχει όλες τις δυνατές ακμές Εναλλακτικά μπορούμε να κατασκευάσουμε ένα τεχνητό αφετηριακό κόμβο εισάγοντας τις ακμές με μηδενικό βάρος) β) Ο αλγόριθμος Bellman-Ford (στη βασική του έκδοση) ανιχνεύει την ύπαρξη κύκλου αρνητικού βάρος όταν μετά από επαναλήψεις βρεθεί ακμή με Αυτό σημαίνει ότι το γράφημα προκατόχων έχει κύκλο που
περιλαμβάνει το, ο οποίος αντιστοιχεί σε κύκλο αρνητικού βάρους του Ο κύκλος αυτός μπορεί να βρεθεί ακολουθώντας τους προκατόχους: Ξεκινώντας από το, μεταβαίνουμε στο, μετά στο, και ούτω καθεξής, μέχρι να καταλήξουμε πίσω στο (Στο μάθημα έχουμε δει και βελτιωμένες εκδοχές του Bellman-Ford που ανιχνεύουν έναν κύκλο αρνητικού βάρος με το που θα σχηματιστεί στο γράφημα προκατόχων) Άσκηση 4 α) Έστω ότι έχουμε δύο διατεταγμένες λίστες και, όπου κάθε λίστα είναι αποθηκευμένη σε ένα ισορροπημένο δένδρο δυαδικής αναζήτησης Ο αλγόριθμος συγχώνευσης που θα αναλύσουμε δημιουργεί μια νέα διατεταγμένη λίστα, αρχικά κενή, η οποία μετά τη συγχώνευση θα περιέχει τα στοιχεία των και Για τη συγχώνευση θα χρειαστούμε τις πράξεις αναζήτηση, διαχωρισμός και ένωση οι οποίες εκτελούνται χρόνο χειρότερης περίπτωσης Επιπλέον θα χρειαστούμε την πράξη: ελάχιστο( ): Επιστρέφει το ελάχιστο στοιχείο της λίστας Και αυτή η πράξη μπορεί να εκτελεστεί εύκολα σε ένα ισορροπημένο δένδρο δυαδικής αναζήτησης σε χρόνο Η συγχώνευση πραγματοποιεί το παρακάτω βήμα μέχρι να μείνουν κενές οι και Βήμα συγχώνευσης: Πρώτα εκτελούμε ελάχιστο( ) και ελάχιστο( ) Έστω ότι Τότε εκτελούμε αναζήτηση(, ) η οποία επιστρέφει το μεγαλύτερο στοιχείο της που είναι μικρότερο του Στη συνέχεια εκτελούμε διαχωρισμός(, ) η οποία χωρίζει τη λίστα στη θέση του και επιστρέφει δύο νέες λίστες και όπου η περιέχει τους ακέραιους της που είναι και η περιέχει τους ακέραιους της που είναι Εκτελούμε ένωση(, ) και θέτουμε και Αν εκτελούμε τις ανάλογες πράξεις εναλλάσσοντας το ρόλο των και, και των και Παράδειγμα Αν και τότε έχουμε και Η πράξη αναζήτηση(, ) επιστρέφει Η διαχωρισμός(, ) επιστρέφει και Στη συνέχεια η ένωση(, ) δίνει, οπότε το βήμα τελειώνει με, και Στο επόμενο βήμα και Η πράξη αναζήτηση(, ) επιστρέφει Η διαχωρισμός(, ) επιστρέφει και Στη συνέχεια η ένωση(, ) δίνει, οπότε το βήμα τελειώνει με, και
Στη χειρότερη περίπτωση οι λίστες έχουν στοιχεία και χρειάζονται πράξεις ελάχιστο, αναζήτηση, διαχωρισμός και ένωση (Πχ αν η περιέχει τους περιττούς ακέραιους του συνόλου και η τους άρτιους) Επομένως ο χρόνος μιας συγχώνευσης στη χειρότερη περίπτωση είναι β) Τώρα θέλουμε να δείξουμε ότι ο αντισταθμιστικός χρόνος της συγχώνευσης είναι, ξεκινώντας από λίστες με ένα ακέραιο η κάθε μια Ορίζουμε το δυναμικό ενός ακέραιου ως εξής Έστω ότι ο ανήκει στη λίστα Αν το είναι το μοναδικό στοιχείο της λίστας τότε Διαφορετικά έχουμε τις ακόλουθες περιπτώσεις Αν το είναι το πρώτο στοιχείο της λίστας τότε Αν το είναι το τελευταίο στοιχείο της λίστας τότε Διαφορετικά έχουμε Το ολικό δυναμικό της δομής είναι το άθροισμα των επιμέρους δυναμικών Αρχικά αφού κάθε λίστα έχει μόνο ένα στοιχείο έχουμε Στη συνέχεια κάθε πράξη συγχώνευσης έχει ως αποτέλεσμα τη μείωση του δυναμικού Θα δείξουμε ότι η εκτέλεση δύο διαδοχικών βημάτων συγχώνευσης (όπως ορίστηκαν παραπάνω) έχουν ως αποτέλεσμα τη μείωση του δυναμικού τουλάχιστον κατά μία μονάδα Επομένως σε οποιαδήποτε ακολουθία συγχωνεύσεων μπορούν να εκτελεστούν το πολύ βήματα συγχώνευσης Έστω ότι εκτελούμε πράξεις συγχώνευσης Ο συνολικός αριθμός πράξεων αναζήτησης, διαχωρισμού, ένωσης και εύρεσης ελάχιστου είναι Αφού καθεμιά από τις βασικές πράξεις εκτελείται σε χρόνο έχουμε ότι ο συνολικός χρόνος για πράξεις συγχώνευσης είναι Αυτό σημαίνει ότι ο αντισταθμιστικός χρόνος της συγχώνευσης είναι Απομένει να δείξουμε ότι η εκτέλεση δύο διαδοχικών βημάτων συγχώνευσης ελαττώνουν τη συνάρτηση δυναμικού τουλάχιστον κατά μία μονάδα Έστω ότι εκτελούμε την πράξη συγχώνευση(, ) που δημιουργεί μια νέα λίστα με τα στοιχεία των λιστών και Για να διευκολύνουμε την ανάλυση μπορούμε να υποθέσουμε ότι ελάχιστο( ) ελάχιστο( ) και ότι κάθε βήμα συγχώνευσης εισάγει ένα τμήμα της λίστας μέσα στην (Ο αλγόριθμος συγχώνευσης που περιγράψαμε στο (α) μπορεί να τροποποιηθεί ώστε να ικανοποιεί αυτήν την παραδοχή, αλλά έτσι θα εκτελεί περισσότερες πράξεις) Πχ αν και τότε μετά τα δύο πρώτα βήματα συγχώνευσης έχουμε και Έστω ότι η υπολίστα της εισάγεται μεταξύ των στοιχείων και της Αυτό σημαίνει ότι και άρα ισχύει ή ή και τα δύο (Στο παραπάνω παράδειγμα,,,, οπότε και ) Αν ισχύει η πρώτη ανισότητα τότε το δυναμικό του μειώνεται κατά Έχουμε, άρα Αν ισχύει η δεύτερη ανισότητα τότε το δυναμικό του μειώνεται κατά Έχουμε, άρα