Δομές Δεδομένων. Ενότητα 9: Αναδρομικότητα. Δρ. Γεώργιος Σίσιας Τμήμα Μηχανικών Πληροφορικής ΤΕ



Σχετικά έγγραφα
Δομές Δεδομένων. Ενότητα 2: Περισσότερα για τους δείκτες. Δρ. Γεώργιος Σίσιας Τμήμα Μηχανικών Πληροφορικής ΤΕ

Δομές Δεδομένων. Ενότητα 3: Διαχείριση μνήμης. Δρ. Γεώργιος Σίσιας Τμήμα Μηχανικών Πληροφορικής ΤΕ

Δομές Δεδομένων. Ενότητα 4: Πίνακες. Δρ. Γεώργιος Σίσιας Τμήμα Μηχανικών Πληροφορικής ΤΕ

Δομές Δεδομένων. Ενότητα 5: Στοίβες. Δρ. Γεώργιος Σίσιας Τμήμα Μηχανικών Πληροφορικής ΤΕ

Δομές Δεδομένων Ενότητα 1

Δομές Δεδομένων. Ενότητα 6: Ουρές. Δρ. Γεώργιος Σίσιας Τμήμα Μηχανικών Πληροφορικής ΤΕ

Εισαγωγή στην Διοίκηση Επιχειρήσεων

Προγραμματισμός H/Y Ενότητα 5: Συναρτήσεις. Επικ. Καθηγητής Συνδουκάς Δημήτριος Τμήμα Διοίκησης Επιχειρήσεων (Γρεβενά)

Δομές Δεδομένων. Ενότητα 1: Βασικοί τύποι δεδομένων. Δρ. Γεώργιος Σίσιας Τμήμα Μηχανικών Πληροφορικής ΤΕ

Δομές Δεδομένων. Ενότητα 8: Διπλά συνδεδεμένες λίστες. Δρ. Γεώργιος Σίσιας Τμήμα Μηχανικών Πληροφορικής ΤΕ

Εισαγωγή στους Αλγορίθμους

Εισαγωγή στην Διοίκηση Επιχειρήσεων

Εισαγωγή στην Διοίκηση Επιχειρήσεων

Λογιστική Κόστους Ενότητα 12: Λογισμός Κόστους (2)

Εισαγωγή στους Αλγορίθμους

Διοίκηση Εξωτερικής Εμπορικής Δραστηριότητας

Εισαγωγή στην Διοίκηση Επιχειρήσεων

Εισαγωγή στην Διοίκηση Επιχειρήσεων

Εισαγωγή στους Αλγορίθμους Φροντιστήριο 1

Λογιστική Κόστους Ενότητα 8: Κοστολογική διάρθρωση Κύρια / Βοηθητικά Κέντρα Κόστους.

Προγραμματισμός H/Y Ενότητα 6: Δομές (structures) Επικ. Καθηγητής Συνδουκάς Δημήτριος Τμήμα Διοίκησης Επιχειρήσεων (Γρεβενά)

ΣΥΣΤΗΜΑΤΑ ΗΛΕΚΤΡΙΚΗΣ ΕΝΕΡΓΕΙΑΣ ΙIΙ

ΣΥΣΤΗΜΑΤΑ ΗΛΕΚΤΡΙΚΗΣ ΕΝΕΡΓΕΙΑΣ ΙIΙ

ΣΥΣΤΗΜΑΤΑ ΗΛΕΚΤΡΙΚΗΣ ΕΝΕΡΓΕΙΑΣ ΙIΙ

ΠΛΗΡΟΦΟΡΙΚΗ Ι Ενότητα 9: Αναδρομή

Εισαγωγή στην Διοίκηση Επιχειρήσεων

Προγραμματισμός H/Y Ενότητα 1: Εισαγωγή. Επικ. Καθηγητής Συνδουκάς Δημήτριος Τμήμα Διοίκησης Επιχειρήσεων (Γρεβενά)

Αντικειμενοστρεφής Προγραμματισμός Ενότητα 9: Ειδικά θέματα γλώσσας C/C++. Επικ. Καθηγητής Συνδουκάς Δημήτριος Τμήμα Διοίκησης Επιχειρήσεων (Γρεβενά)

Αντικειμενοστρεφής Προγραμματισμός Ενότητα 2: Κλάσεις. Επικ. Καθηγητής Συνδουκάς Δημήτριος Τμήμα Διοίκησης Επιχειρήσεων (Γρεβενά)

Βάσεις Δεδομένων. Ενότητα 1: Εισαγωγή στις Βάσεις δεδομένων. Πασχαλίδης Δημοσθένης Τμήμα Ιερατικών σπουδών

Προγραμματισμός H/Y Ενότητα 2: Εντολές ελέγχου ροής. Επικ. Καθηγητής Συνδουκάς Δημήτριος Τμήμα Διοίκησης Επιχειρήσεων (Γρεβενά)

Αντικειμενοστρεφής Προγραμματισμός Ενότητα 7: Υπερφόρτωση τελεστών. Επικ. Καθηγητής Συνδουκάς Δημήτριος Τμήμα Διοίκησης Επιχειρήσεων (Γρεβενά)

Μηχανολογικό Σχέδιο Ι

Εισαγωγή στην Διοίκηση Επιχειρήσεων

Εισαγωγή στους Αλγορίθμους

Μεθοδολογία Έρευνας Κοινωνικών Επιστημών Ενότητα 2: ΣΥΓΚΕΝΤΡΩΣΗ ΠΛΗΡΟΦΟΡΙΩΝ ΜΑΡΚΕΤΙΝΓΚ Λοίζου Ευστράτιος Τμήμα Τεχνολόγων Γεωπόνων-Kατεύθυνση

Θερμοδυναμική. Ανοικτά Ακαδημαϊκά Μαθήματα. Πίνακες Νερού σε κατάσταση Κορεσμού. Γεώργιος Κ. Χατζηκωνσταντής Επίκουρος Καθηγητής

Προγραμματισμός H/Y Ενότητα 4: Δείκτες. Επικ. Καθηγητής Συνδουκάς Δημήτριος Τμήμα Διοίκησης Επιχειρήσεων (Γρεβενά)

Δομές Δεδομένων Ενότητα 3

Εισαγωγή στους Αλγορίθμους Ενότητα 10η

Συστήματα Αναμονής. Ενότητα 3: Στοχαστικές Ανελίξεις. Αγγελική Σγώρα Τμήμα Μηχανικών Πληροφορικής ΤΕ

Αντικειμενοστρεφής Προγραμματισμός Ενότητα 1: Εισαγωγή. Επικ. Καθηγητής Συνδουκάς Δημήτριος Τμήμα Διοίκησης Επιχειρήσεων (Γρεβενά)

Συστήματα Αναμονής. Ενότητα 7: Ουρά Μ/Μ/1. Αγγελική Σγώρα Τμήμα Μηχανικών Πληροφορικής ΤΕ

Αντικειμενοστρεφής Προγραμματισμός Ενότητα 5: Κληρονομικότητα. Επικ. Καθηγητής Συνδουκάς Δημήτριος Τμήμα Διοίκησης Επιχειρήσεων (Γρεβενά)

Προγραμματισμός Η/Υ. Ενότητα 3: Top Down Σχεδιασμός

Αντικειμενοστρεφής Προγραμματισμός Ενότητα 3: Constructors και destructors

Διοικητική Λογιστική

Διδακτική της Πληροφορικής

Προγραμματισμός Η/Υ. Βασικές Προγραμματιστικές Δομές. ΤΕΙ Ιονίων Νήσων Τμήμα Τεχνολόγων Περιβάλλοντος Κατεύθυνση Τεχνολογιών Φυσικού Περιβάλλοντος

Οντοκεντρικός Προγραμματισμός

Συστήματα Αναμονής. Ενότητα 5: Ανέλιξη Poisson. Αγγελική Σγώρα Τμήμα Μηχανικών Πληροφορικής ΤΕ

Λογιστική Κόστους Ενότητα 10: Ασκήσεις Προτύπου Κόστους Αποκλίσεων.

Οργάνωση και Διοίκηση Πωλήσεων

Εισαγωγή στον δομημένο προγραμματισμό

Αντικειμενοστρεφής Προγραμματισμός Ενότητα 6: Φιλικές συναρτήσεις. Επικ. Καθηγητής Συνδουκάς Δημήτριος Τμήμα Διοίκησης Επιχειρήσεων (Γρεβενά)

Προγραμματισμός H/Y Ενότητα 7: Αρχεία. Επικ. Καθηγητής Συνδουκάς Δημήτριος Τμήμα Διοίκησης Επιχειρήσεων (Γρεβενά)

Αντικειμενοστραφής Προγραμματισμός

Εισαγωγή στους Αλγορίθμους Ενότητα 8η

Διδακτική Πληροφορικής

Συστήματα Αναμονής. Ενότητα 4: Αλυσίδες Markov. Αγγελική Σγώρα Τμήμα Μηχανικών Πληροφορικής ΤΕ

Προγραμματισμός H/Y Ενότητα 3: Πίνακες αριθμών και χαρακτήρων. Επικ. Καθηγητής Συνδουκάς Δημήτριος Τμήμα Διοίκησης Επιχειρήσεων (Γρεβενά)

Τίτλος Μαθήματος: Μαθηματική Ανάλυση Ενότητα Γ. Ολοκληρωτικός Λογισμός

Οργάνωση και Διοίκηση Πωλήσεων Ενότητα 1: Ο ΡΟΛΟΣ ΤΩΝ ΠΩΛΗΣΕΩΝ ΣΤΟ ΠΛΑΙΣΙΟ ΤΗΣ ΣΤΡΑΤΗΓΙΚΗΣ ΜΑΡΚΕΤΙΝΓΚ

Λογιστική Κόστους Ενότητα 11: Λογισμός Κόστους

Οντοκεντρικός Προγραμματισμός

Προγραμματισμός Ηλεκτρονικών Υπολογιστών 2 - Εργαστήριο

Προγραμματισμός Η/Υ. Συναρτήσεις & Υποπρογράμματα. ΤΕΙ Ιονίων Νήσων Τμήμα Τεχνολόγων Περιβάλλοντος Κατεύθυνση Τεχνολογιών Φυσικού Περιβάλλοντος

Συστήματα Αναμονής. Ενότητα 9: Ανέλιξη Γέννησης - Θανάτου. Αγγελική Σγώρα Τμήμα Μηχανικών Πληροφορικής ΤΕ

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ. Ενότητα: ΔΟΜΕΣ ΕΠΑΝΑΛΗΨΗΣ ΚΥΡΟΠΟΥΛΟΣ ΚΩΝΣΤΑΝΤΙΝΟΣ. Τμήμα Διοίκηση Επιχειρήσεων (Κοζάνη)

ΑΝΤΙΡΡΥΠΑΝΤΙΚΗ ΤΕΧΝΟΛΟΓΙΑ ΑΙΩΡΟΥΜΕΝΩΝ ΣΩΜΑΤΙΔΙΩΝ Ενότητα 2: Αιωρούμενα σωματίδια & Απόδοση συλλογής Αν. Καθ. Δρ Μαρία Α. Γούλα Τμήμα Μηχανικών

Σχεδίαση Δικτύων Υπολογιστών

Διοίκηση Εξωτερικής Εμπορικής Δραστηριότητας

Λογιστική Κόστους Ενότητα 11: Λογισμός Κόστους (1)

Τεχνολογία Πολυμέσων. Ενότητα 8: Pool Table. Νικολάου Σπύρος Τμήμα Μηχανικών Πληροφορικής ΤΕ

Εισαγωγή στους Αλγορίθμους Ενότητα 10η Άσκηση Αλγόριθμος Dijkstra

ΕΛΛΗΝΙΚΗ ΔΗΜΟΚΡΑΤΙΑ ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΡΗΤΗΣ

ΗΛΕΚΤΡΟΤΕΧΝΙΑ-ΗΛΕΚΤΡΟΝΙΚΗ ΕΡΓΑΣΤΗΡΙΟ

ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΗΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ

Διεθνείς Οικονομικές Σχέσεις και Ανάπτυξη

ΟΙΚΟΝΟΜΕΤΡΙΑ. Ενότητα 1: Εκτιμητές και Ιδιότητες. Αναπλ. Καθηγητής Νικόλαος Σαριαννίδης Τμήμα Διοίκησης Επιχειρήσεων (Γρεβενά)

Αλγόριθμοι και πολυπλοκότητα Συγχωνευτική Ταξινόμηση

Βάσεις Περιβαλλοντικών Δεδομένων

Εισαγωγή στους Αλγορίθμους Ενότητα 9η Άσκηση - Αλγόριθμος Kruskal

Εισαγωγή στους Αλγορίθμους Ενότητα 9η Άσκηση - Αλγόριθμος Prim

Οικονομετρία Ι. Ενότητα 3: Θεώρημα των Gauss Markov. Δρ. Χαϊδώ Δριτσάκη Τμήμα Λογιστικής & Χρηματοοικονομικής

Ανοικτά Ακαδημαϊκά Μαθήματα στο ΤΕΙ Αθήνας. Βιοστατιστική (Ε) Ενότητα 3: Έλεγχοι στατιστικών υποθέσεων

Ανοικτά Ακαδημαϊκά Μαθήματα στο ΤΕΙ Αθήνας. Βιοστατιστική (Ε) Ενότητα 1: Καταχώρηση δεδομένων

Μεθοδολογία Έρευνας Κοινωνικών Επιστημών

Τεχνολογία Πολυμέσων. Ενότητα 6: Keyframes και Transitions. Νικολάου Σπύρος Τμήμα Μηχανικών Πληροφορικής ΤΕ

Συστήματα Παράλληλης & Κατανεμημένης Επεξεργασίας

Εισαγωγικές έννοιες θεωρίας Συστημάτων Αυτομάτου Ελέγχου

ΟΙΚΟΝΟΜΕΤΡΙΑ. Ενότητα 3: Πολλαπλή Παλινδρόμηση. Αναπλ. Καθηγητής Νικόλαος Σαριαννίδης Τμήμα Διοίκησης Επιχειρήσεων (Γρεβενά)

Ενότητα. Εισαγωγή στις βάσεις δεδομένων

Ανοικτά Ακαδημαϊκά Μαθήματα στο ΤΕΙ Αθήνας. Βιοστατιστική (Ε) Ενότητα 2: Περιγραφική στατιστική

Συστήματα Αναμονής. Ενότητα 2: Τυχαίες Μεταβλητές. Αγγελική Σγώρα Τμήμα Μηχανικών Πληροφορικής ΤΕ

ΗΛΕΚΤΡΟΝΙΚΗ ΙIΙ Ενότητα 6

Εισαγωγή στους Υπολογιστές

Αντικειμενοστραφής Προγραμματισμός

Αντικειμενοστραφής Προγραμματισμός

Εκκλησιαστικό Δίκαιο. Ενότητα 10η: Ιερά Σύνοδος της Ιεραρχίας και Διαρκής Ιερά Σύνοδος Κυριάκος Κυριαζόπουλος Τμήμα Νομικής Α.Π.Θ.

Transcript:

Δομές Δεδομένων Ενότητα 9: Αναδρομικότητα Δρ. Γεώργιος Σίσιας Τμήμα Μηχανικών Πληροφορικής ΤΕ

Άδειες Χρήσης Το παρόν εκπαιδευτικό υλικό υπόκειται σε άδειες χρήσης Creative Commons. Για εκπαιδευτικό υλικό, όπως εικόνες, που υπόκειται σε άλλου τύπου άδειας χρήσης, η άδεια χρήσης αναφέρεται ρητώς. 2

Χρηματοδότηση Το παρόν εκπαιδευτικό υλικό έχει αναπτυχθεί στα πλαίσια του εκπαιδευτικού έργου του διδάσκοντα. Το έργο «Ανοικτά Ακαδημαϊκά Μαθήματα στο TEI Δυτικής Μακεδονίας και στην Ανώτατη Εκκλησιαστική Ακαδημία Θεσσαλονίκης» έχει χρηματοδοτήσει μόνο τη αναδιαμόρφωση του εκπαιδευτικού υλικού. Το έργο υλοποιείται στο πλαίσιο του Επιχειρησιακού Προγράμματος «Εκπαίδευση και Δια Βίου Μάθηση» και συγχρηματοδοτείται από την Ευρωπαϊκή Ένωση (Ευρωπαϊκό Κοινωνικό Ταμείο) και από εθνικούς πόρους. 3

Σκοποί ενότητας Η ενότητα αυτή πραγματεύεται το ζήτημα της αναδρομικότητας. 4

Περιεχόμενα ενότητας Αναδρομή. Παραγοντικό. Άθροισμα αριθμών. Πύργοι του Hanoi. Ασκήσεις. Βιβλιογραφία. 5

Αναδρομή (1/6) Η αναδρομη (recursion) είναι ένας κομψός μηχανισμός απλοποίησης πολύπλοκων υλοποιήσεων. Μια συνάρτηση λέγεται αναδρομική (recursive) όταν καλεί τον εαυτό της. Μια συνάρτηση μπορεί να καλεί τον εαυτό της όσες φορές χρειάζεται. 6

Αναδρομή (2/6) Το σύνηθες είναι μία ή δύο φορές, αλλά αυτό δεν αποκλείει τις περισσότερες. Στην περίπτωση της μίας αναδρομικής κλήσης, η αναδρομική συνάρτηση λέγεται tail recursive, και τις περισσότερες φορές μπορεί να υλοποιηθεί επαναληπτικά (το προτειμότερο). 7

Αναδρομή (3/6) Η αναδρομή βρίσκει εφαρμογή (στα πλαίσια του παρόντος μαθήματος) τόσο στους αλγόριθμους ταξινόμησης που βασίζονται στην προσέγγιση «διαίρει και βασίλευε» (divide and conquer), όσο και στις δενδροειδείς (δενδρικές) δομές (δυαδικά δέντρα, δέντρα AVL, κ.α.). 8

Αναδρομή (4/6) Όπως έχουμε ήδη περιγράψει σε προηγούμενη ενότητα, οι παράμετροι και οι τοπικές μεταβλητές μιας συνάρτησης αποθηκεύονται προσωρινά στη στατική μνήμη (στοίβα) ενός προγράμματος που βρίσκεται σε κατάσταση εκτέλεσης. Ο αποθηκευτικός αυτός χώρος (το έχουμε ήδη αναφέρει) είναι περιορισμένος (συνήθως 4-10 MB σήμερα), και, συνεπώς, είναι εύκολο να εξαντληθεί. 9

Αναδρομή (5/6) Μπορούμε να αντιληφθούμε ότι με την επαναλαμβανόμενη κλήση μιας συνάρτησης από την ίδια, αυτή η μνήμη εξαντλείται. Όταν συμβεί αυτό, το πρόγραμμα καταρρέει με μήνυμα «υπερχείλιση στοίβας» (stack overflow). Αυτό το πρόβλημα φαίνεται ξεκάθαρα σε ένα από τα παραδείγματα της παρούσας ενότητας. 10

Αναδρομή (6/6) Η αποφυγή του συγκεκριμένου προβλήματος γίνεται με τη συμπερίληψη στον κώδικα μιας αναδρομικής συνάρτησης μιας εκφυλισμένης ή ιδιάζουσας (degenerate) περίπτωσης, η οποία μέσα της (αυτό υποδηλώνει κάποια μορφή εντολής if) ΔΕΝ καλεί την υπό υλοποίησης συνάρτησης. Έτσι, κάποια στιγμή θα εκτελεστεί ο κώδικας που δεν καλεί ξανά την ίδια τη συνάρτηση, προκαλώντας με αυτόν τον τρόπο την αντίστροφη εκτέλεσή της μέχρι τον τερματισμό της και, ενδεχομένως, τον τελικό υπολογισμό του αποτελέσματος. 11

Παραγοντικό (1/8) Ας εξετάσουμε ένα παράδειγμα. Το πλέον δημοφιλές παράδειγμα αναδρομικής συνάρτησης είναι ο υπολογισμός του παραγοντικού. Το παραγοντικό μπορεί να υπολογιστεί τόσο με επαναληπτικό τρόπο, όσο και με αναδρομικό. Μόνο ως υποσημείωση αναφέρουμε ότι η πιο αποτελεσματική υλοποίηση του παραγοντικού είναι ο προϋπολογισμός του σε πίνακα αναζήτησης, το οποίο ανάγει τον υπολογισμό σε απλή αναζήτηση. 12

Παραγοντικό (2/8) Από μαθηματικής άποψης, το παραγοντικό ενός αριθμού Ν ορίζεται ως: Η παραπάνω συνάρτηση μπορεί να υλοποιηθεί επαναληπτικά με βρόχο for ή με αναδρομικό. Παρουσιάζουμε και τις δύο υλοποιήσεις. 13

Παραγοντικό (3/8) /* -------------------------------------------------------------------------- */ #include <stdio.h> #include <stdlib.h> /* -------------------------------------------------------------------------- */ // Iterative version of Factorial. Computes N! unsigned int FactorialItr(unsigned int N) { unsigned int Product = 1, i; for ( i = 1; i <= N; i++ ) Product *= i; return ( Product ); } // FactorialItr 14

Παραγοντικό (4/8) // Recursive version of Factorial. Computes N! unsigned int FactorialRec(unsigned int N) { if ( N == 0 ) return ( 1 ); else return ( N * FactorialRec(N - 1) ); } // FactorialRec /* -------------------------------------------------------------------------- */ 15

Παραγοντικό (5/8) void main() { unsigned int i; printf("iterative factorial\n"); printf("-------------------\n"); for ( i = 0; i <= 10; i++ ) printf("%2u! = %u\n", i, FactorialItr(i)); printf("\n\n"); printf("recursive factorial\n"); printf("-------------------\n"); for ( i = 0; i <= 10; i++ ) printf("%2u! = %u\n", i, FactorialRec(i)); } // main /* -------------------------------------------------------------------------- */ 16

Παραγοντικό (6/8) Η επαναληπτική υλοποίηση (unsigned int FactorialItr(unsigned int N)) χρησιμοποιεί μια προσωρινή μεταβλητή Product για να «μαζέψει» το γινόμενο που προκύπτει από το ουδέτερο στοιχείο του πολλαπλασιασμού (το 1) και το μετρητή του βρόχου (το i). Η αναδρομική υλοποίηση (unsigned int FactorialRec(unsigned int N)) ελέγχει αν η παράμετρος Ν είναι 0 ώστε να επιστρέψει 1, και αν δεν ισχύει αυτό, τότε πολλαπλασιάζει το Ν με το αποτέλεσμα της αναδρομικής κλήσης της ίδιας συνάρτησης με μια ελαττωμένη εκδοχή του προβλήματος (Ν-1). 17

Παραγοντικό (7/8) Αυτό θα επαναληφθεί ξανά, αλλά αυτή τη φορά θα πολλαπλασιαστεί το Ν-1 με το αποτέλεσμα της αναδρομικής κλήσης με παράμετρο το Ν-2. Αυτό θα συνεχίσει να συμβαίνει μέχρι να φτάσουμε στην εκφυλισμένη περίπτωση του 1. Τότε ξετυλίγονται οι αναδρομικές κλήσεις, μαζεύοντας σταδιακά το τελικό αποτέλεσμα. 18

Παραγοντικό (8/8) Στην περίπτωση αυτή των αναδρομικών κλήσεων «ελπίζουμε» να μη γίνουν τόσες πολλές κλήσεις ώστε να εξαντληθεί η στατική μνήμη. Το κυρίως πρόγραμμα υπολογίζει το παραγοντικό των αριθμών 0 ως και 10 και με τους δύο τρόπους. 19

Άθροισμα αριθμών (1/9) Παραθέτουμε ένα ακόμη παράδειγμα αναδρομικής συνάρτησης. Στο συγκεκριμένο παράδειγμα, όμως, έχουμε δύο υλοποιήσεις της ίδιας αναδρομικής συνάρτησης. Η πρώτη αναδρομική υλοποίηση είναι σωστή, ενώ η δεύτερη «ξεχνά» τεχνηέντως την εκφυλισμένη περίπτωση. 20

Άθροισμα αριθμών (2/9) Η εκφυλισμένη περίπτωση είναι προς το παρόν απενεργοποιημένη, ώστε να δοκιμαστεί από τον αναγνώστη. Ακολουθεί ο επαναληπτικός και ο αναδρομικός υπολογισμός του αθροίσματος αριθμών. 21

Άθροισμα αριθμών (3/9) /* -------------------------------------------------------------------------- */ #include <stdio.h> #include <stdlib.h> /* -------------------------------------------------------------------------- */ unsigned int SumItr(unsigned int N) { unsigned int i, Total = 0; for ( i = 1; i <= N; i++ ) Total += i; return ( Total ); } // SumItr 22

Άθροισμα αριθμών (4/9) unsigned int SumRec(unsigned int N) { if ( N == 0 ) return ( 0 ); else return ( N + SumRec(N - 1) ); } // SumRec 23

Άθροισμα αριθμών (5/9) unsigned int SumRecError(unsigned int N) { // if ( N == 0 ) // return ( 0 ); // else return ( N + SumRec(N - 1) ); } // SumRec /* -------------------------------------------------------------------------- */ 24

Άθροισμα αριθμών (6/9) void main() { unsigned int i; printf("iterative summation\n"); printf("-------------------\n"); for ( i = 0; i <= 10; i++ ) printf("sum(%2u) = %u\n", i, SumItr(i)); printf("\n\n"); printf("recursive summation\n"); printf("-------------------\n"); for ( i = 0; i <= 10; i++ ) printf("sum(%2u) = %u\n", i, SumRec(i)); printf("\n\n"); 25

Άθροισμα αριθμών (7/9) // The following code will crash the program due to a stack overflow. // The recursive function does not have a degenerate case that stops the // recursion, hence the stack overflow. /* printf("recursive summation (STACK OVERFLOW)\n"); printf("------------------------------------\n"); for ( i = 0; i <= 10; i++ ) printf("sum(%2u) = %u\n", i, SumRecError(i)); */ } // main /* -------------------------------------------------------------------------- */ 26

Άθροισμα αριθμών (8/9) Καλείστε να επαναφέρετε (αφαιρέσετε τα σχόλια) το τελευταίο απόσπασμα κώδικα του κυρίως προγράμματος. Τότε, αν τον εκτελέσετε, θα λάβετε το μήνυμα «Αυτό το πρόγραμμα σταμάτησε να λειτουργεί». Μια ενδελεχής εξέταση θα σας αποκαλύψει ότι έχει συμβεί υπερχείλιση στοίβας. 27

Άθροισμα αριθμών (9/9) Η κατάρρευση του προγράμματος θα συμβεί ακαριαία, αφού η αναδρομική κλήση της συνάρτησης 1 εκατομμύριο και πλέον φορές σήμερα είναι τάχιστη. Δοκιμάστε να εκτελέσετε το πρόγραμμα εκτός του περιβάλλοντος ανάπτυξης (π.χ. Visual Studio). 28

Πύργοι του Hanoi (1/29) Towers of Hanoi. Ακολουθεί ένα εκτενές παράδειγμα αναδρομικής επίλυσης του προβλήματος των πύργων του Hanoi. Στο συγκεκριμένο γρίφο (υπάρχουν διάφορες εικασίες ως προς την προέλευσή του) καλείστε να μεταφέρετε μια στοίβα δίσκων διαφορετικών διαμέτρων από ένα στύλο σε έναν άλλο, με τη βοήθεια ενός τρίτου. 29

Πύργοι του Hanoi (2/29) Η αρχική κατάσταση του γρίφου ορίζει ότι η αρχική στοίβα περιέχει Ν δίσκους, με τους δίσκους με τη μεγαλύτερη διάμετρο να βρίσκονται στη βάση της στοίβας και τη μικρότερη στην κορυφή της. Δεν υπάρχουν δύο δίσκοι με ίδια διάμετρο, ούτε μπορούμε να τοποθετήσουμε ένα δίσκο με μεγαλύτερη διάμετρο πάνω σε έναν άλλο. 30

Πύργοι του Hanoi (3/29) Το πλήθος των βημάτων (μετακίνηση ενός δίσκου από ένα στύλο σε έναν άλλο) για τη μετακίνηση των δίσκων είναι, όπου Ν το πλήθος των δίσκων. Στο παρακάτω παράδειγμα έχει τεθεί ως όριο οι 12 δίσκοι, ώστε το πλήθος των μετακινήσεων να μην υπερβεί το 4095. 31

Πύργοι του Hanoi (4/29) Η υλοποίηση του συγκεκριμένου προβλήματος προήρθε από το αντίστοιχο μάθημα μεταπτυχιακού επιπέδου ενός ανοιχτού πανεπιστημίου. Η λύση που παρουσιάζεται αποτελεί το 1/4 της καθιερωμένης εβδομαδιαίας εργασίας στη διάρκεια του ακαδημαϊκού εξαμήνου. Τα άλλα 3/4 του προβλήματος (που δεν παρουσιάζουμε) αφορούν τη χρήση διαφορετικής υλοποίησης της κύριας δομής περιγραφής της έννοιας των στύλων. 32

Πύργοι του Hanoi (5/29) Οι στύλοι υλοποιούνται με τη βοήθεια στατικής στοίβας. Ο κώδικας είναι δοκιμασμένος στο CodeGear RAD Studio 2007. Η μεταφορά του στο Visual Studio απαιτεί την αντικατάσταση της clrscr() της συνάρτησης void PrintRods(STACK rod[3], int N) με system("cls");. 33

Πύργοι του Hanoi (6/29) /* -------------------------------------------------------------------------- */ #include <stdio.h> #include <conio.h> #include <stdlib.h> /* -------------------------------------------------------------------------- */ /* Minimum and maximum number of discs on a stack. */ #define MIN_STACK_ELEMENTS 1 #define MAX_STACK_ELEMENTS 12 34

Πύργοι του Hanoi (7/29) /* Type definition of STACK. */ typedef struct { int Discs[MAX_STACK_ELEMENTS]; int NumDiscs; int MaxDiscs; } STACK; 35

Πύργοι του Hanoi (8/29) /* -------------------------------------------------------------------------- */ /* ** Waits for a key press. */ void PressAnyKeyToContinue() { printf("press any key to continue..."); if ( getch() == 0) getch(); } /* PressAnyKeyToContinue */ 36

Πύργοι του Hanoi (9/29) // Prints the contents of a stack. void PrintStack(STACK *s, char *msg) { printf(" Stack : %s\n", msg); printf("numdiscs : %d\n", s->numdiscs); printf("maxdiscs : %d\n", s->maxdiscs); printf("contents : "); for ( int i = 0; i < MAX_STACK_ELEMENTS; i++ ) printf("%2d ", s->discs[i]); printf("\n\n"); } /* PrintStack */ 37

Πύργοι του Hanoi (10/29) // Initialise a stack to hold MaxElements. void InitStack(STACK *s, int MaxElements) { int i, j; for ( i = 0; i < MaxElements; i++ ) s->discs[i] = ( MaxElements - i ); for ( j = i; j < MAX_STACK_ELEMENTS; j++ ) s->discs[j] = 0; s->numdiscs = MaxElements; s->maxdiscs = MAX_STACK_ELEMENTS; } /* InitStack */ 38

Πύργοι του Hanoi (11/29) / / Insert x at the top of the stack. void Push(int x, STACK *s) { if ( s->numdiscs < ( s->maxdiscs - 1 ) ) { s->discs[s->numdiscs] = x; s->numdiscs++; } else { printf("error in Push\n"); PressAnyKeyToContinue(); } /* if */ } /* Push */ 39

Πύργοι του Hanoi (12/29) // Return the element at the top of the stack. int Top(STACK *s) { if ( s->numdiscs > 0 ) return ( s->discs[s->numdiscs - 1] ); else { printf("error in Top\n"); PressAnyKeyToContinue(); return ( 0 ); } } /* Top */ 40

Πύργοι του Hanoi (13/29) // Remove the element at the top of the stack. void Pop(STACK *s) { if ( s->numdiscs > 0 ) { s->discs[s->numdiscs - 1] = 0; s->numdiscs--; } else { printf("error in Pop\n"); PressAnyKeyToContinue(); } /* if */ } /* Pop */ 41

Πύργοι του Hanoi (14/29) // Initialise scanning stack from (highest possible) top to bottom. void InitScan(STACK *s) { for ( int i = 0; i < MAX_STACK_ELEMENTS; i++ ) s->discs[i] = ( MAX_STACK_ELEMENTS - i ); } /* InitScan */ 42

Πύργοι του Hanoi (15/29) // Return the next element in top-to-bottom order. int ScanNext(STACK *s) { if ( s->numdiscs > 1 ) return ( s->discs[s->numdiscs - 2] ); else return ( 0 ); } /* ScanNext */ 43

Πύργοι του Hanoi (16/29) //Returns the maximum of 2 integers. int MaxInt(int x, int y) { if ( x < y ) return ( y ); else return ( x ); } /* MaxInt */ 44

Πύργοι του Hanoi (17/29) // Returns the maximum of 3 integers. int MaxInt3(int x, int y, int z) { return ( MaxInt(MaxInt(x, y), z) ); } /* MaxInt3 */ 45

Πύργοι του Hanoi (18/29) /* ** Print the contents of the 3 rods side-to-side horizontally. ** N is the size of the largest disc, or total number of discs. */ { void PrintRods(STACK rod[3], int N) int Row, Col, Blanks; clrscr(); /* Clear the screen. */ printf("\n"); /* Leave a blank line. */ /* We need slightly taller rods. */ printf(" \n"); 46

Πύργοι του Hanoi (19/29) /* Print rows successively from top to bottom. */ for ( Row = ( N - 1 ); Row >= 0; Row-- ) { /* First rod. */ printf(" "); /* Left margin. */ Blanks = MAX_STACK_ELEMENTS - rod[0].discs[row]; for ( Col = 0; Col < Blanks; Col++ ) printf(" "); for ( Col = 0; Col < rod[0].discs[row]; Col++ ) printf("-"); printf(" "); for ( Col = 0; Col < rod[0].discs[row]; Col++ ) printf("-"); for ( Col = 0; Col < Blanks; Col++ ) printf(" "); 47

Πύργοι του Hanoi (20/29) /* Second rod. */ printf(" "); Blanks = MAX_STACK_ELEMENTS - rod[1].discs[row]; for ( Col = 0; Col < Blanks; Col++ ) printf(" "); for ( Col = 0; Col < rod[1].discs[row]; Col++ ) printf("-"); printf(" "); for ( Col = 0; Col < rod[1].discs[row]; Col++ ) printf("-"); for ( Col = 0; Col < Blanks; Col++ ) printf(" "); 48

Πύργοι του Hanoi (21/29) /* Third rod. */ printf(" "); Blanks = MAX_STACK_ELEMENTS - rod[2].discs[row]; for ( Col = 0; Col < Blanks; Col++ ) printf(" "); for ( Col = 0; Col < rod[2].discs[row]; Col++ ) printf("-"); printf(" "); for ( Col = 0; Col < rod[2].discs[row]; Col++ ) printf("-"); for ( Col = 0; Col < Blanks; Col++ ) printf(" "); } /* for */ /* This is the base where the rods are stuck into. */ printf(" \n"); } /* PrintRods */ 49

Πύργοι του Hanoi (22/29) /* -------------------------------------------------------------------------- */ /* ** Solves the Towers-of-Hanoi problem recursively. ** Bibliographical reference for solution algorithm: ** Helman, Paul and Robert Veroff. 1988. Walls and Mirrors: Intermediate ** Problem Solving and Data Structures. The Benjamin/Cummings Publishing ** Company Inc., USA. pp. 195-202. */ void dohanoi(int total, int N, STACK rod[3], int from, int to, int aux) { int disk; 50

Πύργοι του Hanoi (23/29) if ( N == 1 ) { } /* Move the disk directly. */ disk = Top(&(rod[from])); Pop(&(rod[from])); Push(disk, &(rod[to])); PrintRods(rod, MaxInt3(rod[0].MaxDiscs, rod[1].maxdiscs, rod[2].maxdiscs)); PressAnyKeyToContinue(); /* Don't display things too fast. */ 51

Πύργοι του Hanoi (24/29) else if ( N > 1 ) { dohanoi(total, N - 1, rod, from, aux, to); dohanoi(total, 1, rod, from, to, aux); dohanoi(total, N - 1, rod, aux, to, from); } /* if */ } /* dohanoi */ /* -------------------------------------------------------------------------- */ 52

Πύργοι του Hanoi (25/29) int main(int argc, char* argv[]) { STACK MyStacks[3]; int StackHeight; /* Check the number of program arguments. */ if ( argc!= 2 ) { printf("please use the correct syntax: %s N\n", argv[0]); printf("where N is a number between %d and %d\n\n", MIN_STACK_ELEMENTS, MAX_STACK_ELEMENTS); exit(1); } /* if */ 53

Πύργοι του Hanoi (26/29) /* Make sure N belongs in [1, 12]. */ StackHeight = atoi(argv[1]); if ( StackHeight < MIN_STACK_ELEMENTS ) StackHeight = MIN_STACK_ELEMENTS; if ( StackHeight > MAX_STACK_ELEMENTS ) StackHeight = MAX_STACK_ELEMENTS; /* Print the stacks to check their contents. */ InitStack(&(MyStacks[0]), StackHeight); PrintStack(&(MyStacks[0]), "Stack 0"); InitStack(&(MyStacks[1]), 0); PrintStack(&(MyStacks[1]), "Stack 1"); InitStack(&(MyStacks[2]), 0); PrintStack(&(MyStacks[2]), "Stack 2"); PressAnyKeyToContinue(); 54

Πύργοι του Hanoi (27/29) /* Print the initial state of stacks for the user to observe. */ PrintRods(MyStacks, MAX_STACK_ELEMENTS); PressAnyKeyToContinue(); /* Solve the problem. */ dohanoi(max_stack_elements, StackHeight, MyStacks, 0, 1, 2); return ( 0 ); } /* main */ /* -------------------------------------------------------------------------- */ 55

Πύργοι του Hanoi (28/29) Καλέστε το παραπάνω πρόγραμμα από τη γραμμή εντολών με παράμετρο το πλήθος των δίσκων. Ο αριθμός αυτός περιορίζεται στο διάστημα 1 ως 12. Πρέπει να πατήστε κάποιο πλήκτρο για να προχωρίσετε στην επόμενη κίνηση. Η επιλογή 12 δίσκων απαιτεί 4095 κινήσεις. 56

Πύργοι του Hanoi (29/29) Αν κρατήσετε διαρκώς πατημένο κάποιο πλήκτρο (ρυθμός 30-32 διακοπές/δευτερόλεπτο), τότε η μετακίνηση των 12 δίσκων θα χρειαστεί πάνω από 2 λεπτά. Σε κάθε περίπτωση μπορείτε να διακόψετε την εκτέλεση του προγράμματος με CTRL+C. 57

Ασκήσεις (1/4) Άσκηση 1. Να δηλώσετε και να υλοποιήσετε με αναδρομικό τρόπο την ακολουθία Fibonacci: 58

Ασκήσεις (2/4) Άσκηση 2. Να δηλώσετε και να υλοποιήσετε τη συνάρτηση του Ackermann (δοκιμάστε μόνο μικρά m και n): 59

Ασκήσεις (3/4) Άσκηση 3. Υλοποιήστε μια 2η εκδοχή της συνάρτησης Fibonacci που να μετράει το πλήθος των αναδρομικών κλήσεών της. Άσκηση 4. Υλοποιήστε μια 2η εκδοχή της συνάρτησης του Ackermann που να μετράει το πλήθος των αναδρομικών κλήσεών της. Άσκηση 5. Δηλώστε και υλοποιήστε κατάλληλα μια αναδρομική συνάρτηση που τυπώνει ανάποδα μια συμβολοσειρά. 60

Ασκήσεις (4/4) Άσκηση 6. Η ενδεικτική λύση των πύργων του Hanoi είναι αυτόνομη, δηλαδή δε χρειάζεται άλλη βιβλιοθήκη πέραν των βιβλιοθηκών του συστήματος. Προσπαθήστε να χρησιμοποιήσετε τον ήδη υπάρχοντα κώδικα της στατικής στοίβας με κατάλληλες τροποποιήσεις, αφού τον μετατρέψετε σε δική σας βιβλιοθήκη. 61

Βιβλιογραφία (1/8) Aho AV, Hopcroft JE, and Ullman JD. (1974) The design and analysis of computer algorithms. USA, Addison-Wesley Publishing Company. 470 pp. ISBN 0-201-00029-6. ( 38.33, 46.76). Aho AV, Hopcroft JE, and Ullman JD. (1983) Data structures and algorithms. USA, Addison-Wesley Publishing Company. 427 pp. ISBN 0-201-00023-7. ( 43.65, 53.25). Bik AJC. (2004) The software vectorization handbook: applying multimedia extensions for maximum performance. USA, Intel Press. 236 pp. ISBN 0-9743649-2-4. ( 32.31, 46.63). 62

Βιβλιογραφία (2/8) Carrano FM and Henry T. (2013) Data abstraction and problem solving with C++: walls and mirrors. 6th ed. UK, Pearson Education Limited. 833 pp. ISBN10 0-273-76841-7, ISBN13 978-0-76841-8. Cormen TH, Leiserson CE, Rivest RL, and Stein C. (2012) Εισαγωγή στους αλγορίθμους. USA/Ελλάδα, MIT Press/Ίδρυμα Τεχνολογίας & Έρευνας - Πανεπιστημιακές Εκδόσεις Κρήτης. 1260 pp. ISBN 978-960-524-224-4. Dasgupta S, Papadimitriou C and Vazirani U. (2009) Αλγόριθμοι. Ελλάδα, Εκδόσεις Κλειδάριθμος. 416 σελ. ISBN13 978-960-461-211-6. 63

Βιβλιογραφία (3/8) Gerber R, Bik AJC, Smith KB and Tian X. (2006) The software optimization cookbook: high-performance recipes for IA-32 platforms. 2nd ed. USA, Intel Press. 404 pp. ISBN 0-9764832-1-1. ( 35.07, 50.61). Helman P and Veroff R. (1988) Walls and mirrors: intermediate problem solving and data structures. Modula 2 ed. USA, The Benjamin/Cummings Publishing Company, Inc. 625 pp. ( 23.95). Kleinberg J and Tardos W. (2008) Σχεδιασμός αλγορίθμων. Ελλάδα, Εκδόσεις Κλειδάριθμος. 944 σελ. ISBN13 978-960- 461-207-9. 64

Βιβλιογραφία (4/8) Knuth DE. (2009) Η τέχνη του προγραμματισμού: θεμελιώδεις αλγόριθμοι, Τόμος Α. 3η Έκδοση. Ελλάδα, Εκδόσεις Τζιόλα. 759 σελ. ISBN13 978-960-418-185-8. Knuth DE. (2010) Η τέχνη του προγραμματισμού: ημιαριθμητικοί αλγόριθμοι, Τόμος Β. 3η Έκδοση. Ελλάδα, Εκδόσεις Τζιόλα. 912 σελ. ISBN13 978-960-418-224-4. Knuth DE. (2010) Η τέχνη του προγραμματισμού: ταξινόμηση και αναζήτηση, Τόμος Γ. 2η Έκδοση. Ελλάδα, Εκδόσεις Τζιόλα. 926 σελ. ISBN13 978-960-418-245-9. 65

Βιβλιογραφία (5/8) Kruse RL and Ryba AJ. (1999) Data structures and program design in C++. USA, Prentice Hall. 717 pp. ISBN 0-13- 082640-5. ( 40.74). Lafore R. (2005) Δομές δεδομένων και αλγόριθμοι στη Java. Ελλάδα, Εκδόσεις Μ. Γκιούρδα. 798 σελ. ISBN10 960-512- 452-1. Levitin A. (2008) Εισαγωγή στην ανάλυση και σχεδίαση αλγορίθμων. 2η Έκδοση. Ελλάδα, Εκδόσεις Τζιόλα. 700 σελ. ISBN13 978-960-418-143-8. 66

Βιβλιογραφία (6/8) McConnell S. (1993) Code complete: a practical handbook of software construction. USA, Microsoft Press. 857 pp. ( 25.99). Mehlhorn K and Sanders P. (2008) Algorithms and data structures: the basic toolbox. Germany, Springer-Verlag Berlin Heidelberg. 300 pp. ISBN13 978-3-540-77977-3. ( 28.11, 34.29). Prichard JJ and Carrano FM. (2011) Data abstraction and problem solving with Java: walls and mirrors. 3rd ed. UK, Pearson Education Limited. 959 pp. ISBN10 0-273-75120-4. ISBN13 978-0-273-75120-5. 67

Βιβλιογραφία (7/8) Sahni S. (2004) Δομές Δεδομένων, Αλγόριθμοι, και Εφαρμογές στη C++. Ελλάδα/ΗΠΑ, Εκδόσεις Τζιόλα/McGraw-Hill. 830 σελ. ISBN10 960-418-030-4. Sedgewick R and Flajolet P. (2013) An introduction to the analysis of algorithms. 2nd ed. USA, Pearson Education, Inc. 572 pp. ISBN13 978-0-321-90575-8. Sedgewick R and Wayne K. (2011) Algorithms. 4th ed. USA, Pearson Education, Inc. 952 pp. ISBN13 978-0-321-57351-3. Κοίλιας Χ. (2004) Δομές δεδομένων & οργανώσεις αρχείων. Ελλάδα, Εκδόσεις Νέων Τεχνολογιών. 447 σελ. ISBN10 960-8105-64-1. 68

Βιβλιογραφία (8/8) Μποζάνης ΠΔ. (2006) Δομές Δεδομένων. Ελλάδα, Εκδόσεις Τζιόλα. 552 σελ. ISBN10 960-418-084-3. Μποζάνης ΠΔ. (2009) Προβλήματα & ασκήσεις στους αλγορίθμους. Ελλάδα, Εκδόσεις Τζιόλα. 492 σελ. ISBN13 978-960-418-186-5. Μποζάνης ΠΔ. (2013) Αλγόριθμοι. Ελλάδα, Εκδόσεις Τζιόλα. 549 σελ. ISBN13 978-960-418-070-1. Μυσιρλής Ν. (2002) Δομές δεδομένων με C. Ελλάδα, αυτοέκδοση. 347 σελ. ISBN10 960-92031-1-6. Παπαρίζος Κ. (2010) Ανάλυση και σχεδίαση αλγορίθμων. Ελλάδα, Εκδόσεις Τζιόλα. 606 σελ. ISBN13 978-960-418-222-0. 69

Τέλος Ενότητας

Σημείωμα Αναφοράς Copyright ΤΕΙ Δυτικής Μακεδονίας, Δρ. Γεώργιος Σίσιας. «Δομές Δεδομένων». Έκδοση: 1.0. Κοζάνη 2015. Διαθέσιμο από τη δικτυακή διεύθυνση: URL. 71

Σημείωμα Αδειοδότησης Το παρόν υλικό διατίθεται με τους όρους της άδειας χρήσης Creative Commons Αναφορά, Μη Εμπορική Χρήση Παρόμοια Διανομή 4.0 [1] ή μεταγενέστερη, Διεθνής Έκδοση. Εξαιρούνται τα αυτοτελή έργα τρίτων π.χ. φωτογραφίες, διαγράμματα κ.λ.π., τα οποία εμπεριέχονται σε αυτό και τα οποία αναφέρονται μαζί με τους όρους χρήσης τους στο «Σημείωμα Χρήσης Έργων Τρίτων». [1] http://creativecommons.org/licenses/by-nc-sa/4.0/ Ως Μη Εμπορική ορίζεται η χρήση: που δεν περιλαμβάνει άμεσο ή έμμεσο οικονομικό όφελος από την χρήση του έργου, για το διανομέα του έργου και αδειοδόχο. που δεν περιλαμβάνει οικονομική συναλλαγή ως προϋπόθεση για τη χρήση ή πρόσβαση στο έργο. που δεν προσπορίζει στο διανομέα του έργου και αδειοδόχο έμμεσο οικονομικό όφελος (π.χ. διαφημίσεις) από την προβολή του έργου σε διαδικτυακό τόπο. Ο δικαιούχος μπορεί να παρέχει στον αδειοδόχο ξεχωριστή άδεια να χρησιμοποιεί το έργο για εμπορική χρήση, εφόσον αυτό του ζητηθεί. 72

Διατήρηση Σημειωμάτων Οποιαδήποτε αναπαραγωγή ή διασκευή του υλικού θα πρέπει να συμπεριλαμβάνει: το Σημείωμα Αναφοράς. το Σημείωμα Αδειοδότησης. τη δήλωση Διατήρησης Σημειωμάτων. το Σημείωμα Χρήσης Έργων Τρίτων (εφόσον υπάρχει). μαζί με τους συνοδευόμενους υπερσυνδέσμους. 73