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

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

Δυναμικές Δομές Γλώσσα C & Unix Τμήμα Πληροφορικής, ΑΠΘ B’ εξάμηνο lpis.csd.auth.gr/curriculum/C+Unix/UNCL202.html.

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


Παρουσίαση με θέμα: "Δυναμικές Δομές Γλώσσα C & Unix Τμήμα Πληροφορικής, ΑΠΘ B’ εξάμηνο lpis.csd.auth.gr/curriculum/C+Unix/UNCL202.html."— Μεταγράφημα παρουσίασης:

1 Δυναμικές Δομές Γλώσσα C & Unix Τμήμα Πληροφορικής, ΑΠΘ B’ εξάμηνο lpis.csd.auth.gr/curriculum/C+Unix/UNCL202.html

2 2 Μέτρηση Συχνότητας Εμφάνισης Λέξεων σε Κείμενο  Θέλουμε να μετρήσουμε τη συχνότητα εμφά- νισης όλων των λέξεων μέσα σε ένα κείμενο  Η λίστα των λέξεων δεν είναι γνωστή εκ των προτέρων  Δεν μπορούμε να την ταξινομήσουμε από πριν και να χρησιμοποιήσουμε δυαδική αναζήτηση  Δεν μπορούμε να κάνουμε σειριακή αναζήτηση για κάθε καινούρια λέξη, γιατί το πρόγραμμα θα καθυστερεί δραματικά  Πώς μπορούν να οργανωθούν τα δεδομένα για γρήγορη αναζήτηση τυχαίων συνόλων λέξεων;

3 3 Λύση Προβλήματος  Οι λέξεις που έχουν συναντηθεί στο κείμενο να βρίσκονται συνεχώς ταξινομημένες  Κάθε νέα λέξη πρέπει να τοποθετείται στη σωστή «λεξικογραφική» σειρά  Δεν πρέπει να γίνεται μετακίνηση λέξεων μέσα σε ένα γραμμικό πίνακα  Είναι πολύ αργή  Θα χρησιμοποιηθούν δυναμικές δομές δεδομένων  Συνδεδεμένες Λίστες  Δυαδικά Δένδρα

4 4 Συνδεδεμένες Λίστες  Μια από τις πιο βασικές δομές δεδομένων  Αποτελούνται από πολλά στοιχεία τα οποία οργανώνονται ή συνδέονται μεταξύ τους με μια συγκεκριμένη σειρά  Χρησιμοποιούνται για ομαδοποίηση δεδομένων, όπως οι πίνακες

5 5 Συνδεδεμένες Λίστες - Πλεονεκτήματα  Πιο αποδοτικές κατά την εισαγωγή και διαγραφή στοιχείων  Δυναμική χρήση της μνήμης  Σε πολλές εφαρμογές το μέγεθος της συλλογής των δεδομένων δεν είναι γνωστό εκ των προτέρων  Απλά συνδεδεμένες λίστες:  Τα στοιχεία συνδέονται με 1 δείκτη  Η λίστα διατρέχεται από το πρώτο προς το τελευταίο στοιχείο

6 6 Απλά Συνδεδεμένη Λίστα NULL Δεδομένα Δείκτης επόμενου στοιχείου Στοιχείο λίστας Δείκτης στο πρώτο στοιχείο της λίστας  Κάθε στοιχείο της λίστας είναι μία δομή (struct)  Τα δεδομένα μπορεί να είναι 1 ή και περισσότερα στοιχεία (μέλη) της δομής

7 7 Αναπαράσταση της Λίστας με Δομή struct node { int data;... struct node *next; };  Αυτό-αναφορική ή αναδρομική δομή  Δομή που περιέχει τον εαυτό της  Στην πραγματικότητα η δομή node δεν περιέχει όμοια δομή, αλλά έναν δείκτη σε όμοια δομή

8 8 Χρήση Λίστας για τη Μέτρηση Συχνότητας Εμφάνισης Λέξεων σε Κείμενο  Σε κάθε στοιχείο της λίστας αποθη- κεύεται μία λέξη και ένας μετρητής struct node { char *word; int count; struct node *next; };

9 9 Χρήση Λίστας για τη Μέτρηση Συχνότητας Εμφάνισης Λέξεων σε Κείμενο  Η λέξεις τοποθετούνται στη λίστα ταξινομημένες  Όταν το πρόγραμμα συναντάει μία νέα λέξη την τοποθετεί στο «σωστό» σημείο  Όταν το πρόγραμμα συναντάει μία υπάρχουσα λέξη αυξάνει τον μετρητή κατά ένα

10 10 Τοποθέτηση Νέας Λέξης  Είναι πολύ εύκολη η εισαγωγή νέου στοιχείου σε οποιοδήποτε σημείο της λίστας, χωρίς μετακίνηση δεδομένων στη μνήμη  Βλ. πίνακες NULL Αρχική λίστα Τελική λίστα Στοιχείο για εισαγωγή Σημείο εισαγωγής

11 11 Κανόνες Τοποθέτησης Νέας Λέξης  Συγκρίνεται λεξικογραφικά η νέα λέξη με τις υπάρχουσες σε κάθε στοιχείο- κόμβο της λίστας  Εάν η νέα λέξη είναι «μεγαλύτερη» από την λέξη του τρέχοντος στοιχείου, τότε πρέπει να τοποθετηθεί πιο δεξιά  Ακολουθείται ο δείκτης στο επόμενο στοιχείο  Εάν η νέα λέξη είναι ίδια, τότε αυξάνεται ο μετρητής

12 12 Κανόνες Τοποθέτησης Νέας Λέξης  Εάν η νέα λέξη είναι «μικρότερη», τότε πρέπει να τοποθετηθεί αμέσως πριν από το τρέχον στοιχείο  Αν το τρέχον στοιχείο είναι το τέλος της λίστας (NULL), τότε η νέα λέξη τοποθετείται στο τέλος της λίστας

13 13 Δημιουργία Νέας Λέξης  Δημιουργείται μία νέα δομή που περιλαμβάνει τη λέξη και μετρητή 1  Γίνεται η κατάλληλη σύνδεση με το προηγούμενο και επόμενο στοιχείο της λίστας  Μέσω δεικτών

14 14 Κύριο Πρόγραμμα ( main ) void main () { struct node *list = NULL; char word[MAXWORD]; while (getword(word, MAXWORD) != EOF) if (isalpha(word[0])) list = insert(list,word); printlist(list); } Κάθε λέξη τοποθετείται στη σωστή σειρά Τυπώνεται η λίστα (ταξινομημένη)

15 15 Εκτύπωση Στοιχείων Λίστας void printlist (struct node *list) { if (list != NULL) { printf("%4d %s\n", list->count, list->word); printlist(list->next); } •Εκτύπωση των επόμενων στοιχείων •Αναδρομική κλήση •Τερματισμός αναδρομής •Εκτύπωση των δεδομένων του τρέχοντος στοιχείου

16 16 Εισαγωγή Λέξης στη Λίστα struct node *insert(struct node *p, char *w) {struct node *n;int cond; if (p == NULL) { p = alloc(); p->word=strdup(w); p->count = 1; p->next = NULL; } •Αν ο δείκτης δείχνει σε NULL δείκτη •Φτάσαμε στο τέλος της λίστας και η λέξη δεν βρέθηκε •Πρέπει να προστεθεί νέο στοιχείο στο τέλος της λίστας •Δέσμευση μνήμης •Αποθήκευση λέξης •Αποθήκευση μετρητή 1 •Αφού το νέο στοιχείο είναι το τελευταίο της λίστας, το επόμενο είναι NULL

17 17 Τοποθέτηση Νέας Λέξης σε Άδεια Λίστα NULL Αρχική λίστα Τελική λίστα Στοιχείο για εισαγωγή Σημείο εισαγωγής Αλλάζει ο δείκτης προς τη λίστα!

18 18 Εισαγωγή Λέξης στη Λίστα else if ((cond=strcmp(w, p->word)) == 0) p->count++; else if (cond < 0) { n = alloc(); n->word = strdup(w); n->count = 1; n->next = p; p = n; } •Σύγκρινε την λέξη προς εισαγωγή με την αποθηκευμένη λέξη •Αν είναι ίδιες, τότε αύξησε τον μετρητή κατά 1 •Αν είναι μικρότερη, τότε πρόσθεσέ την στη λίστα πριν από το τρέχον στοιχείο •Δημιουργία στοιχείου και αποθήκευση δεδομένων •Το νέο στοιχείο δείχνει το τρέχον στοιχείο ως επόμενό του, αφού προηγείται •Το νέο στοιχείο είναι πλέον το τρέχον στοιχείο της λίστας

19 19 Τοποθέτηση Νέας Λέξης στην Πρώτη Θέση της Λίστας Αλλάζει ο δείκτης προς τη λίστα! NULL Αρχική λίστα Τελική λίστα Στοιχείο για εισαγωγή Σημείο εισαγωγής

20 20 Εισαγωγή Λέξης στη Λίστα else p->next = insert(p->next, w); return p; } •Αν είναι μεγαλύτερη, τότε πρόσθεσέ την πιο δεξιά στη λίστα, μετά από το τρέχον στοιχείο •Κάλεσε αναδρομικά την insert •Θέσε ως τρέχον στοιχείο, το επόμενο •Επειδή η λέξη μπορεί να προστεθεί αμέσως μετά την τρέχουσα, ο δείκτης στην επόμενη θέση της λίστας μπορεί να αλλάξει (μπορεί και όχι) •Το τρέχον στοιχείο δείχνει στο στοιχείο της λίστας που επιστρέφει η insert •Επέστρεψε δείκτη στο νέο (ή παλιό) τρέχον στοιχείο

21 21 Τοποθέτηση Νέας Λέξης σε Ενδιάμεση Θέση της Λίστας NULL Αρχική λίστα Τελική λίστα Στοιχείο για εισαγωγή Σημείο εισαγωγής ΔΕΝ αλλάζει ο δείκτης προς τη λίστα!

22 22 Αναδρομικός Ορισμός  Επειδή ο ορισμός της insert είναι αναδρομικός, πρέπει να προηγείται η υπογραφή της συνάρτησης πριν τον ορισμό της struct node *insert(struct node *, char *);

23 23 Δέσμευση Μνήμης για Δημιουργία Κόμβου της Λίστας #include struct node *alloc(void) { return (struct node *) malloc(sizeof(struct node)); } Μέγεθος μνήμης ενός κόμβου Συνάρτηση βιβλιοθήκης για ανάθεση μνήμης casting

24 24 Αντιγραφή Λέξης char *strdup(char *s) {char *p; p = (char *) malloc(strlen(s)+1); if (p != NULL) strcpy(p, s); return p; } Αντιγραφή string σε ασφαλές μέρος στη μνήμη Δέσμευση μνήμης για το string Υπάρχει στη βιβλιο- θήκη string.h

25 25 Δηλώσεις include & define #include #define MAXWORD 100

26 26 Εναλλακτικοί Ορισμοί Συναρτήσεων – Μη Αναδρομικοί void printlist (struct node *list) { while (list != NULL) { printf("%4d %s\n", list->count, list->word); list = list->next; } •Βρόχος για όλα τα στοιχεία της λίστας •Εκτύπωση των δεδομένων του τρέχοντος στοιχείου •Μετακίνηση στο επόμενο στοιχείο της λίστας

27 27 Εναλλακτικοί Ορισμοί Συναρτήσεων – Μη Αναδρομικοί struct node * insert (struct node *p, char *w) {struct node *n,*r,*prev; int cond; r = p; if (p == NULL) { n = alloc(); n->word = strdup(w); n->count = 1;n->next = NULL; r = n; } else if (strcmp(w,p->word) < 0) { n = alloc();n->word = strdup(w); n->count = 1;n->next = p; r = n; } •Ο επιστρεφόμενος δείκτης r •Συνήθως είναι ο αρχικός •Εκτός αν το νέο στοιχείο προστεθεί στην αρχή ή αν η λίστα είναι άδεια Άδεια λίστα Προσθήκη στοιχείου στην αρχή της λίστας

28 28 Εναλλακτικοί Ορισμοί Συναρτήσεων – Μη Αναδρομικοί else { while (p != NULL) { if ((cond = strcmp(w,p->word)) == 0) { p->count++; break; } else if (cond < 0) { n = alloc();n->word=strdup(w); n->count = 1;n->next = p; prev->next = n; break; } else if (cond > 0) { prev = p; p = p->next; } •Το νέο στοιχείο προστίθεται στη μέση της λίστας •Η λέξη συμπίπτει με την τρέχουσα Η λέξη είναι μικρότερη από την τρέχουσα •Το προηγούμενο στοιχείο πρέπει να δείχνει στο νέο στοιχείο Η λέξη είναι μεγαλύτερη από την τρέχουσα •Προηγούμενο στοιχείο γίνεται το τρέχον •Τρέχον στοιχείο γίνεται το επόμενο

29 29 Εναλλακτικοί Ορισμοί Συναρτήσεων – Μη Αναδρομικοί if (p == NULL) { n = alloc(); n->word=strdup(w); n->count = 1; n->next = NULL; prev->next = n; } return r; } •Το νέο στοιχείο προστίθεται στο τέλος της λίστας •Το προηγούμενο στοιχείο πρέπει να δείχνει στο νέο στοιχείο •Επιστροφή του πρώτου στοιχείου της λίστας •Παλιού ή νέου

30 30 Συμπέρασμα  Όταν έχουμε αυτό-αναφορικές ή αναδρομικές δομές δεδομένων οι αναδρομικές συναρτήσεις χειρισμού τους είναι πιο σύντομες και πιο ευκολονόητες από τις επαναληπτικές διαδικασίες

31 31 Εκτέλεση του Προγράμματος The function addtree is recursive. A word is... parent node. 1 A 1 At 1 Eventually 1 If 1 The 5 a the... 4 word Εισαγωγή κειμένου από τον χρήστη Εκτύπωση αποτελεσμάτων από το πρόγραμμα

32 32 Απόδοση  Καλύτερη περίπτωση αν οι λέξεις φθάνουν με φθίνουσα σειρά  Κάθε φορά εξετάζεται μόνο η πρώτη θέση της λίστας  Χειρότερη: αν είναι ταξινομημένες ήδη σε αύξουσα σειρά  Κάθε φορά εξετάζονται όλες οι θέσεις της λίστας  Όταν είναι τυχαία κατανεμημένες, η πολυπλοκότητα είναι ανάλογη του Ν 2  Ν = ο αριθμός λέξεων

33 33 Δυαδικά Δένδρα  Ένα δένδρο αποτελείται από στοιχεία που ονομάζονται κόμβοι (node)  Οι κόμβοι είναι οργανωμένοι ιεραρχικά  Ο κόμβος στην κορυφή της ιεραρχίας ονομάζεται ρίζα (root)

34 34 Δυαδικά Δένδρα  Οι κόμβοι που βρίσκονται κάτω από έναν άλλο κόμβο είναι τα παιδιά του (children)  Συνήθως τα παιδιά έχουν δικά τους παιδιά, κ.ο.κ.  Κάθε κόμβος έχει ακριβώς έναν γονέα, εκτός από την ρίζα

35 35 Δυαδικά Δένδρα  Ο αριθμός των παιδιών που μπο- ρεί να έχει ένας κόμβος εξαρτάται από το είδος του δένδρου  Παράγοντας διακλάδωσης (branching factor)  Θα δούμε τα δυαδικά δένδρα (binary tree)  Παράγοντας διακλάδωσης = 2

36 36 Δυαδικά Δένδρα Δεδομένα Δείκτης αριστερού υποδένδρου Δείκτης στη ρίζα του δένδρου Ρίζα Παιδιά NULL Δείκτης δεξιού υποδένδρου Τερματισμός δένδρου Τερματικός κόμβος

37 37 Δομή (struct) Δυαδικού Δένδρου  Κάθε κόμβος του δυαδικού δένδρου είναι μία δομή με:  Ένα ή περισσότερα μέλη για τα δεδομένα του κόμβου  1 δείκτη για το αριστερό παιδί (υποδένδρο)  1 δείκτη για το δεξί παιδί (υποδένδρο) struct tnode { int data;... struct tnode *left; struct tnode *right; };

38 38 Χρήση Δένδρου για τη Μέτρηση Συχνότητας Εμφάνισης Λέξεων σε Κείμενο  Σε κάθε κόμβο του δένδρου αποθη- κεύεται μία λέξη και ένας μετρητής struct tnode { char *word; int count; struct tnode *left; struct tnode *right; };

39 39 Χρήση Δένδρου για τη Μέτρηση Συχνότητας Εμφάνισης Λέξεων σε Κείμενο  Η λέξεις τοποθετούνται στο δένδρο έτσι ώστε σε κάθε κόμβο:  Όλες οι λέξεις που βρίσκονται στο αριστερό υποδένδρο να είναι λεξικογραφικά μικρότερες από τη λέξη του κόμβου  Όλες οι λέξεις που βρίσκονται στο δεξί υποδένδρο να είναι λεξικογραφικά μεγαλύτερες από τη λέξη του κόμβου

40 40 Χρήση Δένδρου για τη Μέτρηση Συχνότητας Εμφάνισης Λέξεων σε Κείμενο  Όταν το πρόγραμμα συναντάει μία νέα λέξη την τοποθετεί στο «σωστό» σημείο  Ξεκινάει από τη ρίζα:  Αν η νέα λέξη είναι μικρότερη από την αποθηκευμένη την ψάχνει στο αριστερό υποδένδρο  Αν η νέα λέξη είναι μεγαλύτερη, την ψάχνει στο δεξί υποδένδρο  Αν η νέα λέξη είναι ίδια, αυξάνει τον μετρητή κατά 1

41 41 Χρήση Δένδρου για τη Μέτρηση Συχνότητας Εμφάνισης Λέξεων σε Κείμενο  Αν το δένδρο τερματιστεί (NULL), η λέξη δεν υπάρχει  Δημιουργείται ένας νέος (τερματικός) κόμβος στον οποίο αποθηκεύεται η νέα λέξη (με μετρητή 1)

42 42 Παράδειγμα Δυαδικού Δένδρου  Τοποθέτηση στο δένδρο των λέξεων της φράσης «now is the time for all good men to come to the aid of their party»

43 43 Κύριο Πρόγραμμα ( main ) void main () {struct tnode *root = NULL; char word[MAXWORD]; while (getword(word,MAXWORD)!=EOF) if (isalpha(word[0])) root = addtree(root, word); treeprint(root); } Κάθε λέξη τοποθετείται στη σωστή θέση Τυπώνεται το δένδρο (ταξινομημένο)

44 44 Εκτύπωση Κόμβων Δένδρου void treeprint(struct tnode *p) { if (p != NULL) { treeprint(p->left); printf("%4d %s\n", p->count, p->word); treeprint(p->right); } •Εκτύπωση των κόμβων του δεξιού υποδένδρου Τερματισμός αναδρομής •Εκτύπωση των δεδομένων του τρέχοντος κόμβου •Εκτύπωση των κόμ- βων του αριστερού υποδένδρου •Αναδρομική κλήση

45 45 Εισαγωγή Λέξης στο Δένδρο struct tnode *addtree(struct tnode *p, char *w) {int cond; if (p == NULL) { p = alloc(); p->word=strdup(w); p->count = 1; p->left = p->right = NULL; } •Αν ο δείκτης δείχνει σε NULL δείκτη •Φτάσαμε στο τέλος του δένδρου και η λέξη δεν βρέθηκε •Πρέπει να προστεθεί νέος τερματικός κόμβος στο δένδρο •Δέσμευση μνήμης •Αποθήκευση λέξης •Αποθήκευση μετρητή 1 •Αφού ο νέος κόμβος είναι τερματικός, τα δυο παιδιά του είναι NULL

46 46 Εισαγωγή Λέξης σε Άδειο Δένδρο NULL Αρχικό Δένδρο Τελικό Δένδρο Αλλάζει ο δείκτης προς το δένδρο!

47 47 Εισαγωγή Λέξης στο Δένδρο else if ((cond=strcmp(w, p->word)) == 0) p->count++; else if (cond < 0) p->left = addtree(p->left, w); else p->right = addtree(p->right, w); return p; } •Σύγκρινε την λέξη προς εισαγωγή με την αποθηκευμένη λέξη •Αν είναι ίδιες, τότε αύξησε τον μετρητή κατά 1 •Αν είναι μικρότερη, τότε ψάξ’ την (αναδρομικά) στο αριστερό υποδένδρο •Αν είναι μεγαλύτερη, τότε ψάξ’ την (αναδρομικά) στο δεξί υποδένδρο •Επειδή κάποιο υποδένδρο μπορεί να είναι NULL, η αναδρομή μπορεί να επιστρέψει δείκτη στο νέο κόμβο που θα προστεθεί •Γι’ αυτό γίνεται ανάθεση τιμών στους δείκτες των υποδένδρων

48 48 Εισαγωγή Λέξης στο Δένδρο NULL Αρχικό Δένδρο Νέος Κόμβος Σημείο εισαγωγής

49 49 Εισαγωγή Λέξης στο Δένδρο NULL Τελικό Δένδρο ΔΕΝ αλλάζει ο δείκτης προς το δένδρο! Αλλάζει ο δείκτης στο σημείο εισαγωγής του κόμβου!

50 50 Αναδρομικός Ορισμός  Επειδή ο ορισμός της addtree είναι αναδρομικός, πρέπει να προηγείται η υπογραφή της συνάρτησης πριν τον ορισμό της struct tnode *addtree(struct tnode *, char *);

51 51 Απόδοση  Χειρότερη περίπτωση αν οι λέξεις είναι ταξινομημένες ήδη σε αύξουσα ή φθίνουσα σειρά  Το δένδρο «γέρνει» μόνο από την δεξιά ή την αριστερή πλευρά, αντίστοιχα  Καλύτερη περίπτωση αν οι λέξεις είναι τυχαία κατανεμημένες  Το δένδρο είναι ισορροπημένο  Σε κάθε σύγκριση αποκλείονται μισά στοιχεία του δένδρου  Η πολυπλοκότητα είναι ανάλογη του Ν*log 2 Ν

52 52 Στοίβα (stack)  Δομές δεδομένων για την αποθήκευση και την ανάκτηση δεδομένων με τη μέθοδο LIFO  Last-In, First-Out  Τα δεδομένα ανακτώνται με την ανάστροφή σειρά από αυτήν που αποθηκεύτηκαν  Παράδειγμα: Στοίβα πιάτων

53 53 Λειτουργίες Στοίβας (Push) Νέο στοιχείο Αρχική Στοίβα Εισαγωγή Στοιχείου “PUSH” 5 7 Τελική Στοίβα 3 Νέα Κορυφή Στοίβας Κορυφή Στοίβας

54 54 Λειτουργίες Στοίβας (Pop) Ανακτημένο στοιχείο Τελική Στοίβα Εξαγωγή Στοιχείου “POP” 5 7 Αρχική Στοίβα 3 Κορυφή Στοίβας Νέα Κορυφή Στοίβας

55 55 Υλοποίηση Στοίβας ως Απλά Συνδεδεμένης Λίστας – Δομές/Επικεφαλίδες #include struct node { int data; struct node *next; }; Διαφέρει ανάλογα με την εφαρμογή Απλά συνδεδεμένη λίστα

56 56 Συνάρτηση push void push (struct node **stack, int d) { struct node *p; p = alloc(); p->data = d; p->next = *stack; *stack = p; } Στοιχείο προς αποθήκευση Δείκτης σε λίστα, ώστε να μπορεί η συνάρτηση να αλλάζει το πρώτο στοιχείο της λίστας, δηλαδή την κορυφή της στοίβας Δημιουργία νέου κόμβου Ο δείκτης στο πρώτο στοιχείο της λίστας (στοίβας) «δείχνει» στο νέο κόμβο Ο νέος κόμβος δείχνει στην παλιά κορυφή της στοίβας, αφού τοποθετείται μπροστά της

57 57 Συνάρτηση pop int pop(struct node **stack, int *x) {struct node *p; p = *stack; if (*stack == NULL) return -1; else { *x = (*stack)->data; *stack = (*stack)->next; free(p); return 0; } Δείκτης σε λίστα •Δείκτης σε ακέραιο •Εξαχθέν στοιχείο Επιστρέφει ακέραιο για έλεγχο ορθής λειτουργίας Αντιγράφεται ο δείκτης στην κορυφή της στοίβας Αν η στοίβα είναι άδεια, επιστρέφεται ένδειξη «λάθους» Εξάγεται το στοιχείο της κορυφής της στοίβας (μέσω του δείκτη σε ακέραιο) Η νέα κορυφή της στοίβας είναι πλέον το επόμενο στοιχείο της παλιάς κορυφής Απελευθερώνεται η μνήμη που καταλάμβανε η παλιά κορυφή της στοίβας

58 58 Κυρίως Πρόγραμμα main void main () { struct node *stack = NULL; int x; while (scanf("%d",&x) != EOF) push(&stack,x); printf("\n\nInitial Stack:\n"); printstack(stack); if (pop(&stack,&x) != -1) { printf("\n\nElement popped: %d\n",x); printf("\nStack after pop:\n"); printstack(stack); } else printf("Stack Empty!\n"); } Διαβάζονται ακέραιοι και αποθηκεύονται στη στοίβα Αρχικά η στοίβα είναι κενή Εκτύπωση στοιχείων στοίβας Εξαγωγή ενός στοιχείου από τη στοίβα Εκτύπωση του εξαχθέ- ντος στοιχείου και της υπόλοιπης στοίβας

59 59 Εκτέλεση του προγράμματος ^Z Initial Stack: Element popped: 4 Stack after pop: Είσοδος από το πληκτρολόγιο Έξοδος του προγράμματος

60 60 Ουρά (queue)  Δομές δεδομένων για την αποθήκευση και την ανάκτηση δεδομένων με τη μέθοδο FIFO  First-In, First-Out  Τα δεδομένα ανακτώνται με την ίδια σειρά από αυτήν που αποθηκεύτηκαν  Παράδειγμα: Ουρά εξυπηρέτησης σε ταμείο τράπεζας

61 61 Λειτουργίες Ουράς (Enqueue) Νέο στοιχείο Αρχική Ουρά Εισαγωγή Στοιχείου “ENQUEUE” 3 5 Τελική Ουρά 7 Κεφαλή (head) Ουράς «Ουρά» (tail) Ουράς Νέα «Ουρά» (tail) Ουράς

62 62 Λειτουργίες Ουράς (Dequeue) Ανακτημένο στοιχείο Τελική Ουρά Εξαγωγή Στοιχείου “DEQUEUE” 3 5 Αρχική Ουρά 7 Head Ουράς Νέο Head Ουράς Tail Ουράς

63 63 Υλοποίηση Ουράς ως Απλά Συνδεδεμένης Λίστας – Δομές/Επικεφαλίδες #include struct node { int data; struct node *next; }; struct queue { struct node *head; struct node *tail; }; Ίδια με το stack •Δομή ουράς •Έχει 2 δείκτες σε head και tail

64 64 Συνάρτηση enqueue void enqueue(struct queue *q, int d) {struct node *p; p = alloc(); p->data = d; p->next = NULL; if (q->tail == NULL) q->head = p; else q->tail->next = p; q->tail = p; } Στοιχείο προς αποθήκευση Δείκτης σε ουρά, ώστε να μπορεί η συνάρτηση να αλλάζει το head και το tail Δημιουργία νέου κόμβου Αν η ουρά είναι άδεια, τότε το head δείχνει στο νέο κόμβο Αν η ουρά δεν είναι άδεια, τότε το παλιό tail δείχνει στο νέο κόμβο, ο οποίος θα γίνει το νέο tail

65 65 int dequeue(struct queue *q, int *x) {struct node *p; p = q->head; if (q->head == NULL) return -1; else { *x = q->head->data; q->head = q->head->next; free(p); if (q->head == NULL) q->tail = NULL; return 0; } Συνάρτηση dequeue •Μοιάζει πολύ με το pop της στοίβας •Αντί *stack έχουμε q->head •Αν η ουρά αδειάσει, τότε ενημερώνεται και ο δείκτης στο tail

66 66 Συνάρτηση printqueue void printqueue (struct queue q) {struct node *h; h = q.head; while (h != NULL) { printf ("%4d\n", h->data); h = h->next; } •Χρησιμοποιούμε τον επαναληπτικό τρόπο διάσχισης της λίστας (αντί αναδρομής) •Η δομή queue δεν είναι αυτό-αναφορική

67 67 Κυρίως Πρόγραμμα main int main () { struct queue q = {NULL,NULL}; int x; while (scanf("%d",&x) != EOF) enqueue(&q,x); printf("\n\nInitial Queue:\n"); printqueue(q); if (dequeue(&q,&x) != -1) { printf("\n\nElement dequeued: %d\n",x); printf("\nQueue after dequeue:\n"); printqueue(q); } else printf("Queue Empty!\n"); return 0; } Η main μοιάζει πάρα πολύ με την main της στοίβας

68 68 Εκτέλεση του προγράμματος ^Z Initial Queue: Element dequeued: 1 Queue after dequeue: Είσοδος από το πληκτρολόγιο Έξοδος του προγράμματος


Κατέβασμα ppt "Δυναμικές Δομές Γλώσσα C & Unix Τμήμα Πληροφορικής, ΑΠΘ B’ εξάμηνο lpis.csd.auth.gr/curriculum/C+Unix/UNCL202.html."

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


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