Αλγόριθμοι και πολυπλοκότητα
Ακαδημαϊκό έτος 2024-2025
Γκόγκος Χρήστος, Τμήμα Πληροφορικής και Τηλεπικοινωνιών, Άρτα, Πανεπιστήμιο Ιωαννίνων
Σελίδα ecourse του μαθήματος ecourse UoI.
Τελευταία ενημέρωση: 17/11/2024
Παρουσιάσεις από το βιβλίο “Αλγόριθμοι Σχεδίαση και Εφαρμογές” των M. Goodrich και R. Tamassia
- Κεφάλαιο 1 - Ανάλυση αλγορίθμων
- Κεφάλαιο 5Α - Ουρές προτεραιότητας
- Κεφάλαιο 5Β - Σωροί
- Κεφάλαιο 6Α - Συσχετιστικοί πίνακες
- Κεφάλαιο 6Β - Πίνακες κατακερματισμού
- Κεφάλαιο 6Γ - Κατερματισμός κούκου
- Κεφάλαιο 7 - Δομή ένωσης/εύρεσης
- Κεφάλαιο 8Α - Ταξινόμηση με συγχώνευση
- Κεφάλαιο 8Β - Γρήγορη ταξινόμηση
- Κεφάλαιο 8Γ - Κάτω όριο ταξινόμησης (με συγκρίσεις)
- Κεφάλαιο 10 - Η άπληστη μέθοδος
- Κεφάλαιο 11 - Διαίρει και βασίλευε
- Κεφάλαιο 12Α - Δυναμικός Προγραμματισμός
- Κεφάλαιο 12Β - Δυναμικός Προγραμματισμός: Προγραμματισμός τηλεσκοπίων
- Κεφάλαιο 12Γ - Δυναμικός Προγραμματισμός: Μέγιστη κοινή υποακολουθία
- Κεφάλαιο 12Δ - Δυναμικός Προγραμματισμός: Πρόβλημα σακιδίου 0-1
- Κεφάλαιο 13Α - Ορολογία και αναπαραστάσεις γράφων
- Κεφάλαιο 13Β - Αναζήτηση πρώτα σε βάθος
- Κεφάλαιο 13Γ - Αναζήτηση πρώτα σε πλάτος
- Κεφάλαιο 14 - Συντομότερες διαδρομές
- Κεφάλαιο 15 - Δέντρα επικάλυψης ελαχίστου κόστους
- Κεφάλαιο 16 - Μέγιστες ροές
- Κεφάλαιο 17Α - NP πληρότητα
- Κεφάλαιο 18 - Προσεγγιστικοί αλγόριθμοι
Θέματα προετοιμασίας
1. Ανάλυση αλγορίθμων
- Khan’s Academy - Asymptotic notation
- Μια εύπεπτη εισαγωγή στην ανάλυση αλγορίθμων
- Αντιστροφή λίστας
- Μέγιστος κοινός διαιρέτης καιν ελάχιστο κοινό πολλαπλάσιο
- Το πρόβλημα του “πειραγμένου” νομίσματος
- Εντοπισμός μέγιστης τιμής ακολουθίας
- Το πρόβλημα της μέγιστης κοινής υποακολουθίας (maxsubarray) max_subarray.ipynb
- Παραδείγματα με υπολογισμό πολυπλοκότητας σε κώδικα Python time_complexity.ipynb
5. Ουρές προτεραιότητας και σωροί
- Οπτικοποίηση δημιουργίας σωρού ελαχίστων (MINHEAP) με διαδοχικές εισαγωγές τιμών: π.χ. χρησιμοποιήστε το πλήκτρο Insert για τη διαδοχική εισαγωγή των τιμών 21,5,17,12,3,9,16 σε έναν σωρό ελαχίστων (David Galles Computer Science University of San Francisco).
- Οπτικοποίηση δημιουργίας σωρού ελαχίστων (MINHEAP) με τη διαδικασία heapify: χρησιμοποιήστε το πλήκτρο BuildHeap για τη δημιουργία ενός σωρού ελαχίστων από έναν πίνακα 31 τιμών με τους ακέραιους από 1 μέχρι και 31 (David Galles Computer Science University of San Francisco).
- Οπτικοποίηση διαφόρων λειτουργιών σε σωρό μεγίστων (MAXHEAP) από το visualgo.net.
Ουρές προτεραιότητας στην Python
- Απλή υλοποίηση σωρού heap_impl.py
- Υλοποίηση σωρού της standard βιβλιοθήκης της Python στο module heapq
- Παράδειγμα: heapq_example.py
Ουρές προτεραιότητας στην C++
Παράδειγμα: priority_queue_example.cpp
Ουρές προτεραιότητας στην Java
Παραδείγματα: Java PriorityQueue by Programiz
Ασκήσεις
- Έστω ένας μηχανισμός παραγωγής πραγματικών τιμών. Όταν παράγεται μια νέα τιμή να υπολογίζεται και να εμφανίζεται η διάμεσος από όλες τις τιμές που έχουν παραχθεί μέχρι εκείνη τη χρονική στιγμή. Γράψτε πρόγραμμα που να υλοποιεί τη λύση.
- Σημείωση 1: η διάμεσος μιας λίστας παρατηρήσεων είναι η τιμή της μεσαίας παρατήρησης στη διατεταγμένη σε αύξουσα σειρά λίστας παρατηρήσεων όταν το πλήθος των παρατηρήσεων είναι περιττό, και το ημιάθροισμα των δύο μεσαίων παρατηρήσεων στη διατεταγμένη σε αύξουσα σειρά λίστας παρατηρήσεων όταν όταν το πλήθος των παρατηρήσεων είναι άρτιο.
- Σημείωση 2: Προσομοιώστε την παραγωγή πραγματικών τιμών με μια λίστα τυχαίων πραγματικών τιμών. Θεωρείστε ότι στη χρονική στιγμή 0 παράγεται η τιμή που βρίσκεται στη θέση 0 της λίστας, στη χρονική στιγμή 1 παράγεται η τιμή που βρίσκεται στη θέση 1 της λίστας κ.ο.κ.
Περιγραφή αλγοριθμικής προσέγγισης Δημιουργούνται δύο σωροί, ένας σωρός μεγίστων (ΜΑΧHEAP) και ένας σωρός ελαχίστων (MINHEAP). Η ρίζα του MAXHEAP θα πρέπει να είναι μικρότερη από τη ρίζα του MINHEAP. Αν αυτό δεν ισχύει θα πρέπει να μεταφέρεται η ρίζα του ενός από τους δύο σωρούς στον άλλο σωρό έτσι ώστε να επιβληθεί αυτή η συνθήκη. Οι εισαγωγές νέων τιμών θα γίνονται πάντα στον MAXHEAP. Οι δύο σωροί θα πρέπει να έχουν το ίδιο μέγεθος ή ο ένας να είναι κατά 1 μόνο στοιχείο μεγαλύτερος του άλλου και όταν αυτό παραβιάζεται θα μεταφέρεται η ρίζα του μεγαλύτερου σωρού στον μικρότερο σωρό. Η διάμεσος θα είναι είτε η ρίζα του μεγαλύτερου σωρού είτε το ημιάθροισμα των ριζών των δύο σωρών. # Ψευδοκώδικας 1. Λήψη νέου ακεραίου και προσθήκη στον MAXHEAP 2. Αν η ρίζα του MAXHEAP είναι μεγαλύτερη από τη ρίζα του MINHEAP τότε αφαίρεσε τη ρίζα του MAXHEAP και πρόσθεσέ την στον MINHEAP 3. Αν το μέγεθος των 2 σωρών διαφέρει κατά 2 αφαίρεσε τη ρίζα από το μεγαλύτερο σωρό και πρόσθεσε την στο μικρότερο σωρό. 4. Η διάμεσος θα είναι o μέσος όρος των κορυφών των 2 σωρών, αν οι σωροί έχουν το ίδιο μέγεθος ή η ρίζα του μεγαλύτερου από τους 2 σωρούς. 5. Επιστροφή στο βήμα 1 ή τερματισμός
- Λύση: heap_exercise2.py
6. Πίνακες αντιστοίχισης
Οι πίνακες αντιστοίχισης ή συσχετιστικοί πίνακες (associative arrays) ή συσχετιστικές μνήμες (associative memories), ή χάρτες (maps), ή χάρτες κατακερματισμού (hashmaps) ή λεξικά (dictionaries) είναι σύνολα ζευγών κλειδί/τιμή. Υποστηρίζουν τις λειτουργίες εντοπισμού (με δεδομένο το κλειδί), εισαγωγής του ζεύγους κλειδί/τιμή΄και διαγραφής (με δεδομένο το κλειδί) με υψηλή ταχύτητα, Ο(1) υπό προϋποθέσεις. Μπορούμε να θεωρούμε ότι οι πίνακες αντιστοίχισης αναφέρονται στον Αφηρημένο Τύπο Δεδομένων (ΑΤΔ), ενώ όταν υπάρχει στο όνομα η λέξη κατακερματισμός ότι μιλάμε για υλοποίηση του ΑΤΔ με κάποια υλοποίηση πίνακα κατακερματισμού.
Λεξικά στην Python
- Dictionaries
- Υλοποίηση των dictionaries στην Python
- The python corner - Python Hash Tables: Understanding dictionaries
Πίνακες αντιστοίχισης στη C++
- unordered_map - υλοποίηση με πίνακα κατακερματισμού
- Παράδειγμα: unordered_map_example.cpp
- map - υλοποίηση πίνακα αντιστοίχισης (με Red-Black δένδρα) με ταξινομημένα κλειδιά
Πίνακες αντιστοίχισης στη Java
Συναρτήσεις κατακερματισμού
Μη κρυπτογραφικές συναρτήσεις κατακερματισμού (χρήση σε δομές δεδομένων)
Κρυπτογραφικές συναρτήσεις κατακερματισμού
Παραδείγματα με hash functions στην Python
- interactive_py_hash.py
- interactive_py_hash2.py κρυπτογραφικες συναρτήσεις κατακερματισμού με το module hashlib
Ελάχιστη τέλεια συνάρτηση κατακερματισμού (minimal perfect hash function)
Τέλεια συνάρτηση κατακερματισμού είναι μια συνάρτηση κατακερματισμού η οποία αντιστοιχίζει τα στοιχεία ενός συνόλου σε ένα σύνολο ακεραίων χωρίς συγκρούσεις. Ελάχιστη τέλεια συνάρτηση κατακερματισμού είναι μια τέλεια συνάρτηση κατακερματισμού που αντιστοιχίζει χωρίς συγκρούσεις n κλειδιά σε n διαδοχικούς ακεραίους από το 0 έως το n-1.
Δείτε και το http://cmph.sourceforge.net/concepts.html
Ανοικτή διευθυνσιοδότηση (open addressing ή closed hashing)
Η ανοικτή διευνσιοδότηση λαμβάνει το όνομά της από την ιδιότητα που έχει να επιτρέπει στα κλειδιά να μετακινηθούν και σε άλλες θέσεις, διαφορετικές από τη θέση στην οποία γίνονται αρχικά hash.
Η ανοικτή διευνσιοδότηση είναι γνωστή και ως κλειστός κατακερματισμός (closed hashing) καθώς τα κλειδία τοποθετούνται μόνο εντός του πίνακα κατακερματισμού και δεν χρησιμοποιείται κάποια άλλη βοηθητική δομή.
- Οπτικοποίηση ανοικτής διευθυνσιοδότησης
Παραλλαγές ανοικτής διευθυνσιοδότησης
- Γραμμική ανίχνευση (linear probing)
- Τετραγωνική ανίχνευση (quadratic probing)
- Διπλός κατακερματισμός (double hashing)
- Τυχαίος κατακερματισμός (random hashing)
Κλειστή διευθυνσιοδότηση (closed addressing ή open hashing ή separate chaining)
Η κλειστή διευθυνσιοδότηση λαμβάνει το όνομά της από την ιδιότητα που έχει να τοποθετεί τα κλειδιά στη θέση στην οποία γίνονται hash, χρησιμοποιώντας μια βοηθητική δομή (π.χ. συνδεδεμένη λίστα) για να αποθηκεύσει στην ίδια θέση πιθανώς περισσότερα από ένα στοιχεία τα οποία γίνονται hash στην ίδια θέση.
Η κλειστή διευθυνσιοδότηση είναι γνωστή και ως ανοικτός κατακερματισμός (open hashing) και ως ξεχωριστή αλυσίδωση (separate chaining). Το όνομα ανοικτός κατακερματισμός προκύπτει καθώς τα κλειδιά δεν είναι απαραίτητο να βρίσκονται εντός του ίδιου του πίνακα κατακερματισμού, αλλά μπορούν να βρίσκονται σε κάποια βοηθητική δομή.
- Οπτικοποίηση κλειστής διευθυνσιοδότησης
Κατακερματισμός κούκου
Ο κατακερματισμός κούκου πετυχαίνει Ο(1) χρόνο χειρότερης περίπτωσης για αναζήτηση και διαγραφή και Ο(1) χρόνο μέσης περίπτωσγης για εισαγωγή.
- Οπτικοποίηση κατακερματισμού κούκου.
Ασκήσεις
- Γράψτε ένα πρόγραμμα που να δέχεται έναν πίνακα ακεραίων και μια τιμή sum και να εμφανίζει όλα τα ζεύγη τιμών του πίνακα με άθροισμα ίσο με την τιμή sum.
- Λύση: hash_exercise1.py
- Γράψτε ένα πρόγραμμα που να εντοπίζει σε ένα λεξικό με μεγάλο πλήθος λέξεων όλες τις λέξεις για τις οποίες υπάρχουν τουλάχιστον άλλες 4 λέξεις που είναι αναγραμματισμοί της (π.χ. user -> [‘rues’, ‘ruse’, ‘suer’, ‘sure’, ‘user’]).
- Λύση: hash_exercise2.py
- Γράψτε ένα προγραμμα που να εντοπίζει το πλήθος των διακριτών ακεραίων σε μια μεγάλη λίστα ακεραίων.
- Λύση: hash_exercise3.py
- Γράψτε ένα πρόγραμμα που να δέχεται έναν πίνακα διακριτών ακεραίων τιμών και να εμφανίζει τον αριθμό κατάταξης κάθε τιμής του πίνακα (π.χ. για τον πίνακα [17, 13, 21, 19] να επιστρέφει [2, 1, 4, 3])
- Λύση: hash_exercise4.py
- Γράψτε ένα πρόγραμμα που να υπολογίζει το πλήθος εμφανίσεων των ελληνικών γραμμάτων (Α-Ω, χωρίς διάκριση σε κεφαλαία ή μικρά) σε ένα δεδομένο κείμενο.
- Λύση: hash_exercise5.py
7. Δομές Ένωσης-Εύρεσης (disjoint sets)
Ασκήσεις
- Δίνεται ένα σύνολο από σχέσεις φιλίας ανάμεσα σε άτομα (κάθε άτομο αναπαρίσταται από έναν αριθμό και η σχέση φιλίας με ένα ζεύγος αριθμών). Εντοπίστε τις ομάδες ατόμων που είναι συνδεδεμένες (π.χ. friends = [[ 1, 0 ], [ 2, 3 ], [ 1, 2 ], [ 4, 5 ]]).
8. Αλγόριθμοι Merge-Sort και Quick-Sort
Οπτικοποιήσεις Quick-Sort και άλλων αλγορίθμων ταξινόμησης
- https://opendsa-server.cs.vt.edu/embed/quicksortAV
- https://www.sortvisualizer.com/
- https://www.hackerearth.com/practice/algorithms/sorting/quick-sort/visualize/
- https://tobinatore.github.io/algovis/sorting.html
Κάτω όριο για ταξινόμηση βασισμένη σε συγκρίσεις στοιχείων
10. Άπληστοι Αλγόριθμοι
Οι άπληστοι αλγόριθμοι εφαρμόζονται σε προβλήματα που έχουν:
- την ιδιότητα της άπληστης επιλογής (greedy choice property), δηλαδή μια βέλτιστη λύση να μπορεί να επιτευχθεί επιλέγοντας τοπικά βέλτιστα.
- την ιδιότητα της βέλτιστης υποδομής (optimal substructure property), δηλαδή η βέλτιστη λύση να μπορεί να σχηματιστεί με βάση βέλτιστες λύσεις σε υποπροβλήματα του προβλήματος.
Παραδείγματα προβλημάτων που λύνονται βέλτιστα με την άπληστη μέθοδο:
- Κλασματικό πρόβλημα σακιδίου (fractional knapsack)
- Χρονοπρογραμματισμός εργασιών με καθορισμένες στιγμές έναρξης και τερματισμού σε πανομοιότυπες μηχανές με στόχο την ελαχιστοποίηση του πλήθους των μηχανών
- Κωδικοποίηση Huffmann
- Αλγόριθμος του Dijkstra για την εύρεση των συντομότερων διαδρομών από μια κορυφή προς όλες τις άλλες κορυφές ενός γράφου χωρίς αρνητικά βάρη
Κωδικοποίηση Huffmann
- https://ben-tanen.com/adaptive-huffman/
- https://www.csfieldguide.org.nz/en/interactives/huffman-tree/
11. Διαίρει και βασίλευε
Διάφορα προβλήματα στα οποία εφαρμόζεται η τεχνική “διαίρει και βασίλευε”:
- Δυαδική αναζήτηση
- Merge-Sort
- Quick-Sort
- Πολλαπλασιασμός ακεραίων με τον αλγόριθμο του Karatsuba
- Πολλαπλασιασμός πινάκων με τον αλγόριθμο του Strassen
- Σύνολο μεγίστων (maxima set)
- Το μάστερ θεώρημα
12. Δυναμικός προγραμματισμός
Υπολογισμός όλων των δυνατών υποακολουθιών συμβολοσειράς με Brute Force
- subsequences1.py με πράξεις σε δυαδικούς αριθμούς
- subsequences2.py επαναληπτικά
- subsequences3.py αναδρομικά
- subsequences4.py με χρήση του itertools
Διάφορα προβλήματα στα οποία εφαρμόζεται η τεχνική του “δυναμικού προγραμματισμού”:
- Μέγιστη κοινή υποακολουθία (LCS - longest common subsequence)
- Γινόμενα αλυσίδας πινάκων
- Προγραμματισμός τηλεσκοπίων (weighted job scheduling problem)
- Πρόβλημα 0-1 σακιδίου (0-1 knapsack)
- Αλγόριθμος των Floyd-Warshall εύρεσης συντομότερων διαδρομών για όλα τα ζεύγη κορυφών σε γράφο
13. Γράφοι
- Αναπαράσταση γράφων
- Λίστα ακμών (edge list)
- Πίνακας γειτονικότητας (adjacency matrix)
- Λίστα γειτονικότητας (adjacency list)
- https://www.khanacademy.org/computing/computer-science/algorithms/graph-representation/a/describing-graphs
- Διάσχιση γράφου πρώτα κατά πλάτος, διάσχιση γράφου πρώτα κατά βάθος
- graph_traversal.py διάσχιση μη κατευθυνόμενου γράφου
- IDEA graph scan
Ακυκλικοί κατευθυνόμενοι γράφοι (DAGs = Directed Acyclic Graphs)
- Τοπολογική ταξινόμηση: τοποθέτηση των κορυφών του DAG σε τέτοια σειρά έτσι ώστε αν υπάρχει ακμή από την κορυφή u στην κορυφή v η κορυφή u να προηγείται στη σειρά της κορυφής v
- Αλγόριθμος του Kahn
Λαβύρινθοι
14. Συντομότερα μονοπάτια
- Αλγόριθμοι single source shortest paths (sssp)
- Αλγόριθμος του Dijkstra (άπληστη μέθοδος)
- Αλγόριθμος των Bellman-Ford (Δυναμικός Προγραμματισμός)
- Αλγόριθμος εύρεσης συντομότερων μονοπατιών σε DAGs
- Αλγόριθμοι all pairs shortest paths (apsp)
- Αλγόριθμος των Floyd-Warshall (Δυναμικός Προγραμματισμός)
15. Ελάχιστα συνεκτικά δέντρα
- Αλγόριθμος των Prim-Jarnik (υλοποίηση με χρήση ουράς προτεραιότητας)
- Αλγόριθμος του Kruskal (υλοποίηση με χρήση ξένων συνόλων)
- Αλγόριθμος του Borůvka
16. Ροή δικτύου και αντιστοίχιση
17. NP-πληρότητα
18. Προσεγγιστικοί αλγόριθμοι
Aσκήσεις
-
Δίνεται μια ακολουθία μεγάλου μεγέθους με τυχαίες ακέραιες τιμές. Ζητείται να βρεθούν οι 10 πλέον συχνές τιμές χρησιμοποιώντας μια ουρά προτεραιότητας. Αναζητήστε την αποδοτικότερη λύση. Γράψτε πρόγραμμα που να υλοποιεί τη λύση.
- Λύση Α: heap_exercise1a.py
- Λύση Β: heap_exercise1b.py
-
Γράψτε πρόγραμμα που να δέχεται τον αριθμό μητρώου και το όνομα, για 10 φοιτητές. Στη συνέχεια να δέχεται επαναληπτικά αριθμούς μητρώου. Αν ο αριθμός μητρώου δεν υπάρχει στους 10 φοιτητές, το πρόγραμμα να τερματίζει, αλλιώς να εμφανίζει το μήνυμα “Γειά σου “ ακολουθούμενο από το όνομα του φοιτητή. Να χρησιμοποιηθεί λεξικό (πίνακας κατακερματισμού).
-
Γράψτε πρόγραμμα που με είσοδο ένα μη ταξινομημένο πίνακα A χωρίς διπλότυπα και μια τιμή d, να εκτυπώνει όλα τα ζεύγη τιμών του Α με διαφορά τιμής d. Για παράδειγμα για Α=[1, 5, 6, 2, 7, 4] και d=3 να εκτυπώνει τα ζεύγη (1,4), (2,5), (4,7). Παρατηρείστε ότι τα ζεύγη εμφανίζονται με πρώτο το μικρότερο στοιχείο κάθε φορά.
Εκμάθηση Python
Εξάσκηση σε διάφορα αλγοριθμικά προβλήματα
Εργασίες παλαιότερων ετών
- 1η εργασία 2021-2022 - το πρόβλημα του μέγιστου υποπίνακα
- 2η εργασία 2021-2022 - Λαβύρινθος με ξένα σύνολα
- 3η εργασία 2021-2022 - Δυναμικός προγραμματισμός, το πρόβλημα της μέγιστης κοινής υποακολουθίας
- 1η εργασία 2023-2024 - Γρήγορος υπολογισμός συγκεντρωτικών χρεώσεων πιστωτικών καρτών
- 2η εργασία 2023-2024 - Χρονοπρογραμματισμός εργασιών σε βιομηχανικό περιβάλλον