Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

ΕΙΣΑΓΩΓΗ ΣΤΗΝ ΠΛΗΡΟΦΟΡΙΚΗ Κεφάλαιο 9 Δομές Δεδομένων σε C Γιώργος Γιαγλής.

Παρόμοιες παρουσιάσεις


Παρουσίαση με θέμα: "ΕΙΣΑΓΩΓΗ ΣΤΗΝ ΠΛΗΡΟΦΟΡΙΚΗ Κεφάλαιο 9 Δομές Δεδομένων σε C Γιώργος Γιαγλής."— Μεταγράφημα παρουσίασης:

1 ΕΙΣΑΓΩΓΗ ΣΤΗΝ ΠΛΗΡΟΦΟΡΙΚΗ Κεφάλαιο 9 Δομές Δεδομένων σε C Γιώργος Γιαγλής

2 Περίληψη Κεφαλαίου 9 Δομές Δεδομένων – Δυναμικές Δομές Δεδομένων – Λίστες Διάσχιση λίστας, Αναζήτηση στοιχείου σε λίστα, Εισαγωγή στοιχείου σε λίστα, Διαγραφή στοιχείου από λίστα, Άλλες μορφές λιστών – Στοίβες Εισαγωγή στοιχείου σε στοίβα, Εξαγωγή στοιχείου από στοίβα, Υλοποίηση στοίβας με πίνακα – Ουρές Εισαγωγή στοιχείου σε ουρά, Εξαγωγή στοιχείου από ουρά, Υλοποίηση ουράς με πίνακα – Δένδρα και Γράφοι Παράσταση δένδρων στη C, Διάσχιση δένδρου, Δυαδικά δένδρα αναζήτησης 2

3 Δυναμικές Δομές Δεδομένων Ως τώρα έχουμε συναντήσει δομές δεδομένων στις οποίες προκαθορίζεται το μέγεθος και πλήθος των στοιχείων-μεταβλητών Αποτέλεσμα – Περιορισμένη χωρητικότητα των Δομών Δεδομένων, θα πρέπει το πρόγραμμα να ξαναγραφτεί στο μέλλον – Υπερβολική και άσκοπη κατάληψη μνήμης από κενό πίνακα Αντιμετώπιση: Δυναμικές Δομές Δεδομένων Το μέγεθος τους αυξομειώνεται ανάλογα με τις ανάγκες, έτσι ώστε να χρησιμοποιεί πάντα ακριβώς το χώρο που τους είναι απαραίτητος (π.χ. ένας πίνακας για φοιτητές του ΟΠΑ, που το μέγεθος του να αυξάνεται κάθε φορά που ένας νέος φοιτητής εισάγεται στη βάση και να μειώνεται κάθε φορά που κάποιος διαγράφεται από αυτή ) Πώς; Με χρήση Δεικτών, επιτρέπουν την έμμεση αναφορά στη μνήμη του υπολογιστή Εφαρμογές – Λίστες – Στοίβες – Ουρές 3

4 Λίστες Απλά Συνδεδεμένες Δυναμικές Λίστες Τι είναι; Μια συνεχόμενη αναπαράσταση στοιχείων( κόμβοι της λίστας) Κάθε κόμβος συνδέεται με τον επόμενο μέσω μιας μεταβλητή δείκτη Παράδειγμα μιας απλής λίστας: Έχουμε 4 κόμβους Κάθε κόμβος αποτελείται από 2 μέρη: – στο πρώτο αποθηκεύεται η πληροφορία που μας ενδιαφέρει – το δεύτερο μέρος είναι ένας δείκτης στον επόμενο κόμβο της λίστας ΠΑΡΑΤΗΡΗΣΕΙΣ: – η υλοποίηση ενός κόμβου λίστας στη C θα γίνεται με μια δομή (struct) – αρχή της λίστας ορίζεται από μια μεταβλητή δείκτη που «δείχνει» στον πρώτο κόμβο – ο δείκτης στον τελευταίο κόμβο της λίστας έχει μια ειδική τιμή (ονομάζεται nil ή null) που ορίζει ότι ο δείκτης αυτός δε δείχνει πουθενά 4

5 Λίστες, Δημιουργία Λίστας struct Komvos { int Plhroforia; struct Komvos *next; }; struct Komvos *Lista; Κάθε κόμβος αποτελείται από ένα ακέραιο αριθμό Plhroforia και ένα δείκτη ο οποίος ονομάζεται next και δείχνει σε μια δομή τύπου Komvos 5 Δημιουργία Λίστας Βήμα 1: Αρχική Δήλωση Λίστας Ορίζουμε τον τύπο των κόμβων της Ορίζουμε μια μεταβλητή δείκτη σε έναν τέτοιο κόμβο Σχηματικά: Βήμα 1: Αρχική Δήλωση Λίστας

6 Δημιουργία Λίστας Βήμα 2: Δημιουργία Πρώτου κόμβου Χρήση συνάρτησης malloc: επιτρέπει τη δυναμική δέσμευση χώρου μνήμης για χρήση από κάποια μεταβλητή Σχηματικά: Βήμα 2: Δημιουργία Πρώτου κόμβου Λίστες, Δημιουργία Λίστας ΜεταβλητήΔείκτη = (ΤύποςΚόμβου *) malloc(sizeof(ΤύποςΚ όμβου)); Όρισμα το μέγεθος της δομής στην οποία θα δημιουργήσει ένα δείκτη [sizeof(ΤύποςΚόμβου)] Επιστρέφει ένα δείκτη σε μια τέτοια δομή, (ΤύποςΚόμβου *) της παραπάνω δήλωσης. Ο δείκτης αυτός εκχωρείται σε κάποια ΜεταβλητήΔείκτη, η οποία έτσι «δείχνει» σε μια «νέα» περιοχή της μνήμης που έχει δεσμευτεί για αυτό το σκοπό. 6

7 Δημιουργία Λίστας Βήμα 2: Δημιουργία Πρώτου κόμβου Χρήση συνάρτησης malloc: επιτρέπει τη δυναμική δέσμευση χώρου μνήμης για χρήση από κάποια μεταβλητή Σχηματικά: Βήμα 2: Δημιουργία Πρώτου κόμβου Λίστες, Δημιουργία Λίστας ΜεταβλητήΔείκτη = (ΤύποςΚόμβου *) malloc(sizeof(ΤύποςΚ όμβου)); Όρισμα το μέγεθος της δομής στην οποία θα δημιουργήσει ένα δείκτη [sizeof(ΤύποςΚόμβου)] Επιστρέφει ένα δείκτη σε μια τέτοια δομή, (ΤύποςΚόμβου *) της παραπάνω δήλωσης. Ο δείκτης αυτός εκχωρείται σε κάποια ΜεταβλητήΔείκτη, η οποία έτσι «δείχνει» σε μια «νέα» περιοχή της μνήμης που έχει δεσμευτεί για αυτό το σκοπό. 7

8 Λίστες, Δημιουργία Λίστας Δημιουργία Λίστας Βήμα 2: Δημιουργία Πρώτου κόμβου ΠΑΡΑΤΗΡΗΣΕΙΣ: η ΜεταβλητήΔείκτη έχει αποκτήσει τιμή και δείχνει σε ένα νέο κόμβο. Δηλαδή δεσμεύεται για πρώτη φορά στη μνήμη, όχι στη δήλωση, αλλά στη διάρκεια εκτέλεσης του προγράμματος Τα περιεχόμενα του κόμβου είναι ακόμα αόριστα, αφού δεν έχει δοθεί κάποια αρχική τιμή σε αυτά Μεταβλητή του κόμβου αυτού δεν έχει κάποιο όνομα. Ο μόνος τρόπος προσπέλασης της είναι μέσω κάποιου δείκτη που δείχνει σε αυτή (έμμεση αναφορά μνήμης) 8

9 Δημιουργία Λίστας Βήμα 3: Δημιουργία Κόμβου στον οποίο θα δείχνει η Lista Χρήση συνάρτησης malloc Σχηματικά: Βήμα 3: Δημιουργία Κόμβου στον οποίο θα δείχνει η Lista ΠΑΡΑΤΗΡΗΣΗ: Τα περιεχόμενα του κόμβου που δημιουργήθηκε έχουν αόριστη τιμή Λίστες, Δημιουργία Λίστας 9 Lista = (struct Komvos *) malloc(sizeof(struct Komvos)); Δεσμεύεται στη μνήμη ελεύθερος χώρος ίσο με το χώρο που απαιτείται για μια μεταβλητή δομής τύπου Komvos Δίνεται τιμή στη μεταβλητή Lista, η διεύθυνση του πρώτου byte αυτού του νέου χώρου μνήμης

10 Δημιουργία Λίστας Βήμα 4: Απόδοση τιμών στα περιεχόμενα του νέου κόμβου Σχηματικά: Βήμα 4: Απόδοση τιμών στα περιεχόμενα του νέου κόμβου Λίστες, Δημιουργία Λίστας Lista -> Plhroforia = 1; Lista -> next = NULL; Απόδοση τιμών στα πεδία Plhroforia και next του κόμβου που δημιουργήσαμε 10 Χρήση τελεστή -> ΜεταβλητήΔείκτη -> ΌνομαΠεδίου

11 Δημιουργία Λίστας Βήμα 5: Δημιουργία επόμενου κόμβου Α τρόπος Σχηματικά: Βήμα 5: Δημιουργία επόμενου κόμβου (α τρόπος) Λίστες, Δημιουργία Λίστας Lista = (struct Komvos *) malloc(sizeof(struct Komvos)); Lista -> Plhroforia = 2; Lista -> next = NULL; Δημιουργείται νέος κόμβος, η εντολή Lista δείχνει σ αυτόν. Απόδοση τιμών στον κόμβο 11 ΜειονέκτημαΠροτεινόμενη Λύση Δεν μπορούμε πια να προσπελάσουμε τον πρώτο κόμβο Να αποδώσουμε τιμή στη μεταβλητή Lista -> next του πρώτου κόμβου (β τρόπος)

12 Δημιουργία Λίστας Βήμα 5: Δημιουργία επόμενου κόμβου Β τρόπος Σχηματικά: Βήμα 5: Δημιουργία επόμενου κόμβου (β τρόπος) Λίστες, Δημιουργία Λίστας Lista -> next = (struct Komvos *) malloc(sizeof(struct Komvos)); Lista -> next -> Plhroforia = 2; Lista -> next -> next = NULL; Απόδοση τιμής στη μεταβλητή Lista -> next του πρώτου κόμβου 12 ΜειονέκτημαΠροτεινόμενη Λύση Δεν μπορεί να χρησιμοποιηθεί αποτελεσματικά για τη δημιουργία πολλών κόμβων (πχ αν είχαμε 100 κόμβους;) Δεν μπορεί να εκμεταλλευτεί τη δύναμη των εντολών επανάληψης Χρήση μιας δεύτερης μεταβλητής δείκτη, έστω temp, που να δείχνει πάντα στον τελευταίο κόμβο της λίστας μας

13 Δημιουργία Λίστας Βήμα 5: Δημιουργία επόμενου κόμβου Γ τρόπος Προτεινόμενος τρόπος: γ τρόπος δημιουργεί μια λίστα με δυο κόμβους μέσω της μεταβλητής temp μπορούμε πια να ορίσουμε και τους υπόλοιπους κόμβους με μια εντολή επανάληψης χωρίς να χρειαστεί να ξαναπειράξουμε την αρχική μεταβλητή Lista Λίστες, Δημιουργία Λίστας Komvos *temp; temp = (struct Komvos *) malloc(sizeof(struct Komvos)); temp -> Plhroforia = 2; temp -> next = NULL; Lista -> next = temp; 1) Ορίζει μια μεταβλητή δείκτη σε κόμβο με το όνομα temp 2)Δημιουργεί ένα νέο κόμβο στον οποίο θα δείχνει η temp 3)Αποδίδει περιεχόμενα κόμβο στον οποίο δείχνει η temp 4) Συνδέει τους δυο κόμβους μέσω απόδοσης τιμής στη μεταβλητή Lista -> next έτσι ώστε αυτή να δείχνει στον ίδιο κόμβο που δείχνει και η temp 13

14 Λίστες, Δημιουργία Λίστας Δημιουργία Λίστας Βήμα 5: Δημιουργία επόμενου κόμβου (γ τρόπος) Σχηματικά 14

15 Λίστες, Διάσχιση Λίστας Η Λίστα είναι μια μορφή δυναμικής δομής δεδομένων Η δυναμική διαχείριση μνήμης δημιουργεί δυσκολίες στον τρόπο άμεσης αναφοράς στα περιεχόμενα της λίστας. Δηλαδή μόνο ο πρώτος κόμβος μπορεί να προσπελαστεί άμεσα. Για να προσπελαστεί ο κόμβος που επιθυμούμε, πρέπει να προσπελαστούν και όλοι οι προηγούμενοι του 15

16 Λίστες, Διάσχιση Λίστας Αλγόριθμος Διάσχισης Λίστας 1.Ορίζουμε μια βοηθητική μεταβλητή δείκτη, έστω temp(απαραίτητη για να διασχίσουμε τη λίστα χωρίς να αλλάξουμε τα περιεχόμενα της μεταβλητής Lista) 2.Μετακινούμαστε από κόμβο σε κόμβο μέσω της μεταβλητής temp->next, η οποία δείχνει πάντα στον επόμενο κόμβο της λίστας 3.Η διάσχιση τελειώνει όταν η μεταβλητή temp->next έχει τιμή NULL(τέλος λίστας) ή όταν βρεθεί το ζητούμενο στοιχείο ΠΡΟΣΟΧΗ: Οριακές περιπτώσεις – Άδεια δομή (δείτε το παράδειγμα που ακολουθεί) – Γεμάτη Δομή – Η δραστηριότητα που θέλουμε να επιτελέσουμε πρέπει να γίνει στον πρώτο κόμβο (δείτε το παράδειγμα δημιουργίας της λίστας, όπου ο πρώτος κόμβος δημιουργείται διαφορετικά από τους υπόλοιπους) – Η δραστηριότητα που θέλουμε να επιτελέσουμε πρέπει να γίνει στον τελευταίο κόμβο 16

17 Λίστες, Διάσχιση Λίστας Αλγόριθμος Διάσχισης Λίστας 17 temp = Lista; /* αρχικοποίηση μεταβλητής temp */ if (temp == NULL) /* αν η λίστα είναι κενή */ printf(“Κενή Λίστα!”) else do printf(“%d”, temp -> Plhroforia); /* εκτύπωση τιμής κάθε κόμβου */ temp = temp -> next; /* μετακίνηση στον επόμενο κόμβο */ while (temp!= NULL); /* όσο υπάρχουν ακόμα επόμενοι κόμβοι */ temp = Lista; /* αρχικοποίηση μεταβλητής temp */ if (temp == NULL) /* αν η λίστα είναι κενή */ printf(“Κενή Λίστα!”) else do printf(“%d”, temp -> Plhroforia); /* εκτύπωση τιμής κάθε κόμβου */ temp = temp -> next; /* μετακίνηση στον επόμενο κόμβο */ while (temp!= NULL); /* όσο υπάρχουν ακόμα επόμενοι κόμβοι */

18 Λίστες, Διάσχιση Λίστας Εναλλακτικός Αλγόριθμος Διάσχισης Λίστας ΜΕΙΟΝΕΚΤΗΜΑ Δεν τυπώνει τίποτα σε περίπτωση που η λίστα είναι κενή 18 temp = Lista; /* αρχικοποίηση μεταβλητής temp */ while (temp != NULL) /* όσο η λίστα δεν είναι κενή */ {printf(“%d”, temp -> Plhroforia); /* εκτύπωση τιμής κάθε κόμβου */ temp = temp -> next; /* μετακίνηση στον επόμενο κόμβο */ }

19 Λίστες, Αναζήτηση Στοιχείου σε Λίστα Στις Λίστες μπορούμε να εφαρμόσουμε ΜΟΝΟ Γραμμική Αναζήτηση Αλγόριθμος παρόμοιος με αλγόριθμο διάσχισης Παράδειγμα αλγορίθμου Αναζήτησης σε μη ταξινομημένη λίστα 19 Αναζήτηση στοιχείου με τιμή Stoxos (βοηθητική ακέραια μεταβλητή Vrethike (true) αν το στοιχείο βρεθεί και (false) διαφορετικά) temp = Lista; /* αρχικοποίηση μεταβλητής temp */ Vrethike = 0; /* αρχικοποίηση μεταβλητής: το στοιχείο δεν έχει βρεθεί */ while ((temp!=NULL) && (!Vrethike)) /* όσο δεν τέλειωσε η λίστα και δεν έχει βρεθεί */ if (temp -> Plhroforia == Stoxos) /* αν το στοιχείο βρεθεί */ Vrethike = 1; if (Vrethike) /* αν η επανάληψη τελειώσει επειδή το στοιχείο βρέθηκε */ printf(“Το στοιχείο υπάρχει στη λίστα”) else /* αν η επανάληψη τελειώσει επειδή η λίστα εξαντλήθηκε */ printf(“Το στοιχείο δεν υπάρχει στη λίστα”);

20 Λίστες, Αναζήτηση Στοιχείου σε Λίστα Παράδειγμα αλγορίθμου Αναζήτησης σε ταξινομημένη λίστα 20 Αναζήτηση στοιχείου με τιμή Stoxos Ο Αλγόριθμος τερματίζει αν βρεθεί στοιχείο με μεγαλύτερη τιμή από το ζητούμενο temp = Lista; /* αρχικοποίηση μεταβλητής temp */ Vrethike = 0; /* αρχικοποίηση μεταβλητής: το στοιχείο δεν έχει βρεθεί */ while ((temp!=NULL) && (!Vrethike)) /* όσο δεν τέλειωσε η λίστα και δεν έχει βρεθεί */ if (temp -> Plhroforia == Stoxos) /* αν το στοιχείο βρεθεί */ Vrethike = 1 else if (temp -> Plhroforia > Stoxos) /* αν ξεπεράσαμε την τιμή-στόχο */ temp = NULL; /* “αναγκάζουμε” την επανάληψη να τελειώσει */ if (Vrethike) /* αν η επανάληψη τελειώσει επειδή το στοιχείο βρέθηκε */ printf(“Το στοιχείο υπάρχει στη λίστα”) else /* αν η επανάληψη τελειώσει επειδή η λίστα εξαντλήθηκε */ printf(“Το στοιχείο δεν υπάρχει στη λίστα”);

21 Λίστες, Εισαγωγή στοιχείου σε λίστα Αλγόριθμος εισαγωγής στοιχείου – Στην αρχή μη ταξινομημένης λίστας – Στο τέλος μη ταξινομημένης λίστας – Σε ταξινομημένη λίστα (παραμένει ταξινομημένη και μετά την εισαγωγή) 21

22 Λίστες, Εισαγωγή στοιχείου σε λίστα Εισαγωγή στοιχείου στην αρχή μη ταξινομημένης Λίστας - Παράδειγμα 1.Δημιουργία κόμβου με τη συνάρτηση malloc 2.Ο δείκτης next του κόμβου αυτού να δείχνει εκεί που δείχνει αρχικά ο δείκτης Lista 3.Ο δείκτης Lista δείχνει στο νέο κόμβο 4.Ονομάζουμε το νέο κόμβο Neos και έστω x το στοιχείο (πληροφορία) που θέλουμε να εισάγουμε 22 Neos = (struct Komvos *) malloc(sizeof(struct Komvos)); /* δημιουργία κόμβου */ Neos -> Plhroforia = x; /* απόδοση τιμής στο νέο κόμβο */ Neos -> next = Lista;/* ο νέος κόμβος δείχνει στην προηγούμενη αρχή της λίστας */ Lista = Neos; /* η λίστα ξεκινάει πια από το νέο κόμβο */

23 Λίστες, Εισαγωγή στοιχείου σε λίστα Εισαγωγή στοιχείου στο τέλος μη ταξινομημένης Λίστας - Παράδειγμα 1.Δημιουργία κόμβου με τη συνάρτηση malloc 2.Διάσχιση της υπάρχουσας λίστας 3.Ο δείκτης next του τελευταίου κόμβου να δείχνει στο νέο κόμβο 23 Neos = (struct Komvos *) malloc(sizeof(struct Komvos)); /* δημιουργία κόμβου */ Neos -> Plhroforia = x; /* απόδοση τιμής στο νέο κόμβο */ Neos -> next = NULL; /* ο νέος κόμβος δε δείχνει πουθενά */ if (Lista == NULL) /* αν η λίστα ήταν αρχικά άδεια */ Lista = Neos; /* η λίστα θα δείχνει στο νέο κόμβο */ else {temp = Lista; /* βοηθητική μεταβλητή διάσχισης της λίστας */ while (temp -> next != NULL) /* μέχρι να τελειώσει η λίστα */ temp = temp -> next; /* προχωράμε στον επόμενο κόμβο */ temp -> next = Neos; /* ο τελευταίος κόμβος θα δείχνει στο νέο */ }

24 Λίστες, Εισαγωγή στοιχείου σε λίστα Εισαγωγή στοιχείου σε ταξινομημένη λίστα- Παράδειγμα 1.Δημιουργία κόμβου με τη συνάρτηση malloc 2.Διάσχιση της υπάρχουσας λίστας μέχρι να βρούμε τη σωστή θέση εισαγωγής του νέου κόμβου 3.Ενημέρωση δυο δεικτών: το δείκτη next του προηγούμενου κόμβου της λίστας να δείχνει στο νέο κόμβο και το δείκτη next του νέου κόμβου να δείχνει στον επόμενο 24

25 Λίστες, Εισαγωγή στοιχείου σε λίστα Εισαγωγή στοιχείου σε ταξινομημένη λίστα- Παράδειγμα 25 Neos = (struct Komvos *) malloc(sizeof(struct Komvos)); /* δημιουργία κόμβου */ Neos -> Plhroforia = x; /* απόδοση τιμής στο νέο κόμβο */ if (Lista == NULL) /* αν η λίστα ήταν αρχικά άδεια */ {Lista = Neos; /* η λίστα θα δείχνει στο νέο κόμβο */ Neos -> next = NULL; /* ο νέος κόμβος δε θα δείχνει πουθενά */ else {temp = Lista; /* βοηθητική μεταβλητή διάσχισης της λίστας */ previous = NULL; /* βοηθητική μεταβλητή που δείχνει τον προηγούμενο κόμβο */ while ((temp!=NULL) && (temp -> Plhroforia < x)) /* μέχρι να τελειώσει η λίστα ή να βρεθεί η σωστή θέση */ {previous = temp; /* προχώρησε τον προηγούμενο κόμβο μια θέση */ temp = temp -> next; /* προχώρησε τον τρέχοντα κόμβο μια θέση */ } previous -> next = Neos; /* ο δείκτης next του προηγούμενου κόμβου δείχνει το νέο */ Neos -> next = temp; /* ο δείκτης next του νέου κόμβου δείχνει τον επόμενο */ }

26 Λίστες, Διαγραφή στοιχείου από λίστα Διαγραφή = Απελευθέρωση μνήμης Γίνεται με χρήση της συνάρτησης free (ουσιαστικά αντίθετη της malloc) Αλγόριθμος Διαγραφής 1.διασχίζει πρώτα τη λίστα μέχρι να βρει τον κόμβο προς διαγραφή 2.ενημερώνει το δείκτη next του προηγούμενου κόμβου ώστε να δείχνει προς τον επόμενο 3.απελευθερώνει το χώρο μνήμης του διαγραφέντος κόμβου 26 free(ΜεταβλητήΔείκτη);

27 Λίστες, Διαγραφή στοιχείου από λίστα Αλγόριθμος Διαγραφής - Παράδειγμα 27 if (Lista == NULL) /* αν η λίστα είναι άδεια */ printf(“Δεν μπορεί να γίνει διαγραφή”); else if (Lista -> Plhroforia == x) /* αν το ζητούμενο στοιχείο είναι το πρώτο */ {temp = Lista; /* ο τρέχων κόμβος είναι ο πρώτος */ Lista = Lista -> next; /* η λίστα ξεκινάει από τον επόμενο κόμβο */ free(temp); /* απελευθερώνεται η μνήμη του τρέχοντος κόμβου */ } else {temp = Lista; /* βοηθητική μεταβλητή διάσχισης της λίστας */ previous = NULL; /* βοηθητική μεταβλητή που δείχνει τον προηγούμενο κόμβο */ while ((temp!=NULL) && (temp -> Plhroforia != x)) /* μέχρι να τελειώσει η λίστα ή να βρεθεί ο κόμβος */ {previous = temp; /* προχώρησε τον προηγούμενο κόμβο μια θέση */ temp = temp -> next; /* προχώρησε τον τρέχοντα κόμβο μια θέση */ } if (temp!=NULL) /* αν το στοιχείο βρέθηκε */ {previous->next = temp->next; /* ο δείκτης του προηγούμενου δείχνει το επόμενο */ free(temp); /* απελευθερώνεται η μνήμη του τρέχοντος κόμβου */ } else /* αν το στοιχείο προς διαγραφή δεν υπάρχει */ printf(“Το στοιχείο δεν υπάρχει στη λίστα”); }

28 Λίστες, Άλλες Μορφές Λίστας Απλά συνδεδεμένες Λίστες: κάθε κόμβος συνδέεται μόνο με τον επόμενο του (όσες είδαμε έως τώρα) Διπλά συνδεδεμένες Λίστες: κάθε κόμβος αποτελείται από τρία στοιχεία: την πληροφορία, ένα δείκτη στον επόμενο κόμβο και ένα δείκτη στον προηγούμενο κόμβο Κυκλικές Λίστες: ίδιες με απλά συνδεδεμένες ΑΛΛΑ ο δείκτης επόμενου του τελευταίου κόμβου δείχνει πίσω στον πρώτο κόμβο της λίστας 28

29 Στοίβες Στοίβα (stack): ειδική μορφή λίστας, τα στοιχεία εισάγονται και εξάγονται μόνο από το ένα άκρο της (κορυφή της στοίβας) Το τελευταίο στοιχείο που μπαίνει στη στοίβα βγαίνει πρώτο Δομή LIFO, Last In First Out Παραδείγματα στο φυσικό κόσμο: – Μια στοίβα πιάτα – Είσοδος αυτοκινήτων σε γκαράζ πλοίων 29

30 Στοίβες, Ορισμός Στοίβας 30 Σχηματική Αναπαράσταση Στοίβας

31 Στοίβες, Ορισμός Στοίβας 31 /* ορισμός δομής για τους κόμβους της στοίβας */ struct KomvosStoivas { int Plhroforia; struct KomvosStoivas *next; }; /* ορισμός μεταβλητής που θα δείχνει πάντα την κορυφή της στοίβας */ struct KomvosStoivas *Stoiva; /* απόδοση αρχικής τιμής στην (αρχικά άδεια) στοίβα */ Stoiva = NULL; Ορισμός Στοίβας σε C

32 Στοίβες, Εισαγωγή στοιχείου σε Στοίβα Εισαγωγή στοιχείου σε στοίβα 1.Χρήση malloc για δημιουργία ο νέου κόμβου με την προς εισαγωγή πληροφορία 2.Απόδοση στο δείκτη next του κόμβου αυτού της τιμής του δείκτη της στοίβας 3.Αλλάγή της τιμή του δείκτη της στοίβας ώστε να δείχνει στο νέο κόμβο 32 /* δημιουργία κόμβου */ Neos = (struct KomvosStoivas *) malloc(sizeof(struct KomvosStoivas)); Neos -> Plhroforia = x; /* απόδοση τιμής στο νέο κόμβο */ Neos -> next = Stoiva; /* ο δείκτης next του νέου κόμβου δείχνει στην παλιά κορυφή */ Stoiva = Neos; /* η στοίβα τώρα ξεκινάει από το νέο κόμβο */

33 Στοίβες, Εξαγωγή στοιχείου από Στοίβα Εξαγωγή στοιχείου από Λίστα 1.Ανάκληση η πληροφορίας του αρχικού κόμβου 2.Αλλαγή της τιμής του δείκτη της στοίβας ώστε να δείχνει εκεί που έδειχνε η παλιά κορυφή της 3.Απελευθέρωση της μνήμης που καταλάμβανε η παλιά κορυφή Οριακή περίπτωση: άδεια στοίβα 33 if (Stoiva == NULL) printf(“Στοίβα άδεια. Δεν μπορεί να γίνει διαγραφή”); else {temp = Stoiva; /* προσωρινός κόμβος που θα απελευθερωθεί */ x = Stoiva -> Plhroforia; /* ανάκληση τιμής που θα εξαχθεί */ Stoiva = Stoiva -> next; /* αλλαγή τιμής στην κορυφή της στοίβας */ free(temp); /* απελευθέρωση μνήμης του προσωρινού κόμβου */ }

34 Στοίβες, Υλοποίηση Στοίβας με Πίνακα Η Στοίβα μπορεί να υλοποιηθεί ΚΑΙ με στατικό τρόπο, δηλαδή με Πίνακα Τότε η στοίβα αποτελείται από δυο μεταβλητές – ένα πίνακα Ν θέσεων στον οποίο αποθηκεύονται τα στοιχεία της στοίβας – μια ακέραια μεταβλητή η οποία αναπαριστά την κορυφή της στοίβας (δείχνει πόσα στοιχεία έχει η στοίβα) Υλοποίηση Στοίβας με Πίνακα μπορεί να γίνει με πολλούς τρόπους – Ένας από αυτούς: η κορυφή να δείχνει πάντα στην πρώτη ελεύθερη θέση (δηλαδή μετά το τελευταίο στοιχείο) Πλεονέκτημα Στατικής Στοίβας Ευκολότερη υλοποίηση περισσότερων πράξεων Μειονέκτημα Στατικής Στοίβας Μειονέκτημα στατικών δομών, σταθερό μέγεθος 34

35 Στοίβες, Υλοποίηση Στοίβας με Πίνακα Σχηματική Απεικόνιση Στατικής Λίστας 35

36 Στοίβες, Υλοποίηση Στοίβας με Πίνακα 36 /* ορισμός δομής που ομαδοποιεί τον πίνακα και το δείκτη κορυφής της στοίβας */ struct StatikiStoiva { int Plhroforia[N]; int top; }; /* ορισμός μεταβλητής για τη στοίβα */ struct StatikiStoiva Stoiva; /* απόδοση αρχικής τιμής στην (αρχικά άδεια) στοίβα */ Stoiva.top = 0; Ορισμός Στατικής Στοίβας σε C ΠΡΟΣΟΧΗ Η ομαδοποίηση του πίνακα Plhroforia και του δείκτη top σε μια δομή είναι προαιρετική Χρήσιμη όταν σε ένα πρόγραμμα υπάρχουν περισσότερες από μια στοίβες, Διευκολύνει τον ορισμό και τη διαχείριση τους μέσω δομών. Δείκτης top με τιμή 0 δηλώνει ότι η στοίβα αρχικά είναι κενή από στοιχεία

37 Στοίβες, Υλοποίηση Στοίβας με Πίνακα 37 if (Stoiva.top == N) /* αν η στοίβα έχει ήδη Ν στοιχεία */ printf(“Η στοίβα είναι γεμάτη. Δεν μπορεί να γίνει εισαγωγή”); else {Stoiva.Plhroforia[top]=x; /* προσέξτε ότι ο δείκτης top παίρνει τιμές από 0 ως Ν-1 */ Stoiva.top++; /* αύξηση δείκτη κορυφής */ } Εισαγωγή Στοιχείου Αυξάνοντας το δείκτη top κατά ένα Εισάγοντας το νέο στοιχείο x στη θέση αυτή του πίνακα ΠΡΟΣΟΧΗ: Έλεγχος αν η Στοίβα είναι ήδη γεμάτη (δε χρειάζεται στην περίπτωση δυναμικής υλοποίησης)

38 Στοίβες, Υλοποίηση Στοίβας με Πίνακα 38 Εξαγωγή Στοιχείου Ανάκληση της πληροφορία που βρίσκεται στην κορυφή της στοίβας Μειώνοντας του δείκτη top κατά ένα ΠΡΟΣΟΧΗ: το στοιχείο στην πραγματικότητα δε διαγράφεται από τον πίνακα, απλά μαρκάρεται η θέση του ως ελεύθερη αλλάζοντας την τιμή του δείκτη top Έλεγχος αν η Στοίβα είναι άδεια if (Stoiva.top == 0) /* αν η στοίβα δεν έχει στοιχεία */ printf(“Η στοίβα είναι άδεια. Δεν μπορεί να γίνει εξαγωγή”); else {Stoiva.top--; /* μείωση δείκτη κορυφής */ x=Stoiva.Plhroforia[top]; /* προσέξτε ότι ο δείκτης top παίρνει τιμές από 0 ως Ν-1 */ }

39 Ουρές Ουρά (queue): ειδική μορφή λίστας, τα στοιχεία εισάγονται από το ένα άκρο και εξάγονται από το άλλο. Κάθε νέο στοιχείο εισάγεται στο τέλος ενώ κάθε στοιχείο εξέρχεται από την αρχή της ουράς Δομή FIFO, Fast In First Out Παράδειγμα στο φυσικό κόσμο : – Ουρά πελατών με μια τράπεζα Συνήθως έχει τη μορφή μιας απλά συνδεδεμένης λίστας με ένα επιπλέον δείκτη που δείχνει κάθε φορά στο τελευταίο στοιχείο της 39

40 Ουρές, Ορισμός Ουράς 40 Σχηματική Αναπαράσταση Ουράς

41 Ουρές, Ορισμός Ουράς 41 /* ορισμός δομής για τους κόμβους της ουράς */ struct KomvosOuras { int Plhroforia; struct KomvosOuras *next; }; /* ορισμός μεταβλητών που θα δείχνουν στην αρχή και το τέλος της ουράς */ struct KomvosOuras *Arxh, *Telos; /* απόδοση αρχικών τιμών στην (αρχικά άδεια) ουρά */ Arxh = NULL; Telos = NULL; Ορισμός Ουράς σε C

42 Ουρές, Εισαγωγή στοιχείου σε Ουρά Εισαγωγή στοιχείου σε Ουρά – Η εισαγωγή γίνεται πάντα μετά το δείκτη Telos 1.Χρήση malloc για δημιουργία ο νέου κόμβου με την προς εισαγωγή πληροφορία (ο οποίος δε θα δείχνει πουθενά) 2.Αλλαγή του δείκτη next του τελευταίου κόμβου ώστε να δείχνει στο νέο 3.Αλλαγή της τιμή του δείκτη Telos ώστε να δείχνει στο νέο κόμβο 42 /* δημιουργία κόμβου */ Neos = (struct KomvosOuras *) malloc(sizeof(struct KomvosOuras)); Neos -> Plhroforia = x; /* απόδοση τιμής στο νέο κόμβο */ Neos -> next = NULL; /* ο νέος κόμβος δε δείχνει πουθενά */ if (Telos != NULL) /* αν η ουρά δεν είναι άδεια */ Telos -> next = Neos; /* ο προηγούμενος τελευταίος κόμβος δείχνει το νέο κόμβο */ Telos = Neos; /* ο δείκτης τέλους δείχνει το νέο κόμβο */ if (Arxh == NULL) /* αν η ουρά ήταν άδεια) */ Arxh = Neos; /* ο δείκτης αρχής δείχνει το νέο κόμβο */

43 Ουρές, Εξαγωγή στοιχείου από Ουρές Εξαγωγή στοιχείου από Ουρά (γίνεται από την κορυφή της ουράς) 1.Ανάκληση η πληροφορίας του αρχικού κόμβου 2.Αλλαγή της τιμής του δείκτη αρχής ώστε να δείχνει εκεί που έδειχνε ο παλιός δείκτης αρχής 3.Απελευθέρωση της μνήμης που καταλάμβανε ο παλιός αρχικός κόμβος Οριακή περίπτωση: Η ουρά είναι άδεια ή αδειάζει μετά τη διαγραφή. Πρέπει να ενημερωθεί ο δείκτης Τέλους 43 if Arxh == NULL printf(“Ουρά άδεια. Δεν μπορεί να γίνει διαγραφή”); else {temp = Arxh; /* προσωρινός κόμβος που θα απελευθερωθεί */ x = Arxh -> Plhroforia; /* ανάκληση τιμής που θα εξαχθεί */ Arxh = Arxh -> next; /* αλλαγή τιμής στην κορυφή της ουράς */ if (Arxh == NULL) /* αν η ουρά άδειασε μετά τη διαγραφή */ Telos = NULL; /* ενημέρωση του δείκτη τέλους */ free(temp); /* απελευθέρωση μνήμης του προσωρινού κόμβου */ }

44 Ουρές, Υλοποίηση Ουράς με Πίνακα Η Ουρά μπορεί να υλοποιηθεί ΚΑΙ με στατικό τρόπο, δηλαδή με Πίνακα Τότε η ουρά αποτελείται από τρεις μεταβλητές – ένα πίνακα Ν θέσεων στον οποίο αποθηκεύονται τα στοιχεία της ουράς – δυο ακέραιες μεταβλητές οι οποίες αναπαριστούν την αρχή και το τέλος της ουράς Υλοποίηση Ουράς με Πίνακα μπορεί να γίνει με πολλούς τρόπους – Ένας από αυτούς: Ο δείκτης αρχής να δείχνει πάντα στο πρώτο στοιχείο και ο δείκτης τέλους στην πρώτη ελεύθερη θέση (δηλαδή μετά το τελευταίο στοιχείο) Πλεονέκτημα Στατικής Στοίβας Ευκολότερη υλοποίηση περισσότερων πράξεων Μειονέκτημα Στατικής Στοίβας Μειονέκτημα στατικών δομών, σταθερό μέγεθος 44

45 Ουρές, Υλοποίηση Ουράς με Πίνακα Σχηματική Απεικόνιση Στατικής Ουράς 45

46 Ουρές, Υλοποίηση Ουράς με Πίνακα 46 /* ορισμός δομής για τα στοιχεία της στατικής ουράς */ struct StatikiOura { int Plhroforia[N]; int Arxh; int Telos; }; /* ορισμός μεταβλητής για την ουρά */ struct StatikiOura Oura; /* απόδοση αρχικών τιμών στα στοιχεία της (αρχικά άδειας) ουράς */ Oura.Arxh = 0; Oura.Telos = 0; Ορισμός Στατικής Ουράς σε C

47 Ουρές, Υλοποίηση Ουράς με Πίνακα 47 if (Oura.Telos < N) /* αν το στοιχείο χωράει στο τέλος του πίνακα */ {Oura.Plhroforia[Telos]=x; /* το νέο στοιχείο εισάγεται στο τέλος */ Oura.Telos++; /* αύξηση δείκτη τέλους */ } else /* αν ο δείκτης τέλους έχει φτάσει στο τέλος του πίνακα */ if (Oura.Arxh == 0) /* αν ο δείκτης αρχής βρίσκεται στην αρχή */ printf(“Η ουρά είναι γεμάτη. Δεν μπορεί να γίνει εισαγωγή”); else /* πρέπει να γίνει μετακίνηση στοιχείων */ {StoixeiaOuras = Telos - Arxh; /* πόσα στοιχεία πρέπει να μετακινηθούν */ for (i=Arxh;i>0;i--) /* μετακίνηση */ for (k=1;k > */ Oura.Plhroforia[i+k-2]=Oura.Plhroforia[i+k-1]; /* >> */ Arxh = 0; /* ενημέρωση νέου δείκτη αρχής */ Εισαγωγή Στοιχείου Εισάγοντας το νέο στοιχείο x στη θέση του πίνακα που δείχνει ο δείκτης τέλους Αυξάνοντας το δείκτη Telos κατά ένα ΠΡΟΣΟΧΗ: Έλεγχος αν η Όυρά είναι ήδη γεμάτη Όταν ο δείκτης τέλους φτάσει στο τέλος του πίνακα, να ελέγχεται αν υπάρχουν άδειες θέσεις και να μετακινούνται όλα τα στοιχεία μπροστά (αλλιώς θα υπάρχουν άδειες θέσεις και δεν θα μπορούν να γίνουν εισαγωγές)

48 Ουρές, Υλοποίηση Ουράς με Πίνακα 48 Εξαγωγή Στοιχείου Ανάκληση της πληροφορία που βρίσκεται στην αρχή της ουράς Αυξάνοντας το δείκτη Arxh κατά ένα ΠΡΟΣΟΧΗ: Έλεγχος αν η Στοίβα είναι άδεια ή αν αδειάσει μετά την εξαγωγή if (Oura.Telos == 0) /* αν η ουρά δεν έχει στοιχεία */ printf(“Η ουρά είναι άδεια. Δεν μπορεί να γίνει εξαγωγή”); else {x=Oura.Plhroforia[Arxh]; /* εξαγωγή του πρώτου στοιχείου */ Oura.Arxh++; /* αύξηση δείκτη αρχής */ if (Oura.Arxh == Oura.Telos) /* αν μετά την εξαγωγή η ουρά άδειασε */ {Oura.Arxh = 0; /* ενημέρωση δεικτών */ Oura.Telos = 0; /* >> >> */ }


Κατέβασμα ppt "ΕΙΣΑΓΩΓΗ ΣΤΗΝ ΠΛΗΡΟΦΟΡΙΚΗ Κεφάλαιο 9 Δομές Δεδομένων σε C Γιώργος Γιαγλής."

Παρόμοιες παρουσιάσεις


Διαφημίσεις Google