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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Ηλεκτρονικοί Υπολογιστές

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

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

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

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

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

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

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

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

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

Πληροφορική ΙΙ Θεματική Ενότητα 5

Ειδικά Θέματα Δικτύων Ι

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

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

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

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

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

Τεχνολογία Πολιτισμικού Λογισμικού

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

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

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

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

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

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

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

Βάσεις Δεδομένων. Ενότητα 5: ΚΑΝΟΝΙΚΟΠΟΙΗΣΗ ΒΑΣΗΣ ΔΕΔΟΜΕΝΩΝ. Πασχαλίδης Δημοσθένης Τμήμα Ιερατικών σπουδών

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

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

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

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

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

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

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

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

Δομημένος Προγραμματισμός

Προγραμματισμός ΙΙ Ενότητα 5:

Προγραμματισμός Υπολογιστών & Υπολογιστική Φυσική

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

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

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

Δομημένος Προγραμματισμός

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

Transcript:

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

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

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

Σκοποί ενότητας Σε αυτή την ενότητα παρουσιάζονται οι ουρές. 4

Περιεχόμενα ενότητας (1/2) Εισαγωγή. Στατικές ουρές. Ενδεικτική υλοποίηση στατικής ουράς. Δηλώσεις και υλοποιήσεις πέντε βασικών λειτουργιών για τη στατική ουρά. Ασκήσεις στις στατικές ουρές. Δυναμικές ουρές. 5

Περιεχόμενα ενότητας (2/2) Ενδεικτική υλοποίηση δυναμικής ουράς. Ασκήσεις στις δυναμικέςουρές. Ερωτήσεις. Βιβλιογραφία. 6

Εισαγωγή Οι ουρές είναι μια δομή όπου η εισαγωγή στοιχείων γίνεται στο τέλος της και η εξαγωγή στην αρχή της. Συνήθως απεικονίζονται στη στατική μορφή τους είτε ως γραμμικός μονοδιάστατος πίνακας είτε με τη χρήση κυκλικής διάταξης. Η δυναμική τους μορφή απεικονίζεται ως συνδεδεμένη λίστα κόμβων. 7

Στατικές ουρές (1/12) Στο παρακάτω σχήμα απεικονίζεται μια στατική ουρά που είναι υλοποιημένη με τη βοήθεια ενός πίνακα 10 θέσεων. Στο ίδιο σχήμα φαίνονται και οι δύο δείκτες που χρειάζονται για την εισαγωγή και εξαγωγή στοιχείων. Ο δείκτης Front δείχνει στην αρχή της ουράς από την οποία θα αφαιρέσουμε το πρώτο στοιχείο, ενώ ο δείκτης Back δείχνει στην επόμενη διαθέσιμη κενή θέση στο τέλος της ουράς. 8

Στατικές ουρές (2/12) Εικόνα 1. Στατική ουρά. Πηγή: Διδάσκων (2015). 9

Στατικές ουρές (3/12) Από το σχήμα καθίσταται προφανές ότι με την εισαγωγή και διαγραφή στοιχείων κάποια στιγμή ο δείκτης Back θα φτάσει στο τέλος του πίνακα. Είναι αντιπαραγωγικό να μετακινούμε τα στοιχεία του πίνακα κατά μία θέση κάθε φορά που αφαιρούμε ένα στοιχείο από την αρχή της ουράς. Έτσι, είναι σκόπιμο να «ανακυκλώνουμε» τις διαθέσιμες θέσεις του πίνακα. 10

Στατικές ουρές (4/12) Είναι απολύτως λογικό κάποια στιγμή ο δείκτης Front να έπεται του Back. Για δική μας διευκόλυνση μπορούμε να φανταστούμε μια στατική ουρά ως κυκλική, όπου οι δύο δείκτες «περιστρέφονται» γύρω της κατά την εισαγωγή και διαγραφή στοιχείων. Σε κάθε περίπτωση, δεν μπορούμε να προσθέσουμε στοιχεία όταν η ουρά έχει γεμίσει, αλλά ούτε και να αφαιρέσουμε όταν αυτή έχει αδειάσει τελείως. 11

Στατικές ουρές (5/12) Η αρχική συνθήκη κατά την αρχικοποίηση μιας ουράς ορίζει τους δύο δείκτες να έχουν την ίδια τιμή (0) δηλαδή η ουρά είναι κενή, αφού οι δύο δείκτες έχουν «συναντηθεί». Όταν η ουρά έχει γεμίσει, τότε πάλι οι δύο δείκτες έχουν «συναντηθεί». Αυτό, όμως, προκαλεί ένα πρόβλημα. Αν πέρα από την ουρά η δομή μας έχει μόνο τους δύο δείκτες, τότε δεν μπορούμε να γνωρίζουμε πότε η ουρά είναι γεμάτη και πότε άδεια, αφού και στις δύο περιπτώσεις οι δύο δείκτες έχουν την ίδια τιμή. 12

Στατικές ουρές (6/12) Αυτό το πρόβλημα λύνεται με διάφορους τρόπους, δύο από τους οποίους είναι οι εξής: 1. Φροντίζουμε να μη «συναντηθούν» οι δύο δείκτες όταν προσθέτουμε στοιχεία, αφήνοντας πάντα μία θέση κενή. Δηλαδή, σύμφωνα με το παραπάνω σχήμα, προσέχουμε να έχουμε το πολύ στοιχεία (στο παράδειγμά μας 9). Έτσι οι δύο δείκτες θα έχουν την ίδια τιμή μόνο όταν η ουρά είναι κενή. 13

Στατικές ουρές (7/12) 2. Διατηρούμε ένα μετρητή των στοιχείων που υπάρχουν στην ουρά. Έτσι οι δύο δείκτες έχουν μόνο ένα ρόλο, αυτό των δεικτών, και όχι διπλό (δείκτες και μετρητής ταυτόχρονα). Συνεπώς μπορούν να πάρουν κάποια στιγμή την ίδια τιμή, χωρίς αυτό να προκαλεί πρόβλημα. 14

Στατικές ουρές (8/12) Η πρώτη προσέγγιση αποφεύγει την αποθήκευση και διατήρηση μετρητή με κόστος ένα λιγότερο στοιχείο στην ουρά, ενώ η δεύτερη χρησιμοποιεί ολόκληρο τον πίνακα, με κόστος την αποθήκευση και διατήρηση ενός μετρητή. Στην ενδεικτική υλοποίηση που παραθέτουμε σε λίγο χρησιμοποιούμε την προσέγγιση της διατήρησης μετρητή. 15

Στατικές ουρές (9/12) Οι βασικές λειτουργίες μιας ουράς (είτε στατικής είτε δυναμικής) είναι οι ακόλουθες: 1. Αρχικοποίηση (δηλωμένης) ουράς. 2. Έλεγχος για κενή ουρά (ή ενδεχομένως και γεμάτη). 3. Εισαγωγή στοιχείου σε μια ουρά που δεν έχει γεμίσει. 4. Ανάγνωση με αφαίρεση/εξαγωγή του στοιχείου στην αρχή μιας ουράς που έχει τουλάχιστον 1 στοιχείο. 5. Ανάγνωση χωρίς αφαίρεση/εξαγωγή του στοιχείου στην αρχή μιας ουράς που έχει τουλάχιστον 1 στοιχείο. 6. Αποδέσμευση μιας δυναμικής ουράς. 16

Στατικές ουρές (10/12) Όπως και στην περίπτωση των στοιβών, μπορούμε να έχουμε και πρόσθετες λειτουργίες (π.χ. την αντιστροφή μιας ουράς). Ας αρχίσουμε με τη δήλωση των τύπων. typedef int TItem; typedef struct { TItem size_t size_t size_t } TStaticQueue; Array[MAX_QUEUE_SIZE]; Front; Back; TotalItems; 17

Στατικές ουρές (11/12) Η πρώτη δήλωση αφορά το γενικό τύπο των στοιχείων που θα αποθηκεύουμε σε κάθε μία θέση της ουράς, που στην περίπτωσή μας θα είναι ένας ακέραιος. Η δήλωση αυτού του ενδιάμεσου τύπου μάς βοηθάει στην ελάττωση των αλλαγών στον κώδικα, όποτε αυτό καταστεί αναγκαίο. Η δεύτερη δήλωση είναι αυτή της ουράς. 18

Στατικές ουρές (12/12) Ο τύπος της στατικής ουράς (TStaticQueue) αποτελείται από τα εξής τέσσερα κατά σειρά πεδία: 1. Τον πίνακα των στοιχείων που θα αποθηκεύσουμε στην ουρά. 2. Το δείκτη Front που θα δείχνει στο πρώτο διαθέσιμο προς εξαγωγή στοιχείο. 3. Το δείκτη Back που θα δείχνει στην αμέσως επόμενη διαθέσιμη θέση για την εισαγωγή στοιχείου. 4. Το μετρητή TotalItems που θα αυξάνουμε όταν προσθέτουμε στοιχεία και θα μειώνουμε όταν αφαιρούμε στοιχεία από την ουρά. Ο μετρητής αυτός μας βοηθάει στον έλεγχο κενής ή γεμάτης ουράς, όταν πρόκειται να αφαιρέσουμε ή να προσθέσουμε στοιχεία, αντίστοιχα. 19

Ενδεικτική υλοποίηση στατικής ουράς (1/11) /* -------------------------------------------------------------------------- */ #include <stdio.h> #include <stdlib.h> /* -------------------------------------------------------------------------- */ #define MAX_QUEUE_SIZE 10 /* -------------------------------------------------------------------------- */ typedef int TItem; 20

Ενδεικτική υλοποίηση στατικής ουράς (2/11) typedef struct { TItem Array[MAX_QUEUE_SIZE]; size_t Front; size_t Back; size_t TotalItems; } TStaticQueue; 21

Ενδεικτική υλοποίηση στατικής ουράς (3/11) void StaticQueue_Init(TStaticQueue *q) { for ( size_t i = 0; i < MAX_QUEUE_SIZE; i++ ) q->array[i] = 0; q->front = 0; q->back = 0; q->totalitems = 0; } // StaticQueue_Init bool StaticQueue_IsEmpty(TStaticQueue q) { return ( q.totalitems == 0 ); } // StaticQueue_IsEmpty 22

Ενδεικτική υλοποίηση στατικής ουράς (4/11) bool StaticQueue_Add(TStaticQueue *q, TItem Item) { if ( q->totalitems < MAX_QUEUE_SIZE ) { q->array[q->back] = Item; // q->back++; // if ( q->back >= MAX_QUEUE_SIZE ) q->back = 0; q->back = ( ( q->back + 1 ) % MAX_QUEUE_SIZE ); q->totalitems++; return ( true ); } else return ( false ); } // StaticQueue_Add 23

Ενδεικτική υλοποίηση στατικής ουράς (5/11) bool StaticQueue_Remove(TStaticQueue *q, TItem *Item) { if ( q->totalitems > 0 ) { *Item = q->array[q->front]; // q->front++; // if ( q->front >= MAX_QUEUE_SIZE ) q->front = 0; q->front = ( ( q->front + 1 ) % MAX_QUEUE_SIZE ); q->totalitems--; return ( true ); } else return ( false ); } // StaticQueue_Remove 24

Ενδεικτική υλοποίηση στατικής ουράς (6/11) bool StaticQueue_Front(TStaticQueue q, TItem *Item) { if ( q.totalitems > 0 ) { *Item = q.array[q.front]; return ( true ); } else return ( false ); } // StaticQueue_Front 25

Ενδεικτική υλοποίηση στατικής ουράς (7/11) void StaticQueue_Write(TStaticQueue q) { size_t i, Count = 0; printf("\nstaticqueue_write\n"); printf("-----------------\n"); printf("front Index = %3u\n", q.front); printf(" Back Index = %3u\n", q.back); printf("total Items = %3u\n", q.totalitems); // Print entire array. printf("array Items = "); for ( i = 0; i < MAX_QUEUE_SIZE; i++ ) printf("%3d ", q.array[i]); 26

Ενδεικτική υλοποίηση στατικής printf("\n"); printf("queue Items = "); ουράς (8/11) if ( q.totalitems > 0 ) { // Print only the items on the queue. i = q.front; while ( Count < q.totalitems ) { printf("%3d ", q.array[i]); i++; if ( i >= MAX_QUEUE_SIZE ) i = 0; Count++; } // while } // if printf("\n"); } // StaticQueue_Write 27

Ενδεικτική υλοποίηση στατικής ουράς (9/11) void main() { TStaticQueue queue; Titem item; StaticQueue_Init(&queue); StaticQueue_Write(queue); StaticQueue_Add(&queue, rand()); StaticQueue_Add(&queue, rand()); StaticQueue_Write(queue); 28

Ενδεικτική υλοποίηση στατικής ουράς (10/11) StaticQueue_Remove(&queue, &item); StaticQueue_Remove(&queue, &item); StaticQueue_Write(queue); while ( StaticQueue_Add(&queue, rand()) ); StaticQueue_Write(queue); if ( StaticQueue_Add(&queue, rand()) ) printf("\n\nadded item\n\n\n"); else printf("\n\nqueue is full, cannot add more items\n\n\n"); 29

Ενδεικτική υλοποίηση στατικής ουράς (11/11) if ( StaticQueue_Front(queue, &item) ) printf("\n\nqueue Front = %3d\n\n\n", item); else printf("\n\nqueue is empty, cannot extract item\n\n\n"); while ( StaticQueue_Remove(&queue, &item) ); StaticQueue_Write(queue); if ( StaticQueue_Front(queue, &item) ) printf("\n\nqueue Front = %3d\n\n\n", item); else printf("\n\nqueue is empty, cannot extract item\n\n\n"); } // main 30

Δηλώσεις και υλοποιήσεις 5 βασικών λειτουργιών για τη στατική ουρά (1/9) 1. Η συνάρτηση void StaticQueue_Init(TStaticQueue *q) δέχεται μία παράμετρο τύπου δείκτη προς στατική ουρά, την οποία αρχικοποιεί ως εξής: Θέτει την τιμή 0 στα στοιχεία του πίνακα, στους δείκτες Front και Back, και στο μετρητή TotalItems. Αυτή η συνάρτηση μεταβάλλει την ουρά. 31

Δηλώσεις και υλοποιήσεις 5 βασικών λειτουργιών για τη στατική ουρά (2/9) 2. Η συνάρτηση bool StaticQueue_IsEmpty(TStaticQueue q) δέχεται μία παράμετρο του τύπου της ουράς και επιστρέφει TRUE αν είναι κενή (ο μετρητής TotalItems είναι 0), και FALSE στην αντίθετη περίπτωση. Αυτή η συνάρτηση δε μεταβάλλει την ουρά. 32

Δηλώσεις και υλοποιήσεις 5 βασικών λειτουργιών για τη στατική ουρά (3/9) 3. Η συνάρτηση bool StaticQueue_Add(TStaticQueue *q, TItem Item) δέχεται μία παράμετρο τύπου δείκτη προς στατική ουρά, και το στοιχείο που θα αποπειραθεί να προσθέσει σε αυτή. Η πρόσθεση ενός στοιχείου μπορεί να γίνει μόνο όταν η ουρά δεν έχει γεμίσει. Στην περίπτωση αυτή προσθέτουμε το στοιχείο στην ουρά, και μετακινούμε το δείκτη Back κατά μία θέση δεξιά. 33

Δηλώσεις και υλοποιήσεις 5 βασικών λειτουργιών για τη στατική ουρά (4/9) 3. (Συνέχεια). Αυτό, φυσικά, πρέπει να γίνει με προσοχή, αφού μπορούμε να βγούμε εκτός του δεξιού ορίου του πίνακα. Ο απαραίτητος έλεγχος γι' αυτήν την περίπτωση φαίνεται στον κώδικα με δύο τρόπους (όπου ο ένας από αυτούς είναι σχολιασμένος). Η σχολιασμένη εκδοχή ελέγχει να υπερβαίνουμε το δεξί όριο του πίνακα, και αν συμβεί κάτι τέτοιο, επαναφέρει το δείκτη Back στην πρώτη θέση του πίνακα (αυτή με δείκτη 0). 34

Δηλώσεις και υλοποιήσεις 5 βασικών λειτουργιών για τη στατική ουρά (5/9) 3. (Συνέχεια). Η ασχολίαστη εκδοχή χρησιμοποιεί την τεχνική του υπολοίπου της διαίρεσης με το μέγιστο πλήθος στοιχείων που μπορεί να δεχθεί ο πίνακας. Η συνάρτηση αυτή δυνητικά μεταβάλλει την ουρά. Όταν η εισαγωγή ήταν επιτυχής ο μετρητής αυξάνει κατά 1 και η συνάρτηση επιστρέφει TRUE, ενώ στην αντίθετη περίπτωση επιστρέφει FALSE, χωρίς, όμως, την τροποποίηση της ουράς. 35

Δηλώσεις και υλοποιήσεις 5 βασικών λειτουργιών για τη στατική ουρά (6/9) 4. Η συνάρτηση bool StaticQueue_Remove(TStaticQueue *q, TItem *Item) δέχεται μία παράμετρο τύπου δείκτη προς στατική ουρά, και μία ακόμη παράμετρο τύπου δείκτη προς τον τύπο των αντικειμένων που αποθηκεύονται σε αυτή. Η αφαίρεση ενός στοιχείου μπορεί να γίνει μόνο όταν η ουρά περιέχει τουλάχιστον ένα στοιχείο. Ο κώδικας διενεργεί τον απαραίτητο έλεγχο πριν την αφαίρεση του πρώτου στοιχείου της ουράς. 36

Δηλώσεις και υλοποιήσεις 5 βασικών λειτουργιών για τη στατική ουρά (7/9) 4. (Συνέχεια). Όσον αφορά την τροποποίηση του δείκτη Front, την επιστρεφόμενη τιμή της συνάρτησης, και την τροποποίηση των παραμέτρων και του μετρητή, ισχύουν όσα έχουν αναφερθεί στην προηγούμενη συνάρτηση. Η συνάρτηση αυτή δυνητικά μεταβάλλει και τις δύο παραμέτρους (ή καμία). 37

Δηλώσεις και υλοποιήσεις 5 βασικών λειτουργιών για τη στατική ουρά (8/9) 5. Η συνάρτηση bool StaticQueue_Front(TStaticQueue q, TItem *Item) δέχεται μία αμετάβλητη παράμετρο του τύπου της ουράς, καθώς και έναν δείκτη προς τον τύπο των στοιχείων που αποθηκεύονται σε αυτή. Η ανάγνωση του μπροστινού στοιχείου της ουράς είναι δυνατή μόνο όταν υπάρχει τουλάχιστον ένα στοιχείο σε αυτή. 38

Δηλώσεις και υλοποιήσεις 5 βασικών λειτουργιών για τη στατική ουρά (9/9) 5. (Συνέχεια). Ο απαραίτητος αυτός έλεγχος θα καθορίσει και την επιστρεφόμενη τιμή της συνάρτησης. Η συνάρτηση αυτή δε μεταβάλλει την ουρά (τότε επιστρέφει FALSE), ενώ ενδέχεται να μεταβάλλει την παράμετρο εξόδου το Item (τότε επιστρέφει TRUE). 39

Ασκήσεις στις στατικές ουρές Άσκηση 1. Υλοποιήστε συνάρτηση που αντιστρέφει τη σειρά των στοιχείων μιας ουράς, αφήνοντας τους δείκτες και το μετρητή ανέπαφους. Άσκηση 2. Υλοποιήστε συνάρτηση που φροντίζει τα στοιχεία μιας ουράς να ξεκινούν από την πρώτη θέση του πίνακα. Δηλαδή, μετακινήστε τα στοιχεία του πίνακα με τέτοιο τρόπο που η αρχή της ουράς να βρίσκεται στη θέση 0, το δεύτερο στοιχείο στη θέση 1, κ.ο.κ. 40

Δυναμικές ουρές (1/16) Στο σχήμα απεικονίζεται μια δυναμική ουρά, η οποία είναι υλοποιημένη αλυσιδωτά με μικρά μπλοκ μνήμης που περιέχουν τα δεδομένα (TItem) και δείκτη σε επόμενο μπλοκ. Εικόνα 2. Δυναμική ουρά. Πηγή: Διδάσκων (2015). 41

Δυναμικές ουρές (2/16) Η δυναμική ουρά χρειάζεται ένα δείκτη Front που δείχνει στο πρώτο στοιχείο της. Είναι αναγκαία και η ύπαρξη ενός δεύτερου δείκτη που να δείχνει στο τελευταίο στοιχείο της ουράς. Με αυτόν τον τρόπο είναι γρήγορη η προσθήκη ενός στοιχείου, αφού έτσι δε χρειάζεται να σαρώσουμε ολόκληρη την ουρά ώστε να βρούμε το τελευταίο στοιχείο και να προσθέσουμε στο δείκτη Next τον καινούργιο κόμβο. Ακολουθεί μια ενδεικτική δήλωση του τύπου μιας δυναμικής ουράς. 42

Δυναμικές ουρές (3/16) typedef int TItem; typedef struct TQueueNodeTAG { TItem Item; TQueueNodeTAG *Next; } TQueueNode; typedef struct { TQueueNode TQueueNode } TDynamicQueue; *Front; *Back; 43

Δυναμικές ουρές (4/16) Όπως και στις προηγούμενες περιπτώσεις, ο βασικός τύπος δεδομένων που αποθηκεύουμε σε μια ουρά αποκαλείται TItem. Ακολουθεί η δήλωση του τύπου της δομής του κόμβου, όπου περιέχονται δύο πεδία: Το στοιχείο που θέλουμε να αποθηκεύσουμε (Item), και ο δείκτης στον επόμενο κόμβο (Next). Τέλος έχουμε τη δομή της δυναμικής ουράς, με τη δήλωση δύο πεδίων για τους δείκτες Front και Back. 44

Δυναμικές ουρές (5/16) Πρέπει να έχουμε υπόψη ότι όταν η ουρά είναι κενή, τότε και οι δύο δείκτες Front και Back είναι NULL. Αντιθέτως, αν υπάρχει έστω και ένα στοιχείο, τότε κανείς τους δεν είναι NULL. Στη συγκεκριμένη δομή θα μπορούσαμε να προσθέσουμε ένα ακόμη πεδίο, που να μετράει το πλήθος των στοιχείων στην ουρά (το οποίο αφαιρέθηκε σκόπιμα). 45

Δυναμικές ουρές (6/16) Η σειρά των ενεργειών για την εισαγωγή ενός στοιχείου στο τέλος της ουράς είναι η εξής: 1. Δέσμευση μνήμης για ένα στοιχείο. 2. Αν η δέσμευση πετύχει, τότε: a. Αντιγράφουμε τα δεδομένα που θέλουμε στο Item του καινούργιου στοιχείου. Το Next θα πάρει, φυσικά, την τιμή NULL, αφού αυτό θα είναι τώρα το τελευταίο στοιχείο στην ουρά. 46

Δυναμικές ουρές (7/16) 2. Αν η δέσμευση πετύχει, τότε (Συνέχεια): b. Προσέχουμε αν η προσθήκη του καινούργιου κόμβου γίνεται σε άδεια ουρά. Αν η ουρά είναι άδεια (Front == NULL), τότε και οι δύο δείκτες Front και Back ενημερώνονται ώστε να δείχνουν στον ίδιο (και μοναδικό για την ώρα) κόμβο. Αν η ουρά δεν είναι άδεια (Front!= NULL), τότε ενημερώνουμε κατάλληλα το δείκτη Back. c. Αναφέρουμε την επιτυχή προσθήκη ενός στοιχείου στην ουρά. 47

Δυναμικές ουρές (8/16) 3. Αν η δέσμευση ΔΕΝ πετύχει, τότε: Αφήνουμε την ουρά αμετάβλητη, δηλαδή δεν επιτελούμε καμία ενέργεια (όπως θα δείτε στην υλοποίηση σε λίγο αυτό είναι εύκολο, αφού δε γράφουμε καθόλου κώδικα). Αναφέρουμε την αποτυχία προσθήκης ενός στοιχείου στην ουρά. 48

Δυναμικές ουρές (9/16) Δηλαδή, όπως παρατηρούμε, η επιτυχής ή ανεπιτυχής εισαγωγή ενός στοιχείου στην ουρά εξαρτάται από την ύπαρξη μνήμης (ή απλούστερα χώρου) για τα νέα δεδομένα. Θα παρατηρήσετε ότι αυτό είναι αντίστοιχο της ύπαρξης χώρου στον πίνακα στην περίπτωση της στατικής ουράς. 49

Δυναμικές ουρές (10/16) Η σειρά των ενεργειών για την ανάγνωση και εξαγωγή ενός στοιχείου από την αρχή μιας ουράς είναι η εξής: 1. Έλεγχος αν η ουρά είναι κενή (ο δείκτης Front είναι NULL). a. Δε μεταβάλλουμε καμία παράμετρο (την ουρά και το χώρο αποθήκευσης της τιμής στον πρώτο κόμβο της). b. Αναφέρουμε την αποτυχία ανάγνωσης και εξαγωγής του πρώτου στοιχείου της ουράς. 50

Δυναμικές ουρές (11/16) 2. Αν η ουρά ΔΕΝ είναι κενή, τότε: a. Δηλώνουμε προσωρινό δείκτη στον τύπο της δομής, και αντιγράφουμε σε αυτόν τα περιεχόμενα του δείκτη Front. b. Τροποποιούμε το δείκτη Front ώστε να δείχνει στον επόμενο κόμβο της ουράς, σε σχέση με αυτόν που έδειχνε μόλις πριν λίγο. c. Ενημερώνουμε την παράμετρο με τα δεδομένα του στοιχείου που θα αφαιρέσουμε. d. Ελευθερώνουμε το χώρο μνήμης που δεσμεύτηκε για το προς αφαίρεση στοιχείο. e. Προσέχουμε αν ο δείκτης Front είναι NULL, αφού αυτό σημαίνει ότι η ουρά άδειασε. Σε αυτήν την περίπτωση κάνουμε NULL και το δείκτη Back. f. Αναφέρουμε την επιτυχή εξαγωγή του επάνω στοιχείου της ουράς. 51

Δυναμικές ουρές (12/16) Θα παρατηρήσετε για μία ακόμη φορά ότι η επιτυχία της συγκεκριμένης λειτουργία εξαρτάται αποκλειστικά από την ύπαρξη στοιχείων στην ουρά, δηλαδή όπως ακριβώς και με την περίπτωση της στατικής υλοποίησης. 52

Δυναμικές ουρές (13/16) Η σειρά των ενεργειών για την απλή ανάγνωση του στοιχείου στην αρχή μιας ουράς, χωρίς την αφαίρεσή του, είναι η εξής: 1. Έλεγχος αν η ουρά είναι κενή (ο δείκτης Front είναι NULL). a. Δε μεταβάλλουμε καμία παράμετρο. Φυσικά η ουρά στην παρούσα λειτουργία δε θα άλλαζε, ούτως ή άλλως. b. Αναφέρουμε την αποτυχία ανάγνωσης του πρώτου στοιχείου από την ουρά. 2. Αν η ουρά ΔΕΝ είναι κενή, τότε: a. Αντιγράφουμε τα δεδομένα (Item) του πρώτου στοιχείου της ουράς στην παράμετρο. b. Αναφέρουμε την επιτυχή ανάγνωση του πρώτου στοιχείου της ουράς. 53

Δυναμικές ουρές (14/16) Το μέτρημα των στοιχείων μιας δυναμικής ουράς γίνεται με τη χρήση ενός προσωρινού δείκτη που, για αρχή, δείχνει στο πρώτο στοιχείο. Με τη βοήθεια αυτού του δείκτη «κατεβαίνουμε» στην ουρά μέχρι αυτός να γίνει NULL, μετρώντας ταυτόχρονα τα στοιχεία της ένα-ένα. Η χρήση του προσωρινού δείκτη είναι απαραίτητη, αφού αν τροποποιήσουμε το δείκτη Front, στο τέλος θα χάσουμε ολόκληρη την ουρά. 54

Δυναμικές ουρές (15/16) Εξάλλου, η λειτουργία του μετρήματος των στοιχείων μιας ουράς δε θα πρέπει να τη μεταβάλλει καθόλου, αλλά απλά να μετράει τα στοιχεία της. Η αποδέσμευση των στοιχείων μιας ουράς είναι απαραίτητη ώστε να επιστρέψουμε πίσω στο ΛΣ τη μνήμη που έχουμε δεσμεύσει. Ο τρόπος υλοποίησης είναι παρόμοιος με το μέτρημα, δηλαδή με τη χρήση ενός προσωρινού δείκτη ο οποίος προοδευτικά δείχνει ολοένα και πιο κάτω, αποδεσμεύοντας τη μνήμη καθ' οδόν. 55

Δυναμικές ουρές (16/16) Τα πλεονεκτήματα και μειονεκτήματα όσον αφορά τη στατική ή δυναμική υλοποίηση μιας ουράς συνοψίζονται ως εξής: Η στατική ουρά είναι απλούστερη στην υλοποίηση. Η στατική ουρά δέχεται σταθερό μέγιστο αριθμό στοιχείων, είτε χρησιμοποιείται ολόκληρη η μνήμη, είτε όχι. Η δυναμική ουρά χρησιμοποιεί μνήμη ανάλογη των στοιχείων που έχει αποθηκευμένα. Ο χώρος που απαιτείται για την αποθήκευση των δεδομένων σε κάθε κόμβο μιας δυναμικής ουράς είναι μεγαλύτερος σε σχέση με τη στατική, αφού σε κάθε κόμβο αποθηκεύονται όχι μόνο τα δεδομένα που θέλουμε, αλλά και ένας δείκτης προς το επόμενο στοιχείο. 56

Ενδεικτική υλοποίηση δυναμικής ουράς (1/14) /* -------------------------------------------------------------------------- */ #include <stdio.h> #include <stdlib.h> /* -------------------------------------------------------------------------- */ typedef int TItem; typedef struct TQueueNodeTAG { TItem Item; TQueueNodeTAG *Next; } TQueueNode; 57

Ενδεικτική υλοποίηση δυναμικής ουράς (2/14) typedef struct { TQueueNode *Front; TQueueNode *Back; } TDynamicQueue; void DynamicQueue_Init(TDynamicQueue *q) { q->front = NULL; q->back = NULL; } // DynamicQueue_Init 58

Ενδεικτική υλοποίηση δυναμικής ουράς (3/14) bool DynamicQueue_IsEmpty(TDynamicQueue q) { return ( q.front == NULL ); } // DynamicQueue_IsEmpty bool DynamicQueue_Add(TDynamicQueue *q, TItem Item) { TQueueNode *NewNode; NewNode = (TQueueNode *) malloc(sizeof(tqueuenode)); 59

Ενδεικτική υλοποίηση δυναμικής ουράς (4/14) if ( NewNode!= NULL ) { NewNode->Item = Item; NewNode->Next = NULL; // Or q->front if ( q->front!= NULL ) // Add after end of the queue. q->back = q->back->next = NewNode; else // This will be the first item on the queue. q->front = q->back = NewNode; return ( true ); } else return ( false ); } // DynamicQueue_Add 60

Ενδεικτική υλοποίηση δυναμικής ουράς (5/14) bool DynamicQueue_Remove(TDynamicQueue *q, TItem *Item) { if ( q->front == NULL ) return ( false ); TQueueNode *Tmp = q->front; q->front = q->front->next; *Item = Tmp->Item; free(tmp); if ( q->front == NULL ) q->back = NULL;//If queue is empty, Back= NULL. return ( true ); } // DynamicQueue_Remove 61

Ενδεικτική υλοποίηση δυναμικής ουράς (6/14) bool DynamicQueue_Front(TDynamicQueue q, TItem *Item) { if ( q.front == NULL ) return ( false ); *Item = q.front->item; return ( true ); } // DynamicQueue_Front 62

Ενδεικτική υλοποίηση δυναμικής ουράς (7/14) size_t DynamicQueue_Count(TDynamicQueue q) { TQueueNode *Tmp = q.front; size_t Counter = 0; while ( Tmp!= NULL ) { Counter++; Tmp = Tmp->Next; } // while return ( Counter ); } // DynamicQueue_Count 63

Ενδεικτική υλοποίηση δυναμικής ουράς (8/14) void DynamicQueue_Deallocate(TDynamicQueue *q) { TQueueNode *Tmp = q->front; while ( q->front!= NULL ) { q->front = q->front->next; free(tmp); Tmp = q->front; } // while q->back = NULL; } // DynamicQueue_Deallocate 64

Ενδεικτική υλοποίηση δυναμικής ουράς (9/14) void DynamicQueue_Write(TDynamicQueue q) { TQueueNode *Tmp = q.front; printf("\ndynamicqueue_write\n"); printf("--------------------\n"); printf("front Pointer = 0x%08X\n", q.front); printf(" Back Pointer = 0x%08X\n", q.back); printf(" Total Items = %3u\n", DynamicQueue_Count(q)); printf(" Queue Items = "); while ( Tmp!= NULL ) { printf("%3d ", Tmp->Item); Tmp = Tmp->Next; } // while printf("\n"); } // DynamicQueue_Write 65

Ενδεικτική υλοποίηση δυναμικής ουράς (10/14) void main() { TDynamicQueue queue; TItem item; int i; DynamicQueue_Init(&queue); DynamicQueue_Write(queue); DynamicQueue_Add(&queue, rand()); DynamicQueue_Add(&queue, rand()); DynamicQueue_Write(queue); 66

Ενδεικτική υλοποίηση δυναμικής ουράς (11/14) DynamicQueue_Remove(&queue, &item); // DynamicQueue_Remove(&queue, &item); DynamicQueue_Write(queue); // Add 10 items just for testing. for ( i = 0; i < 10; i++ ) DynamicQueue_Add(&queue, rand()); DynamicQueue_Write(queue); if ( DynamicQueue_Add(&queue, rand()) ) printf("\n\nadded item\n\n\n"); else printf("\n\nout of memory, cannot add more items\n\n\n"); DynamicQueue_Write(queue); 67

Ενδεικτική υλοποίηση δυναμικής ουράς (12/14) if ( DynamicQueue_Front(queue, &item) ) printf("\n\nqueue Front = %3d\n\n\n", item); else printf("\n\nqueue is empty, cannot extract item\n\n\n"); if ( DynamicQueue_Remove(&queue, &item) ) printf("\n\nremoved from Queue = %3d\n\n\n", item); else printf("\n\nqueue is empty, cannot extract item\n\n\n"); DynamicQueue_Write(queue); 68

Ενδεικτική υλοποίηση δυναμικής ουράς (13/14) while ( DynamicQueue_Remove(&queue, &item) ); DynamicQueue_Write(queue); if ( DynamicQueue_Front(queue, &item) ) printf("\n\nqueue Front = %3d\n\n\n", item); else printf("\n\nqueue is empty, cannot extract item\n\n\n"); DynamicQueue_Deallocate(&queue); } // main 69

Ενδεικτική υλοποίηση δυναμικής ουράς (14/14) Η τρόπος υλοποίησης των επιμέρους λειτουργιών είναι παρόμοιος με τη στατική ουρά, αλλά αυτήν τη φορά δεσμεύουμε και αποδεσμεύουμε μνήμη με τις συναρτήσεις malloc και free, αντίστοιχα. Οι συνθήκες που καθορίζουν την επιτυχία ή αποτυχία μιας λειτουργίας παραμένουν οι ίδιες: Προσθήκη ενός στοιχείου: επαρκής μνήμη. Ανάγνωση και αφαίρεση ενός στοιχείου: η ουρά δεν είναι κενή. Ανάγνωση του στοιχείου στην αρχή μιας ουράς: η ουρά δεν είναι κενή. 70

Ασκήσεις στις δυναμικές ουρές

Άσκηση 1 (1/2) Επειδή ο κώδικας της δυναμικής ουράς έχει προστεθεί στη βιβλιοθήκη ενός έργου, χρησιμοποιείται εκτενώς σε άλλα προγράμματα. Σας έχουν ενημερώσει ότι το μέτρημα των στοιχείων της ουράς καθυστερεί κάποιους αλγόριθμους. Επίσης, γνωρίζετε ότι δεν πρέπει να αλλάξετε τίποτε από τις δηλώσεις (δηλαδή τα πρωτόκολλα κλήσης) των παραπάνω συναρτήσεων. 72

Άσκηση 1 (2/2) Προβείτε στις κατάλληλες ενέργειες ώστε η ουρά να γνωρίζει ανά πάσα στιγμή το πλήθος των στοιχείων που έχει, χωρίς να χρειάζεται μέτρημα. Μην αφαιρέσετε τη συνάρτηση size_t DynamicQueue_Count(TDynamicQueue q). 73

Άσκηση 2 Χρησιμοποιώντας ως βάση τον κώδικα της στατικής ουράς, υλοποιήστε το συγκεκριμένο ΑΤΔ αλλά όχι με τη στρατηγική της μέτρησης των θέσεων του πίνακα που χρησιμοποιούνται, αλλά αυτής που αφήνει πάντοτε ένα κενό στοιχείο (δηλαδή στην ουρά θα έχετε το πολύ στοιχεία). 74

Άσκηση 3 Στη συγκεκριμένη άσκηση καλείστε να πράξετε το ίδιο και στους δύο τύπους ουράς που εξετάσαμε (στατική και δυναμική): Υλοποιήστε συνάρτηση που αντιστρέφει την ουρά. Φροντίστε και στις δύο περιπτώσεις να χρησιμοποιήσετε όσο το δυνατόν λιγότερη πρόσθετη μνήμη. 75

Άσκηση 4 (1/2) Υλοποιήστε εξ αρχής τη στατική ουρά με τρόπο που να ορίζετε εσείς το πλήθος των θέσεων της ουράς (στη συνάρτηση Init). Βοήθεια: Θυμηθείτε τα παραδείγματα της δυναμικής δέσμευσης μνήμης για μονοδιάστατους πίνακες. Θα σας βοηθήσουν οι συναρτήσεις malloc και free. 76

Άσκηση 4 (2/2) Συνεπώς θα πρέπει να προσθέσετε και μια συνάρτηση αποδέσμευσης της ουράς. Όσον αφορά τη στρατηγική που σας επιτρέπει να γνωρίζετε πότε γέμισε η ουρά, χρησιμοποιήστε αυτή με το μετρητή. 77

Άσκηση 5 (1/2) Επεκτείνετε την προηγούμενη άσκηση έτσι ώστε να μπορεί να μεταβάλλεται ο συνολικός χώρος μιας ουράς, χωρίς να χάνονται τα στοιχεία του σε περίπτωση αποτυχημένης επέκτασής του. Βοήθεια: Χρησιμοποιήστε τη συνάρτηση realloc (επιτρέπει την επέκταση ή συρρίκνωση ενός χώρου μνήμης χωρίς την απώλεια των δεδομένων του). 78

Άσκηση 5 (2/2) Ίσως θεωρήσετε ότι είναι συνετό να συρρικνώνετε το χώρο της μνήμης όταν ο χώρος που είναι κενός ξεπερνάει το 50% του συνολικού δεσμευμένου χώρου. Σε αυτήν την περίπτωση μια μετακίνηση των στοιχείων της ουράς στην αρχή του χώρου μνήμης θα σας διευκολύνει. 79

Άσκηση 6 (1/4) Για μία ακόμη φορά διαπιστώνετε ότι στη συνάντηση της προγραμματιστικής ομάδας ενός έργου, η βιβλιοθήκη σας για τις δυναμικές ουρές πρέπει να τροποποιηθεί. Σας ενημερώνουν ότι η προσθήκη στοιχείων πρέπει να βελτιωθεί. Ανακαλύπτετε ότι είναι προτιμότερη η δέσμευση αρκετών κόμβων μαζί (π.χ. 10), και η σταδιακή χρήση τους όταν αυτή είναι απαραίτητη. 80

Άσκηση 6 (2/4) Αυτό που σας ζητούν είναι όταν θέλετε να προσθέσετε στοιχεία σε μια δυναμική ουρά, πρέπει να δεσμεύετε χώρο όχι για ένα μόνο στοιχείο τη φορά, αλλά για περισσότερα (χρησιμοποιήστε σταθερά στην αρχή του προγράμματός σας). Έτσι, όταν θέλετε να προσθέσετε ένα στοιχείο, τότε δεσμεύετε 10 κόμβους και ενημερώνετε τον πρώτο. 81

Άσκηση 6 (3/4) Με αυτόν τον τρόπο σας περισσεύουν ακόμη 9 θέσεις για πρόσθεση στοιχείων, χωρίς να χρειάζεται η εκ νέου δέσμευση χώρου - απλά ενημερώνετε τους επόμενους διαθέσιμους κόμβους. Μόλις γεμίσουν και οι άλλες 9 θέσεις και χρειαστείτε επιπλέον χώρο, τότε επαναλαμβάνετε το παραπάνω. 82

Άσκηση 6 (4/4) Δηλαδή, η δέσμευση του χώρου γίνεται μαζικά, ανά Ν (π.χ. 10) κόμβους, και χρησιμοποιούνται κατ' απαίτηση. Φροντίστε για τις όσο το δυνατόν ελάχιστες τροποποιήσεις στην κλήση των συναρτήσεων (ακόμη και καθόλου). 83

Άσκηση 7 (1/2) Επειδή ο επικεφαλής της προγραμματιστικής ομάδας στην οποία εργάζεστε έχει φύγει για διακοπές σε εξωτικό νησί, σας έχει ανατεθεί να τελειώσετε εσείς αυτό που του είχε ανατεθεί πριν φύγει για ξεκούραση. Η αποδέσμευση των κόμβων στην αρχή της ουράς πρέπει, τώρα, να γίνεται μαζικά, όπως και με τη δέσμευση. 84

Άσκηση 7 (2/2) Δηλαδή, όταν αφαιρεθούν Ν (π.χ. 10) στοιχεία, τότε να γίνεται η αποδέσμευση των κόμβων που τα περιείχαν. Μπορείτε, φυσικά, να προσθέσετε τα πεδία που χρειάζεστε στη δομή της δυναμικής ουράς, αλλά ελαχιστοποιήσετε (ή αποφύγετε εντελώς) τις αλλαγές στις δηλώσεις των συναρτήσεων. 85

Άσκηση 8 Ο επικεφαλής της προγραμματιστικής ομάδας στην οποία εργάζεστε, και εξακολουθεί να βρίσκεται σε διακοπές, επικοινωνεί μαζί σας μέσω Skype και σας αποκαλύπτει μια ωραία ιδέα που είχε. Σας λέει, τώρα, ότι η αποδέσμευση των κόμβων (δηλ. όταν αφαιρούνται στοιχεία) πρέπει να γίνεται όταν το όφελος στον αποθηκευμένο χώρο υπερβαίνει το 10% του συνολικού δεσμευμένου χώρου. Προσπαθήστε να υλοποιήσετε αυτήν την ιδέα, με τις απολύτως ελάχιστες αλλαγές. 86

Ερωτήσεις

Ερώτηση 1 (1/2) Η δέσμευση και αποδέσμευση μνήμης μπορούν να είναι χρονικά δαπανηρές ενέργειες. Όπως ξέρουμε, όταν προσθέτουμε κόμβους, δεσμεύουμε μνήμη. Όταν αφαιρούμε, αποδεσμεύουμε. Μια ιδέα θα ήταν να έχουμε ανά πάσα στιγμή μια συλλογή διαθέσιμων κόμβων. Όταν χρειαζόμαστε χώρο, απλά χρησιμοποιούμε έναν από τους διαθέσιμους. 88

Ερώτηση 1 (2/2) Όταν αφαιρούμε ένα στοιχείο από την ουρά, τότε «μεταφέρουμε» τον κόμβο που μόλις κατέστη διαθέσιμος στη συλλογή των κόμβων. Αυτή η συλλογή των κόμβων μπορεί να έχει συγκεκριμένο μέγεθος (π.χ. 10, αλλά καθορίζεται στην αρχή του προγράμματος με μια σταθερά). Θα μπορούσατε να χρησιμοποιήσετε μια στατική ουρά για την αποθήκευση των διαθέσιμων κόμβων που θα μπαινοβγαίνουν στη δυναμική ουρά; Περιγράψτε λεπτομερώς τα βήματα που θα χρειαζόσασταν σε ένα τέτοιο σενάριο. 89

Ερώτηση 2 (1/2) Η δέσμευση και αποδέσμευση μνήμης απαιτούν τη διατήρηση κατάλληλων δομών από τον εκάστοτε διαχειριστή μνήμης. Θα μπορούσαμε να συνδυάσουμε στατικές με δυναμικές ουρές, ώστε να επιβαρύνουμε λιγότερο το διαχειριστή μνήμης. Τώρα, κάθε ένας κόμβος μιας δυναμικής ουράς αποτελείται από μια στατική ουρά που έχει συγκεκριμένο πλήθος στοιχείων. 90

Ερώτηση 2 (2/2) Έτσι, μια ουρά 1000 στοιχείων θα χρειάζεται μόνο 20 κόμβους. Ένας κόμβος της δυναμικής ουράς αποδεσμεύεται όταν αδειάσει πλήρως η στατική ουρά που περιέχει. Δεσμεύεται χώρος για έναν καινούργιο κόμβο όταν γεμίσει πλήρως ο τελευταίος. Περιγράψτε λεπτομερώς τα βήματα που θα χρειαζόσασταν σε ένα τέτοιο σενάριο. 91

Βιβλιογραφία (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). 92

Βιβλιογραφία (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. 93

Βιβλιογραφία (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. 94

Βιβλιογραφία (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. 95

Βιβλιογραφία (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. 96

Βιβλιογραφία (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. 97

Βιβλιογραφία (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. 98

Βιβλιογραφία (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. 99

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

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

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

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