6-1 ΜΑΘΗΜΑ 6 ο Ανασκόπηση σε Δείκτες, Συνδεδεμένες Λίστες, Ουρές, Στοίβες.

Slides:



Advertisements
Παρόμοιες παρουσιάσεις
Βάσεις Δεδομένων Ευαγγελία Πιτουρά 1 Ευρετήρια.
Advertisements

Γραφήματα & Επίπεδα Γραφήματα
Ε. ΠετράκηςΛίστες1  Λίστα: πεπερασμένη σειρά στοιχείων ίδιου τύπου  Οι πράξεις εξαρτώνται από τον τύπο της λίστας και όχι από τον τύπο δεδομένων  Λίστα:
Το αλφαριθμητικό (string)
Συλλογές, Στοίβες και Ουρές Σε πολλές εφαρμογές μας αρκεί η αναπαράσταση ενός δυναμικού συνόλου με μια δομή δεδομένων η οποία δεν υποστηρίζει την αναζήτηση.
Στοιχειώδεις Δομές Δεδομένων TexPoint fonts used in EMF. Read the TexPoint manual before you delete this box.: AA A A A Τύποι δεδομένων στη Java • Ακέραιοι.
POINTERS, AGGREGATION, COMPOSITION. POINTERS TO OBJECTS.
-Στοίβα-Ουρά - Πλεονεκτήματα πινάκων -Δομές δεδομένων δευτερεύουσας μνήμης -Πληροφορική και δεδομένα -Παραδείγματα-Προβλήματα ψευδοκώδικα.
Ανασκόπηση σε Δείκτες, Ουρές, Στοίβες, Συνδεδεμένες Λίστες
ΜΑΘΗΜΑ 7ο Κυκλικές και Διπλά Συνδεδεμένες Λίστες,
ΕΠΛ 231 – Δομές Δεδομένων και Αλγόριθμοι
Γλώσσα C & Unix Τμήμα Πληροφορικής, ΑΠΘ B’ εξάμηνο
Lab 3: Sorted List ΕΠΛ231-Δομές Δεδομένων και Αλγόριθμοι18/10/2010.
Πολυδιάστατοι Πίνακες, Δομές, Ενώσεις
Εισαγωγή στους Η/Υ Πίνακες.
Πινακες (Arrays) Σημασια Συνταξη Αρχικοποιηση Προσβαση Παραμετροι
Δείκτες, Πίνακες και Δείκτες, Δείκτες σε Συναρτήσεις
ΕΙΣΑΓΩΓΗ ΣΤΟ ΔΙΑΔΙΚΑΣΤΙΚΟ ΠΡΟΓΡΑΜMΑΤΙΣΜΟ ΠΑΝΕΠΙΣΤΗΜΙΟ ΠΑΤΡΩΝ – ΠΟΛΥΤΕΧΝΙΚΗ ΣΧΟΛΗ ΤΜΗΜΑ ΜΗΧΑΝΙΚΩΝ Η/Υ ΚΑΙ ΠΛΗΡΟΦΟΡΙΚΗΣ.
Συναρτήσεις Κληση/Επιστροφη Παραμετροι
Προγραμματισμός PASCAL Πληροφορική Γ' Λυκείου μέρος γ
ΠΑΝΕΠΙΣΤΗΜΙΟ ΘΕΣΣΑΛΙΑΣ ΤΜΗΜΑ ΜΗΧΑΝΟΛΟΓΩΝ ΜΗΧΑΝΙΚΩΝ ΒΙΟΜΗΧΑΝΙΑΣ Διάλεξη 3: Δείκτες Εαρινό εξάμηνο 2009 ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ Ι. Σαρρής, τηλ.
-17 Προσδοκίες οικονομικής ανάπτυξης στην Ευρώπη Σεπτέμβριος 2013 Δείκτης > +20 Δείκτης 0 a +20 Δείκτης 0 a -20 Δείκτης < -20 Σύνολο στην Ευρωπαϊκή Ένωση:
Τελεστές ανάθεσης (assignment)
Κεφάλαιο 2ο Πεπερασμένα αυτόματα.
Κοντινότεροι Κοινοί Πρόγονοι α βγ θ δεζ η π ν ι κλμ ρσ τ κκπ(λ,ι)=α, κκπ(τ,σ)=ν, κκπ(λ,π)=η κκπ(π,σ)=γ, κκπ(ξ,ο)=κ ξο κκπ(ι,ξ)=β, κκπ(τ,θ)=θ, κκπ(ο,μ)=α.
Προγραμματισμός ΙΙ Διάλεξη #6: Απλές Δομές Ελέγχου Δρ. Νικ. Λιόλιος.
Δομές Αναζήτησης TexPoint fonts used in EMF. Read the TexPoint manual before you delete this box.: AA A A A Χειριζόμαστε ένα σύνολο στοιχείων όπου το κάθε.
Ολυμπιάδα Πληροφορικής
1 Α. Βαφειάδης Αναβάθμισης Προγράμματος Σπουδών Τμήματος Πληροφορικής Τ.Ε.Ι Θεσσαλονίκης Μάθημα Προηγμένες Αρχιτεκτονικές Υπολογιστών Κεφαλαίο Τρίτο Συστήματα.
Δομές Δεδομένων 1 Στοίβα. Δομές Δεδομένων 2 Στοίβα (stack)  Δομή τύπου LIFO: Last In - First Out (τελευταία εισαγωγή – πρώτη εξαγωγή)  Περιορισμένος.
Τεχνολογία ΛογισμικούSlide 1 Αλγεβρική Εξειδίκευση u Καθορισμός τύπων αφαίρεσης σε όρους σχέσεων μεταξύ τύπων λειτουργιών.
Προγραμματισμός ΙΙ Διάλεξη #5: Εντολές Ανάθεσης Εντολές Συνθήκης Δρ. Νικ. Λιόλιος.
1 Τμήμα Μηχανικών Ηλεκτρονικών Υπολογιστών και Πληροφορικής Πανεπιστήμιο Πατρών ΟΝΤΟΚΕΝΤΡΙΚΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΙΙ (C++) Κληρονομικότητα.
Ε. ΠετράκηςΣτοίβες, Ουρές1 Στοίβες  Στοίβα: περιορισμένη ποικιλία λίστας  τα στοιχεία μπορούν να εισαχθούν ή να διαγραφούν μόνο από μια άκρη : λίστες.
ΕΙΣΑΓΩΓΗ ΣΤΗΝ ΠΛΗΡΟΦΟΡΙΚΗ
Lists– Λίστες 1. Αυτό-αναφορικές δομές Τα μέλη μίας δομής μπορεί να είναι οποιουδήποτε τύπου, ακόμα και δείκτες σε δομές του ίδιου τύπου. Χρησιμοποιώντας.
Δυναμικη Δεσμευση Μνημης Συνδεδεμενες Λιστες (dynamic memory allocation, linked lists) Πως υλοποιουμαι προγραμματα που δεν γνωριζουμε πριν την εκτελεση.
Δείκτες (Pointers) – Δομές (Structs)
2-1 Ανάλυση Αλγορίθμων Αλγόριθμος Πεπερασμένο σύνολο εντολών που, όταν εκτελεστούν, επιτυγχάνουν κάποιο επιθυμητό αποτέλεσμα –Δεδομένα εισόδου και εξόδου.
ΗΥ150 – ΠρογραμματισμόςΚώστας Παναγιωτάκης ΗΥ-150 Προγραμματισμός Αρχεία.
TexPoint fonts used in EMF. Read the TexPoint manual before you delete this box.: AA A A A Ουρά Προτεραιότητας (priority queue) Δομή δεδομένων που υποστηρίζει.
TexPoint fonts used in EMF. Read the TexPoint manual before you delete this box.: AA A A A Ουρά Προτεραιότητας (priority queue) Δομή δεδομένων που υποστηρίζει.
HY340 : ΓΛΩΣΣΕΣ ΚΑΙ ΜΕΤΑΦΡΑΣΤΕΣ ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΡΗΤΗΣ, ΣΧΟΛΗ ΘΕΤΙΚΩΝ ΕΠΙΣΤΗΜΩΝ, ΤΜΗΜΑ ΕΠΙΣΤΗΜΗΣ ΥΠΟΛΟΓΙΣΤΩΝ ΔΙΔΑΣΚΩΝ Αντώνιος Σαββίδης.
1 ΗΥ-340 Γλώσσες και Μεταφραστές Φροντιστήριο Πίνακας Συμβόλων Symbol Table.
MΑΘ 106/3122Ξενοφών Ζαμπούλης ΜΑΘ 106/3122 Γλώσσα Προγραμματισμού Δείκτες (Pointers)
Βάσεις Δεδομένων Εργαστήριο ΙΙ Τμήμα Πληροφορικής ΑΠΘ
ΜΑΘΗΜΑ: ΓΛΩΣΣΑ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ C++ ΔΙΔΑΣΚΩΝ: Π. ΚΑΤΣΑΡΟΣ Πέμπτη, 2 Απριλίου 2015Πέμπτη, 2 Απριλίου 2015Πέμπτη, 2 Απριλίου 2015Πέμπτη, 2 Απριλίου 2015Τμ.
TexPoint fonts used in EMF. Read the TexPoint manual before you delete this box.: AA A A A Ουρά Προτεραιότητας (priority queue) Δομή δεδομένων που υποστηρίζει.
ΛΟΓ102: Τεχνολογία Λογισμικού Ι Διδάσκων: Νίκος Παπασπύρου 1Νίκος ΠαπασπύρουΛΟΓ102:
Στοιχειώδεις Δομές Δεδομένων TexPoint fonts used in EMF. Read the TexPoint manual before you delete this box.: AA A A A Τύποι δεδομένων στη C Ακέραιοι.
ΗΥ150 – Προγραμματισμός Ξ. Ζαμπούλης ΗΥ-150 Προγραμματισμός Δομές Δεδομένων.
1 Τμήμα Μηχανικών Ηλεκτρονικών Υπολογιστών και Πληροφορικής Πανεπιστήμιο Πατρών ΟΝΤΟΚΕΝΤΡΙΚΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΙΙ (C++) Τάξεις και Αφαίρεση Δεδομένων.
ΛΟΓ102: Τεχνολογία Λογισμικού Ι Διδάσκων: Νίκος Παπασπύρου 1Νίκος ΠαπασπύρουΛΟΓ102:
ΑΝΑΠΤΥΞΗ ΕΦΑΡΜΟΓΩΝ ΣΕ ΠΡΟΓΡΑΜΜΑΤΙΣΤΙΚΟ ΠΕΡΙΒΑΛΛΟΝ
Lab 3: Sorted List ΕΠΛ231-Δομές Δεδομένων και Αλγόριθμοι115/4/2015.
1 ΤΜΗΜΑ ΜΠΕΣ Αλγόριθμοι Αναζήτησης Εργασία 1 Τυφλή Αναζήτηση.
9-1 ΜΑΘΗΜΑ 9 ο Δυαδικά Δένδρα, Διάσχιση Δυαδικών Δένδρων Υλικό από τις σημειώσεις Ν. Παπασπύρου, 2006.
ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ Κλάσεις και Αντικείμενα Αναφορές.
ΠΡΟΓΡΑΜΜΑΤΙΣΤΙΚΕΣ ΤΕΧΝΙΚΕΣ Διδάσκοντες:Γιάννης Μαΐστρος Στάθης Ζάχος Νίκος Παπασπύρου
ΠΡΟΓΡΑΜΜΑΤΙΣΤΙΚΕΣ ΤΕΧΝΙΚΕΣ Διδάσκοντες:Γιάννης Μαΐστρος Στάθης Ζάχος Νίκος Παπασπύρου
ΕΠΛ 231 – Δομές Δεδομένων και Αλγόριθμοι 4-1 Στην ενότητα αυτή θα μελετηθεί η χρήση στοιβών στις εξής εφαρμογές: Αναδρομικές συναρτήσεις Ισοζυγισμός Παρενθέσεων.
ΗΥ150 – ΠρογραμματισμόςΞ. Ζαμπούλης ΗΥ-150 Προγραμματισμός Αρχεία.
Δομές Δεδομένων και Αρχεία Ενότητα 10: Κυκλικά και Διπλά Συνδεδεμένη Λίστα Ηλίας Κ. Σάββας, Αναπληρωτής Καθηγητής, Τμήμα Μηχανικών Πληροφορικής Τ.Ε., T.E.I.
Δομές Δεδομένων και Αρχεία
ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΗΛΕΚΤΡΟΝΙΚΩΝ ΥΠΟΛΟΓΙΣΤΩΝ Διδάσκοντες:Στάθης Ζάχος Νίκος Παπασπύρου
ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ Κλάσεις και Αντικείμενα.
Οι Δομές Δεδομένων Ουρά και Στοίβα
EPL231 – Data Structures and Algorithms
Οι Δομές Δεδομένων Ουρά και Στοίβα
Αναδρομή Στην ενότητα αυτή θα μελετηθούν τα εξής επιμέρους θέματα:
Μεταγράφημα παρουσίασης:

6-1 ΜΑΘΗΜΑ 6 ο Ανασκόπηση σε Δείκτες, Συνδεδεμένες Λίστες, Ουρές, Στοίβες

6-2 Δείκτες (pointers) - Ανασκόπηση(i) Μεταβλητές –που δεν περιέχουν μια τιμή κάποιου απλού τύπου δεδομένων –αλλά τη διεύθυνση μιας άλλης μεταβλητής Παράδειγμα int x, *p; x δ124 p δ δ124

6-3 Δείκτες (pointers)(ii) Δεικτοδότηση: & –η διεύθυνση μιας μεταβλητής p = &x; Αποδεικτοδότηση: * –το περιεχόμενο μιας διεύθυνσης printf("%d", *p); *p = 7; x δ124 p δ δ124

6-4 Πίνακες και δείκτες(i) Αριθμητική δεικτών int a[3] = {7, 6, 42}; int *p; p δ247 a δ124 7 δ125 6 δ δ124 p = &(a[0]); p = &a; p = a; printf("%d\n", *p); printf("%d\n", *(p+1)); p = p+2; printf("%d\n", *p);

6-5 Πίνακες και δείκτες(ii) Ισοδυναμία πινάκων και δεικτών –Ένας πίνακας είναι ένας δείκτης στο πρώτο στοιχείο. –a[i] ισοδύναμο με *(a+i) –Οι πίνακες όμως είναι σταθεροί δείκτες, δηλαδή δεν μπορούν να αλλάξουν τιμή int a[3] = {7, 6, 42}; int *p = &a; p++; /* correct */ a++; /* wrong! */

6-6 Πίνακες και δείκτες(iii) Παράδειγμα: αντιγραφή πινάκων int a[10], b[10]; int *p = a, *q = b, i; /* assume b initialized */ for (i=0; i<10; i++) *p++ = *q++;

6-7 Πίνακες και δείκτες(iv) Παράδειγμα: εκτύπωση συμβολοσειράς void putchar (char c); char s[] = "Hello world!\n"; char *p; for (p = s; *p != '\0'; p++) putchar(*p);

6-8 Κενός δείκτης και δείκτης σε κενό Ο κενός δείκτης: NULL –Απαγορεύεται να αποδεικτοδοτηθεί! int *p = NULL; *p = 42; /* wrong! */ –Ο μόνος δείκτης που αντιστοιχεί στην ψευδή λογική τιμή, όταν χρησιμοποιείται σε συνθήκη Ο δείκτης σε κενό: void * –Γενική μορφή δείκτη –Απαγορεύεται να αποδεικτοδοτηθεί! –Απαγορεύεται η αριθμητική δεικτών!

6-9 Δείκτες αντί περάσματος με αναφορά Κώδικας Pascal procedure inc (var x : integer); begin x := x+1 end;... inc(a)... Ισοδύναμος κώδικας C void inc (int * ptr_x) { (*ptr_x)++; }... inc(&a)...

6-10 Δείκτες σε εγγραφές Συντομογραφία p->x είναι ισοδύναμο με (*p).x Παράδειγμα struct { int x, y; } coordinates, *p; coordinates.x = 1; coordinates.y = 3; p = &coordinates; printf("%d\n", p->x); printf("%d\n", p->y);

6-11 Μετατροπές τύπων(i) Έμμεσες (coercions) double d = 3; (με ανάθεση) int x = 3.14; int f (int x); (με πέρασμα παραμέτρου) f(3.14); Άμεσες (type casting) ( τύπος ) έκφραση (double) 3 (int) 3.14 (int *) NULL

6-12 Μετατροπές τύπων(ii) Πρόβλημα: πώς μπορώ να τυπώσω το αποτέλεσμα της πραγματικής διαίρεσης δυο ακεραίων αριθμών, χωρίς νέες μεταβλητές; int x = 5, y = 3; Λάθος λύση #1: printf("%d", x/y); Λάθος λύση #2: printf("%lf", x/y); Σωστές λύσεις: printf("%lf", 1.0 * x / y); printf("%lf", (double) x / (double) y); printf("%lf", (double) x / y);

6-13 Δυναμική παραχώρηση μνήμης(i) Συναρτήσεις βιβλιοθήκης –void * malloc (size_t n); Δυναμική παραχώρηση μνήμης μήκους n bytes. Το αποτέλεσμα πρέπει να μετατραπεί στο σωστό τύπο. Επιστρέφεται NULL αν εξαντληθεί η μνήμη. –void free (void * p); Αποδέσμευση της μνήμης στην οποία δείχνει το p. Το p πρέπει να έχει δημιουργηθεί με προηγούμενη κλήση στη malloc. Πόσα bytes χρειάζονται; –sizeof( type ) π.χ. sizeof(int) –sizeof( variable ) π.χ. sizeof(x)

6-14 Δυναμική παραχώρηση μνήμης(ii) Παράδειγμα int *p; int i; p = (int *) malloc(sizeof(int)); *p = 42; free(p); p = (int *) malloc(10 * sizeof(int)); for (i = 0; i < 10; i++) p[i] = 42; free(p); Το αποτέλεσμα της malloc πρέπει να ελεγχθεί ότι δεν είναι NULL !

6-15 ΔΟΜΕΣ & ΔΕΙΚΤΕΣ Ας θεωρήσουμε την παρακάτω δήλωση τύπου typedef struct { int idNumber; char descr[100]; int avail; } sparePartType; Και τις δηλώσεις μεταβλητών: sparePartType var1 = (123, “Wheel”, 1); /* Αρχικές τιμές */ sparePartType *var2 = (sparePartType *) malloc(sizeof(sparePartType); Για να αποθέσουμε τιμές ή να χρησιμοποιήσουμε τα πεδία μπορούμε να γράψουμε: *var2 = var1; /* Αποθέτουμε όλες τις τιμές των πεδίων από την var1 στη θέση μνήμης που «δείχνει η var2 */ var2->idNumber = 10; /* Σύνταξη όταν χρησιμοποιούμε δείκτες σε δομές */ var1.idNumber = 20; /* Σύνταξη όταν χρησιμοποιούμε απλές μεταβλητές δομών */

6-16 ΔΟΜΕΣ & ΔΙΑΝΥΣΜΑΤΑ Οι δομές και τα διανύσματα μπορούν να συνδυασθούν χωρίς περιορισμούς π.χ. typedef struct { char firstName[10]; char lastName[10]; } personType; typedef struct { personType aPerson; int id; int age; int sex; } classType; Οπότε μπορούμε να ορίσουμε μία τάξη μαθητών σαν ένα διάνυσμα στοιχείων τύπου classType. Εάν υποθέσουμε ότι η τάξη μας έχει 10 άτομα τότε ορίζεται σαν μία μεταβλητή π.χ. Class101Var classType class101Var[10]; Σε κάθε «κελί» του διανύσματος υπάρχει μία δομή tύπου classType. Για να βρούμε το μικρό όνομα του τρίτου μαθητή class101Var[2], γράφουμε: (class101Var[2].aPerson).firstName

6-17 ΔΟΜΕΣ & ΔΙΑΝΥΣΜΑΤΑ & ΔΕΙΚΤΕΣ typedef struct { char firstName[10]; char lastName[10]; int id; int age; int sex; } personType; typedef struct { char * classId; personType *aPerson; } classType; Οπότε μπορούμε να ορίσουμε μία τάξη μαθητών σαν ένα διάνυσμα στοιχείων τύπου classType. Εάν υποθέσουμε ότι η τάξη μας έχει 10 άτομα τότε ορίζεται σαν μία μεταβλητή π.χ. Class101Var classType class101Var[10]; classType initializeClass(classType class101Var) { for (int i = 0; i< 10; i++) { class101Var[i].classId = malloc(7); strcpy(class101Var[i].classId, “ECE101”); class101Var[i].aPerson = (personType *) malloc(sizeof(personType)); strcpy((class101Var[i].aPerson)  firstName, “”); strcpy(class101Var[i].aPerson  lastName, “”); (class101Var[i].aPerson)  id = 0; class101Var[i].aPerson  age = 0; class101Var[i].aPerson  sex = 0; return(class101Var); }

6-18 ΠΑΡΑΔΕΙΓΜΑ typedef struct { int F1; int F2; …….. int F8 } aStructType; aStructType *structArray[10]; structArray[0] = (aStructType *) malloc(sizeof(aStructType)); structArray[0]  F1 = 10; *structArray[0].F2 = 20; …………… F1F2F3F4F5F6F7F8 StructArray[ ] aStructType

6-19 ΔΙΑΣΥΝΔΕΟΜΕΝΕΣ ΛΙΣΤΕΣ - 1 Μέχρι τώρα έχουμε μιλήσει για απλές κατασκευές δεδομένων όπως δομές, διανύσματα, και πίνακες Επίσης χρησιμοποιήσαμε αυτές τις απλές κατασκευές για να ορίσουμε πιο σύνθετες κατασκευές όπως διανύσματα από δομές, διανύσματα από δείκτες σε δομές κλπ. Το κοινό χαρακτηριστικό των κατασκευών που είδαμε μέχρι τώρα είναι ότι το μέγεθός τους ορίζεται στατικά κατά την σχεδίαση του προγράμματος. Για παράδειγμα τα διανύσματα έχουν πεπερασμένο μήκος, μέγεθος, και διαστάσεις Το ζητούμενο είναι να ορίσουμε κατασκευές (π.χ. Λίστες) για τις οποίες δεν χρειάζεται να ορίσουμε πόσα στοιχεία έχουν, αλλά θα μπορούμε να προσθέτουμε όσα στοιχεία θέλουμε δυναμικά, δηλαδή κατά την εκτέλεση, και σύμφωνα με τις ανάγκες του προγράμματος μας

6-20 ΔΙΑΣΥΝΔΕΟΜΕΝΕΣ ΛΙΣΤΕΣ - 2 Πριν όμως προχωρήσουμε στην παρουσίαση των διασυνδεόμενων λιστών ας κάνουμε μία μικρή επανάληψη στις δομές Η παρακάτω κατασκευή ορίζει ένα μία δομή με τρία πεδία (fields). struct { int id; char * name; char * surname; } Γραφικά η παραπάνω δομή θα μπορούσε να παρασταθεί ως εξής: int idchar* namechar * surname

6-21 ΔΙΑΣΥΝΔΕΟΜΕΝΕΣ ΛΙΣΤΕΣ - 3 Εάν θέλαμε να φτιάξουμε μία κατασκευή π.χ. το μοντέλο μίας τάξης από μαθητές, ένας τρόπος θα ήταν να ορίσουμε ένα διάνυσμα από δομές σαν και αυτή που ορίσαμε παραπάνω, ή ακόμη καλύτερα ένα διάνυσμα από δείκτες σε τέτοιες δομές. Σχηματικά οι δύο αυτές περιπτώσεις θα φαίνονται ως εξής: F3F2F1 ClassArray_2[9] F1 F2 F3 Δομή Διάνυσμα classArray_1[9] Δομή

6-22 ΔΙΑΣΥΝΔΕΟΜΕΝΕΣ ΛΙΣΤΕΣ - 4 Ας δούμε όμως τώρα τι θα γινόταν εάν εισάγαμε σε μία δομή ένα νέο πεδίο το οποίο θα ήταν ένας δείκτης σε δομή του ιδίου τύπου! Ας υποθέσουμε λοιπόν τα εξής: struct Student { int id; char * name; char * surname; Student *next; }; int idchar *namechar *surname Student * next

6-23 ΔΙΑΣΥΔΕΟΜΕΝΕΣ ΛΙΣΤΕΣ - 5 Ας θεωρήσουμε τώρα μια κατασκευή που μοιάζει όπως το παρακάτω σχήμα: int idchar *namechar *surname Student * next int idchar *namechar *surname Student * next int idchar *namechar *surname Student * next NULL struct Student { int id; char *name; char *surname; Student *next; }; typedef struct Student StudentType; StudentType *list_first = NULL, *list_second, *list_third; list_first = (StudentType *) malloc(sizeof(Student)); list_first->next = (StudentType *) malloc(sizeof(Student)); list_second = list_first->next; list_second->next = (StudentType *) malloc(sizeof(Student)); list_third = list_second->next; list_third->next = NULL;

6-24 ΔΙΑΣΥΝΔΕΟΜΕΝΕΣ ΛΙΣΤΕΣ - 6 struct Student { int id; char *name; char *surname; Student *next; }; typedef struct Student StudentType; StudentType *list_first, *list_second, *list_third; list_first = (StudentType *) malloc(sizeof(StudentType)); list_first->next = (StudentType *) malloc(sizeof(StudentType)); list_second = list_first->next; list_second->next = (StudentType *) malloc(sizeof(StudentType)); list_third = list_second->next; list_third->next = NULL; * list_first * list_second int idchar *namechar *surname Student * next int idchar *namechar *surname Student * next int idchar *namechar *surname Student * next * list_third NULL

6-25 ΔΙΑΣΥΝΔΕΟΜΕΝΕΣ ΛΙΣΤΕΣ - 7 int idchar *namechar *surname Student * next int idchar *namechar *surname Student * next Int idchar *namechar *surname Student * next * temp NULL * list * temp struct Student { int id; char *name; char *surname; Student *next; }; typedef struct Student StudentType; StudentType *list, *temp; int i; list = (StudentType *) malloc(sizeof(StudentType)); temp = list; for(i=1; i<3; i++) { temp->next = (StudentType *) malloc(sizeof(StudentType)); temp = temp->next; temp->next = NULL; } * temp NULL

6-26 ΠΑΡΑΛΛΑΓΕΣ ΔΙΑΣΥΝΔΕΟΜΕΝΕΣ ΛΙΣΤΩΝ Μέχρι τώρα είδαμε διασυνδεόμενες λίστες όπου οι κόμβοι είναι ενωμένοι από τον πρώτο κόμβο (κεφαλή της λίστας) προς τον τελευταίο (ουρά της λίστας) Υπάρχουν αρκετές παραλλαγές αυτής της απλής τοπολογίας. Μερικές και πιο συνήθεις από αυτές τις παραλλαγές είναι: – Π1. Ο τελευταίος κόμβος συνδέεται με τον πρώτο (κυκλικές λίστες) –Π2. Ο κάθε κόμβος συνδέεται με τον επόμενο και με τον προηγούμενο –Π3. Υπάρχουν κάποιοι εξωτερικοί κόμβοι που είναι δείκτες σε συγκεκριμένους (και πιθανόν σημαντικούς) κόμβους της λίστας.

6-27 ΠΑΡΑΛΛΑΓΗ 1 (Σχηματικά) Σε αυτή τη παραλλαγή ο τελευταίος κόμβος είναι συνδεδεμένος με τον πρώτο. Σε αυτή τη περίπτωση ο πρώτος και (εάν θέλουμε) και ο τελευταίος κόμβος θα πρέπει να χαρακτηρίζονται κατάλληλα ώστε να γνωρίζουμε ποιοι είναι αυτοί οι κόμβοι. Αυτό επιτυγχάνεται με τη χρήση δύο μεταβλητών (π.χ. first, last) που είναι δείκτες στον πρώτο και τελευταίο κόμβο αντίστοιχα. firstlast

6-28 ΠΑΡΑΛΛΑΓΗ 1 (Κώδικας –Δύο Κόμβοι) typedef struct Rec_tag { char data[21]; Rec_tag *next; } Rec; typedef Rec *RecPointer; void main() { RecPointer r1, r2, first, last; r1 = (RecPointer)malloc(sizeof(Rec)); r1->next = r1; first = r1; last = r1; r2 = (RecPointer)malloc(sizeof(Rec)); r1->next = r2; last = r2; r2->next = first; }

6-29 ΠΑΡΑΔΕΙΓΜΑ ΠΑΡΑΛΛΑΓΗ 1 – ΔΙΑΓΡΑΦΗ ΤΕΛΕΥΤΑΙΟΥ ΚΟΜΒΟΥ typedef struct Rec_tag { char data[21]; char data[21]; Rec_tag *next; Rec_tag *next; } Rec; typedef Rec *RecPointer; RecPointer deleteLast(RecPointer first, RecPointer last) { RecPointer current = first; RecPointer current = first; while (current->next != last) while (current->next != last) current = current->next; current = current->next; current->next = first; current->next = first; free(last); free(last); last = current; last = current; }

6-30 ΠΑΡΑΛΛΑΓΗ 2.1 (Σχηματικά) Σε αυτή τη παραλλαγή ο κάθε κόμβος είναι συνδεδεμένος με τον προηγούμενο. Σε αυτή τη περίπτωση ο πρώτος κόμβος θα πρέπει να χαρακτηρίζεται κατάλληλα ώστε να γνωρίζουμε πια είναι η κεφαλή της λίστας. Αυτό επιτυγχάνεται με τη χρήση μίας μεταβλητής (π.χ. first) που είναι δείκτης στον πρώτο κόμβο. first NULL previous next

6-31 ΠΑΡΑΛΛΑΓΗ 2.1 (Κώδικας – Δύο Κόμβοι) typedef struct Rec_tag { char data[21]; Rec_tag *next; Rec_tag *previous; } Rec; typedef Rec *RecPointer; void main() { RecPointer r1, r2, first, last; r1 = (RecPointer)malloc(sizeof(Rec)); r1->next = NULL; r1->previous = NULL; first = r1; r2 = (RecPointer)malloc(sizeof(Rec)); r1->next = r2; r2->next = NULL; r2->previous = r1; }

6-32 ΠΑΡΑΔΕΙΓΜΑ ΠΑΡΑΛΛΑΓΗ 2.1 – ΕΙΣΑΓΩΓΗ ΠΡΙΝ ΑΠΟ ΚΑΠΟΙΟ ΚΟΜΒΟ typedef struct Rec_tag{ char data[21]; char data[21]; Rec_tag *next; Rec_tag previous; Rec_tag *next; Rec_tag previous; } Rec; typedef Rec *RecPointer; RecPointer InsertBefore(RecPointer first, RecPointer beforeNode, RecPointer aNewNode) { RecPointer current = first; RecPointer current = first; while (current != beforeNode && current->next != NULL) while (current != beforeNode && current->next != NULL) current = current->next; current = current->next; if(current == beforeNode) { if(current == beforeNode) { aNewNode->next = beforeNode; aNewNode->next = beforeNode; aNewNode->previous = beforeNode->previous; aNewNode->previous = beforeNode->previous; beforeNode->previous->next = aNewNode; beforeNode->previous->next = aNewNode; beforeNode->previous = aNewNode; beforeNode->previous = aNewNode; } elseif(current->next == NULL) elseif(current->next == NULL) current->next = aNewNode current->next = aNewNode aNewNode->previous = current aNewNode->previous = current aNewNode-next = NULL; aNewNode-next = NULL; }

6-33 ΠΑΡΑΛΛΑΓΗ 2.2 (Σχηματικά) Σε αυτή τη παραλλαγή ο τελευταίος κόμβος είναι συνδεδεμένος με τον πρώτο και κάθε κόμβος είναι συνδεδεμένος με τον προηγούμενο. Σε αυτή τη περίπτωση ο πρώτος και (εάν θέλουμε) και ο τελευταίος κόμβος θα πρέπει να χαρακτηρίζονται κατάλληλα ώστε να γνωρίζουμε ποιοι είναι αυτοί οι κόμβοι. Αυτό επιτυγχάνεται με τη χρήση δύο μεταβλητών (π.χ. p1, p2) που είναι δείκτες στον πρώτο και τελευταίο κόμβο αντίστοιχα. firstlast

6-34 ΠΑΡΑΛΛΑΓΗ 2.2 (Κώδικας–Δύο Κόμβοι) typedef struct Rec_tag { char data[21]; Rec_tag *next; Rec_tag *previous; } Rec; typedef Rec *RecPointer; void main() { RecPointer r1, r2, first, last; r1 = (RecPointer)malloc(sizeof(Rec)); r1->next = NULL; r1->previous = NULL; first = r1; r2 = (RecPointer)malloc(sizeof(Rec)); last = r2; r1->next = r2; r2->next = NULL; r1->previous = r2; r2->previous = r1; }

6-35 ΠΑΡΑΔΕΙΓΜΑ ΠΑΡΑΛΛΑΓΗ 2.2 – ΕΙΣΑΓΩΓΗ ΠΡΙΝ ΑΠΟ ΚΑΠΟΙΟ ΚΟΜΒΟ typedef struct Rec_tag { char data[21]; char data[21]; Rec_tag *next; Rec_tag *next; } Rec; typedef Rec *RecPointer; RecPointer InsertBefore(RecPointer first, RecPointer last, RecPointer beforeNode, RecPointer aNewNode) { RecPointer aNewNode) { RecPointer current = first; RecPointer current = first; while (current != beforeNode && current != last) while (current != beforeNode && current != last) current = current->next; current = current->next; if(current == beforeNode) { if(current == beforeNode) { aNewNode->next = beforeNode; aNewNode->next = beforeNode; aNewNode->previous = beforeNode->previous; aNewNode->previous = beforeNode->previous; (beforeNode->previous)->next = aNewNode; (beforeNode->previous)->next = aNewNode; beforeNode->previous = aNewNode; beforeNode->previous = aNewNode; } elseif(current == last) elseif(current == last) current->next = aNewNode current->next = aNewNode aNewNode->previous = current aNewNode->previous = current aNewNode-next = first; aNewNode-next = first; }

6-36 ΠΑΡΑΛΛΑΓΗ 3 (Σχηματικά) Σε αυτή τη παραλλαγή υπάρχουν εξωτερικοί κόμβοι που «δείχνουν» σε σημαντικούς κόμβους της λίστας (όπως ο πρώτος κόμβος και ο τελευταίος). Αυτή η παραλλαγή χρησιμοποιείται όταν θέλουμε να μαρκάρουμε συγκεκριμένους κόμβους της λίστας. Προφανώς, όλες οι παραπάνω παραλλαγές μπορούν να συνδυασθούν και να παράγουν πιο σύνθετες κατασκευές. Η ιδέα είναι να σχεδιάζουμε κατασκευές οι οποίες επιτρέπουν την πιο γρήγορη εκτέλεση του αλγόριθμού μας.....

6-37 ΠΑΡΑΛΛΑΓΗ 3 (Κώδικας–Δύο Κόμβοι) typedef struct Rec_tag { char data[21]; Rec_tag *next; Rec_tag *previous; } Rec; typedef Rec *RecPointer; typedef struct External_tag { char info[21]; External_tag *ptrToListNode; } External; typedef External *ExternalPointer; void main() { RecPointer r1, r2; ExternalPointer ext1, ext2; r1 = (RecPointer)malloc(sizeof(Rec)); ext1 = (ExternalPointer)malloc(sizeof(External)); r1->next = NULL; r2 = (RecPointer)malloc(sizeof(Rec)); ext2 = (ExternalPointer)malloc(sizeof(External)); r1->next = r2; r2->next = NULL; ext1->ptrToListNode = r1; ext2->ptrToListNode = r2; }

6-38 ΟΥΡΕΣ Ο ΑΤΔ Ουρά περιγράφει μία «λίστα» αντικειμένων η οποία όμως έχει συγκεκριμένο τρόπο λειτουργίας για την εισαγωγή νέων στοιχείων και την εξαγωγή στοιχείων που υπάρχουν ήδη στη λίστα. Ο ΑΤΔ Ουρά έχει λοιπόν την εξής λειτουργία για την εισαγωγή νέων στοιχείων και την εξαγωγή στοιχείων που υπάρχουν ήδη στη λίστα: –Τα νέα στοιχεία τοποθετούνται πάντα στο τέλος της «λίστας» –Το μόνο στοιχείο το οποίο μπορεί να εξαχθεί από τη λίστα κάθε φορά είναι το πρώτο στοιχείο της λίστας (το στοιχείο της κεφαλής της λίστας)

6-39 Ο ΑΤΔ Ουρά Χαρακτηριστικά: –Μήκος Έγγυρες Πράξεις –Δημιουργία() : Ουρά –Εύρεση_Μήκους(Ουρά) : ακέραιος –Είναι_Κενή?(Ουρά): λογικό –Εισαγωγή(Ουρά, στοιχείο) : Ουρά –Ανάκτηση(Ουρά) : στοιχείο –Αντιγραφή(Ουρά, Ουρά) : Ουρά –Σύγκριση(Ουρά, Ουρά) : λογικό

6-40 ΥΛΟΠΟΙΗΣΗ ΟΥΡΑΣ ΜΕ ΔΙΑΣΥΝΔΕΟΜΕΝΕΣ ΛΙΣΤΕΣ #include struct Node { int data; Node *next; Node *previous; }; typedef struct Node NodeType; typedef struct { char queueName[10]; NodeType *last; } QueueType; void initialize(char Name[], QueueType *q); void enqueue(QueueType *q, int k); NodeType *dequeue(QueueType *q); queueName last next data prev NULL Πρώτος Κόμβος – Κεφαλή της Ουράς Τελευταίος Κόμβος next data prev NULL

6-41 ΟΙ ΛΕΙΤΟΥΡΓΙΕΣ ΤΟΥ ΑΤΔ ΟΥΡΑ void initialize(char name[]) { QueueType *q = (QueueType *) malloc(sizeof(QueueType)); q->last = NULL; strcpy(q->queueName, name); } NodeType *dequeue(QueueType *q) { NodeType *curent = q->last; NodeType *before = q->last; if(current != NULL && current->next == NULL) { /* One element */ q->last = NULL; return current; } elseif (current != NULL) { /* Several elements */ while(current != NULL) before = current; current = current->next; } before->previous->next = NULL; return before; } else /* Empty list */ return NULL; }

6-42 ΟΙ ΛΕΙΤΟΥΡΓΙΕΣ ΤΟΥ ΑΤΔ ΟΥΡΑ QueueType *enqueue(QueueType *q, int k) { NodeType *newNode = (NodeType *)malloc(sizeof(NodeType)); newNode->data = k; newNode->next = q->last; q->last->previous = newNode; q->last = newNode; return q; }

6-43 ΟΙ ΛΕΙΤΟΥΡΓΙΕΣ ΤΟΥ ΑΤΔ ΟΥΡΑ QueueType *copy (QueueType *source, QueueType *dest) { /* Copies source queue into a new empty queue */ NodeType *sourceNode = source->last; /* Current node in original list */ NodeType *new, *destNode; /* The new node in the new list, and the current node in the new list */ int count = 1; if(dest->last != NULL) { fprintf(stderr, “Destination is not empty list\n”); exit(1); }; while(sourceNode!= NULL) { new = (NodeType *) malloc(sizeof(NodeType)); if(count == 1) { /* First node to be copied */ dest->last = new; dest->previous = NULL; destNode = new; count = 2; } destNode->next = new; new->previous = destNode; new->next = NULL; } return dest;

6-44 ΟΙ ΛΕΙΤΟΥΡΓΙΕΣ ΤΟΥ ΑΤΔ ΟΥΡΑ int length(QueueType *q) { int size = 0; nodeType *curr = q->last; while(curr != NULL) { size = size +1; curr = curr->next; } return size; } int isEmpty?(QueueType *q) { if(q->last == NULL) return 1; else return 0;}

6-45 ΟΙ ΛΕΙΤΟΥΡΓΙΕΣ ΤΟΥ ΑΤΔ ΟΥΡΑ int areEqual?(QueueType *q1, QueueType *q2) { NodeType *node1 = q1->last; NodeType *node2 = q2->last; if(length(q1) != length(q2) /* Lists do not have equal size */ return 0; elseif (q1->last == NULL && q2->last == NULL) /* lists are empty */ return 1; else { /* lists have equal size and are not empty */ while (node1->data == node2->data && node1 != NULL && node2 !=NULL) { node1 = node1->next; node2 = node2->next; }; if(node1 != NULL) /* Nodes node1, node2 are not equal */ return 0; } return 1; }

6-46 Ο ΑΤΔ ΣΤΟΙΒΑ Οι κατασκευές που έχουμε δει μέχρι τώρα (διανύσματα, διασυνδεμένες λίστες με τις παραλλαγές τους, και ουρές) αποτελούν τη βάση για ακόμη πιο πολύπλοκες κατασκευές. Μία τέτοια κατασκευή είναι η στοίβα. Η στοίβα είναι και αυτή μία «λίστα» αντικειμένων, μόνο που έχει διαφορετική συμπεριφορά (δηλαδή έγκυρες πράξεις). Ο ΑΤΔ Στοίβα, είναι πολύ χρήσιμος για εφαρμογές στην επιστήμη υπολογιστών (computer science) Η συμπεριφορά το ΑΤΔ Στοίβα περιγράφεται ως εξής: –Τα νέα στοιχεία εισάγονται στην αρχή (ή καλύτερα) πάνω από τα ήδη υπάρχοντα στοιχεία. –Το στοιχείο που μπορεί να εξαχθεί από τη Στοίβα είναι το πάνω-πάνω στοιχείο (δηλαδή το πρώτο στοιχείο, αυτό που εισήχθη τελευταίο σε σειρά). –Επίσης μπορούμε να ελέγξουμε ένα η Στοίβα είναι άδεια, και πιο είναι το πάνω-πάνω στοιχείο της

6-47 Ο ΑΤΔ ΣΤΟΙΒΑ Εάν θεωρήσουμε την έννοια της Στοίβας αντικειμένων σαν ένα Αφηρημένο Τύπο Δεδομένων τότε αυτός θα έχει τις παρακάτω λειτουργίες (έγκυρες πράξεις) 1.Δημιουργία: Δημιουργεί μία κενή στοίβα 2.Κενή: Ελέγχει εάν μία στοίβα είναι κενή 3.Εισαγωγή : Δέχεται μία θέση στοίβα και εισάγει ένα στοιχείο πάνω από όλα τα άλλα. Η λειτουργία αυτή αναφέρεται στη βιβλιογραφία σαν push 4.Διαγραφή: Διαγράφει το πάνω-πάνω στοιχείο από τη στοίβα. Η λειτουργία αυτή αναφέρεται στη βιβλιογραφία σαν pop 5.Έλεγχος πρώτου στοιχείου: Δέχεται μια στοίβα, και επιστρέφει το στοιχείο που βρίσκεται πάνω-πάνω χωρίς να το διαγράφει από τη λίστα. Η λειτουργία αυτή αναφέρεται στη βιβλιογραφία σαν top

6-48 Ο ΑΤΔ ΣΤΟΙΒΑ Χαρακτηριστικά: –Μέγεθος Έγγυρες Πράξεις –Δημιουργία() : Στοίβα –Είναι_Κενή?(Στοίβα): λογικό –Push(Στοίβα, στοιχείο) : Στοίβα –Pop(Στοίβα) : στοιχείο –Top(Ουρά) : στοιχείο

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

6-50 ΥΛΟΠΟΙΗΣΗ ΤΗΣ ΣΤΟΙΒAΣ ΜΕ ΔΙΑNΥΣΜΑ #define length 100; int top = -1; void push(int stack[], int data) { int data; if(top+1==length) { printf("stack overflow\n"); exit(1); } top++; stack[top]=data; } int pop(int stack[]) { int value; int value; if(top==-1) { if(top==-1) { puts("stack is underflow"); puts("stack is underflow"); exit(1); exit(1); } value=stack[top]; value=stack[top]; top--; top--; return(value); return(value);} void main() { int stack[length]; int stack[length]; push(stack, 10); push(stack,20); pop(stack); }

6-51 ΥΛΟΠΟΙΗΣΗ ΤΗΣ ΣΤΟΙΒAΣ ΜΕ ΔΙΑΣΥΝΔΕΟΜΕΝΗ ΛΙΣΤΑ struct node { int data; struct node *next; }; typedef struct node nodeType; struct stack { nodeType *theStack; }; typedef struct stack stackType; StackType *aStack =(stackType *) malloc(sizeof(stackType)); aStack->theStack = NULL;

6-52 ΥΛΟΠΟΙΗΣΗ ΤΗΣ ΣΤΟΙΒAΣ ΜΕ ΔΙΑΣΥΝΔΕΟΜΕΝΗ ΛΙΣΤΑ void push(stackType *aStack, int data) { nodeType *t, *temp; int data; t=(nodeType *) malloc(sizeof(nodeType)); t->data=data; if(aStack->theStack == NULL) aStack->theStack=t; else { temp = aStack->theStack; t->next = temp; aStack->theStack=t; } int pop(stackType *aStack) { int value; int value; nodeType *t, *temp; nodeType *t, *temp; if(aStack->theStack==NULL) if(aStack->theStack==NULL) { puts("stack is underflow"); puts("stack is underflow"); exit(1); exit(1); } t= aStack->theStack; t= aStack->theStack; temp = t->next; temp = t->next; value=t->data; value=t->data; aStack->theStack = temp; aStack->theStack = temp; free(t); free(t); return(value); return(value);}

6-53 ΑΝΤΙΣΤΡΟΦΗ ΣΤΟΙΒΑΣ #define length 100; int top1 = -1; /* size of first stack */ Int top2 = -1; /*size of second stack */ void push(int stack[], int data, int *top) { int data; if(*top+1==length) { printf("stack overflow\n"); exit(1); } *top++; stack[*top]=data; } int pop(int stack[], int * top) { int value; int value; if(*top==-1) { if(*top==-1) { puts("stack is underflow"); puts("stack is underflow"); exit(1); exit(1); } value=stack[*top]; value=stack[*top]; *top--; *top--; return(value); return(value);} void reverse (stack1, stack2) { int size = top1; int data; for(int i=0; i<size; i++) { for(int i=0; i<size; i++) { data = pop(stack1, &top1); data = pop(stack1, &top1); push(stack2,data, &top2); push(stack2,data, &top2); } }

6-54 ΜΕΤΡΩΝΤΑΣ ΤΟ ΧΡΟΝΟ #include main() { int i; time_t t1, t2; (void) time(&t1); for (i=1;i<=300;i++) printf(``%d %d %d n'',i, i*i, i*i*i); (void) time(&t2); printf(`` n Time to do 300 squares and cubes= %d seconds n'', (int) t2-t1); }