ΤΥΠΟΙ ΚΑΙ ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ 1. Γενικά Κάθε δεδομένο που υπόκειται σε επεξεργασία από ένα πρόγραμμα ( δηλαδή τελικά από έναν ηλεκτρονικό υπολογιστή) έχει τον δικό του τύπο. Ο τύπος αυτός μπορεί να είναι σύνθετος ή απλός όπως θα δούμε παρακάτω. Σε κάθε περίπτωση ο τύπος κάθε δεδομένου οφείλει να οριστεί στην αρχή του προγράμματος. Κάποιες φορές ο ορισμός αυτός γίνεται αυτόματα από το ίδιο το πρόγραμμα, όμως τις περισσότερες φορές ο ορισμός του τύπου κάθε δεδομένου γίνεται από εκείνον που γράφει το πρόγραμμα. Τι όμως ακριβώς είναι ο τύπος δεδομένων; Ας δώσουμε έναν ορισμό: Τύπος Δεδομένων (Data Type) είναι ένα σύνολο ομοειδών δεδομένων (δηλαδή δεδομένων που έχουν ορισμένα κοινά χαρακτηριστικά), μαζί με όλες τις πράξεις που ορίζονται και έχουν νόημα πάνω σ αυτά. Ένας από τους πιο συνηθισμένους και απλούς τύπους δεδομένων είναι οι Ακέραιοι (Integer), δηλαδή οι αριθμοί -3, -2, -1, 0, 1, 2, 3 Οι πράξεις που ορίζονται πάνω στους ακεραίους και των οποίων τα αποτελέσματα ανήκουν επίσης στους ακεραίους είναι η πρόσθεση (ακεραίων), η αφαίρεση (ακεραίων), ο πολλαπλασιασμός (ακεραίων) και η ακέραια διαίρεση (δηλαδή η διαίρεση που δίνει ακέραιο πηλίκο και υπόλοιπο). Έτσι, αν κάποιο δεδομένο (ή κάποια μεταβλητή) ενός προγράμματος είναι τύπου Ακέραιος, τότε σίγουρα μπορεί να πάρει τις τιμές 12, 127, 0, -425 αλλά όχι τις τιμές -3.14, 127.8 ή ακόμα HELLO. Τύποι δεδομένων όπως ο παραπάνω (δηλαδή ο τύπος: Ακέραιοι) ονομάζονται απλοί ή στοιχειώδεις (simple, elementary data types). Γενικά, απλούς ονομάζομε τους τύπους εκείνους οι οποίοι αντιστοιχούν σε ήδη γνωστές και οικείες μαθηματικές και μη έννοιες. 2. Απλοί Τύποι Δεδομένων Οι πιο συνηθισμένοι απλοί τύποι δεδομένων είναι οι Ακέραιοι (Integer) οι Πραγματικοί (Real) οι Χαρακτήρες (Character) και οι Λογικοί αριθμοί (Logical ή Boolean * ) Παρακάτω θα δούμε πιο αναλυτικά τον καθένα από αυτούς. * Από το όνομα ενός σπουδαίου μαθηματικού που ασχολήθηκε συστηματικά με την Άλγεβρα των λογικών αριθμών, που τελικά ονομάστηκε Άλγεβρα του Boole (προφέρεται Μπούλ). -1-
2.1 Ακέραιοι (Integer) Είναι όπως είδαμε και παραπάνω ο πλέον γνωστός και συνηθισμένος τύπος δεδομένων. Στην πραγματικότητα ο τύπος αυτός περιλαμβάνει μόνο ένα πεπερασμένο υποσύνολο του -άπειρου- συνόλου των μαθηματικών ακεραίων. Αυτό φυσικά είναι αναμενόμενο, αφού ο ηλεκτρονικός υπολογιστής είναι ένα μηχάνημα με πεπερασμένες υπολογιστικές δυνατότητες και πεπερασμένη μνήμη. Οι περισσότεροι ηλεκτρονικοί, υπολογιστές αποθηκεύουν έναν ακέραιο αριθμό χρησιμοποιώντας 2 bytes (16 bits) μνήμης. Αυτό σημαίνει ότι μπορούν να αναγνωρίσουν το πολύ 2 16 = 65.536 διαφορετικές τιμές, δηλαδή από το 32.768 μέχρι και το 32.767. Όπως είπαμε και παραπάνω, οι πράξεις που ορίζονται πάνω στους ακεραίους και των οποίων τα αποτελέσματα ανήκουν επίσης στους ακεραίους είναι η πρόσθεση ( <ακέραιος> + <ακέραιος> = <ακέραιος> ), η αφαίρεση ( <ακέραιος> - <ακέραιος> = <ακέραιος> ), ο πολλαπλασιασμός ( <ακέραιος> x <ακέραιος> = <ακέραιος> ) και η ακέραια διαίρεση ( <διαιρετέος> / <διαιρέτης> = <πηλίκο, υπόλοιπο> ). 2.2 Πραγματικοί (Real) Όπως ακριβώς συμβαίνει και με τους ακέραιους, ο τύπος Πραγματικοί (Real) περιλαμβάνει μόνο ένα πεπερασμένο υποσύνολο του συνόλου των πραγματικών αριθμών της άλγεβρας. Πριν όμως δούμε ποιο είναι αυτό το υποσύνολο θα πρέπει να δούμε πώς ακριβώς αναπαρίστανται οι πραγματικοί αριθμοί στην (πεπερασμένη) μνήμη του ηλεκτρονικού υπολογιστή. 2.2.1 Επιστημονική Αναπαράσταση των πραγματικών αριθμών. (Scientific Notation) Είναι μια ειδική μορφή αναπαράστασης αριθμών που χρησιμοποιείται κυρίως σε επιστημονικές μετρήσεις. Σύμφωνα με αυτήν, κάθε αριθμός (όσο μεγάλος ή μικρός και αν είναι) παριστάνεται σαν ένα γινόμενο ενός δεκαδικού αριθμού * επί κάποια δύναμη του 10. Ανάλογα με την επιλογή της δύναμης του 10, μπορούμε να έχουμε πολλές διαφορετικές επιστημονικές αναπαραστάσεις του ίδιου αριθμού. * ή ακέραιου αριθμού (οι ακέραιοι άλλωστε αποτελούν υποσύνολο των δεκαδικών) -2-
Παράδειγμα 1. Μερικές πιθανές επιστημονικές αναπαραστάσεις του αριθμού 1500 είναι: 15 x 10 2 1,5 x 10 3 1500 x 10 0 0,15 x 10 4 0,0015 x 10 6 15000 x 10-1 Επειδή η βάση της δύναμης είναι πάντα το 10, μπορούμε να παραλείψουμε το 10 και να παριστάνουμε τους αριθμούς μας μόνο με το δεκαδικό τους μέρος και τον εκθέτη της δύναμης. Για να ξεχωρίσουμε μάλιστα τον εκθέτη, βάζουμε μπροστά του το γράμμα Ε. Σύμφωνα τώρα με αυτά που είπαμε, οι παραπάνω αριθμοί γράφονται: 15E2 1,5E3 1500E0 0,15E4 0,0015E6 15000E-1 Παράδειγμα 2. Μερικές πιθανές επιστημονικές αναπαραστάσεις του αριθμού 17,3 είναι: 17,3Ε0 1,73E1 0,173Ε2 0,000173E5 173,0E-1 1730E-2 173000E-4 κ.λ.π. Το πρώτο μέρος (δεκαδικό μέρος) της επιστημονικής αναπαράστασης ενός αριθμού ονομάζεται mantissa (δεν υπάρχει αντίστοιχος ελληνικός όρος) και το δεύτερο μέρος (το μέρος εκείνο δηλαδή που ακολουθεί το σύμβολο Ε ) ονομάζεται exponent (εκθέτης). 0,173 Ε 2 mantissa exponent Παρατηρούμε λοιπόν ότι η επιστημονική αναπαράσταση ενός πραγματικού αριθμού δεν είναι μοναδική. Στην πραγματικότητα μπορούμε να έχουμε άπειρες μορφές επιστημονικής αναπαράστασης, μετακινώντας απλώς δεξιά ή αριστερά την υποδιαστολή στην mantissa και προσαρμόζοντας ανάλογα τον εκθέτη. Αυτός είναι και ο λόγος για τον οποίο οι πραγματικοί αριθμοί ονομάζονται και αλλιώς αριθμοί κινητής υποδιαστολής (Floating Point numbers). 2.2.2 Κανονικοποιημένη Επιστημονική Αναπαράσταση. (Normalized Scientific Notation) Από όλες τις -άπειρες- πιθανές μορφές επιστημονικής αναπαράστασης ενός αριθμού, υπάρχει μια μόνο μορφή στην οποία η mantissa αποτελείται από ένα αρχικό μηδενικό (δηλαδή το ακέραιο μέρος της mantissa να είναι μηδέν), υποδιαστολή και μετά ακριβώς από την υποδιαστολή ένα μη μηδενικό ψηφίο -3-
Μετά από το μη μηδενικό ψηφίο αυτό, δεν μας ενδιαφέρει τι υπάρχει στο υπόλοιπο τμήμα της mantissa. Επίσης δεν μας ενδιαφέρει καθόλου ο εκθέτης. Η μορφή αυτή ονομάζεται κανονικοποιημένη μορφή της επιστημονικής αναπαράστασης. Έτσι, η κανονικοποιημένη επιστημονική αναπαράσταση των αριθμών 1500 και 17,3 που είδαμε στα δυο προηγούμενα παραδείγματα είναι αντίστοιχα 0,15E4 και 0,173E2 2.2.3. Τρόπος αποθήκευσης ενός αριθμού τύπου Πραγματικός (Real) Η αποθήκευση ενός αριθμού τύπου Real στη μνήμη του ηλεκτρονικού υπολογιστή, γίνεται μετατρέποντάς τον αριθμό αυτό σε κανονικοποιημένη επιστημονική μορφή και εν συνεχεία αποθηκεύοντας ξεχωριστά δυο ακέραιους αριθμούς. Ο πρώτος ακέραιος περιέχει τα ψηφία που ακολουθούν την υποδιαστολή στην -κανονικοποιημένη- mantissa, και έχει το πρόσημό της, ενώ ο δεύτερος περιέχει τον εκθέτη. Έτσι, συνεχίζοντας τα δυο προηγούμενα παραδείγματα, ο αριθμός 1500 θα αποθηκευτεί στον ηλεκτρονικό υπολογιστή σαν το ζεύγος των ακεραίων [15 4] ενώ ο αριθμός 17,3 σαν [173 2] (γιατί;). Μερικά ακόμα παραδείγματα Διάφορες μορφές Κανονικο Ζεύγος Αριθμός επιστημονικής αναπαράστασης ποιημενη Ακεραίων 3,14159 3,14159E0 314,1590E-2 0,0314159E2 0,314159E1 314159 1-2000 -2,0E3-0,2E4-20000.0E-1-0,2E4-2 4 0,0001 1.0E-4 0,01E-2 1000,0E-7 0,1E-3 1-3 Αντίστροφο παράδειγμα. Ένας αριθμός τύπου Real είναι αποθηκευμένος σαν το ζεύγος ακεραίων [ -25 1]. Επομένως η κανονικοποιημένη του μορφή είναι -0,25E2, ή αλλιώς - 0,25 x 10 1 δηλαδή πρόκειται για τον αριθμό 2,5 2.2.4. Περιοχή και ακρίβεια αναπαράστασης Πραγματικού αριθμού (Real) Όπως ακριβώς συμβαίνει με τον τύπο Ακέραιος, ο ηλεκτρονικός υπολογιστής μπορεί να αναπαραστήσει (και επομένως να αναγνωρίσει) μόνο ένα πεπερασμένο υποσύνολο του συνόλου των πραγματικών αριθμών της άλγεβρας. -4-
Η περιοχή των πραγματικών αριθμών που αναγνωρίζονται από τον ηλεκτρονικό υπολογιστή εξαρτάται από την περιοχή τιμών που μπορεί να πάρει ο ακέραιος εκθέτης. Συνήθως διατίθεται 1 byte (8 bits) για την αποθήκευση του εκθέτη, πράγμα που σημαίνει ότι ο η περιοχή τιμών του εκθέτη είναι από 128 μέχρι και 127 ( 2 8 =256 διαφορετικές τιμές). Αυτό πρακτικά σημαίνει ότι μπορούμε να έχουμε πραγματικούς αριθμούς (θετικούς και αρνητικούς) τόσο μεγάλους όσο και το 10 127 και τόσο κοντά στο μηδέν όσο και το 10-128. Βέβαια, για να αναπαραστήσουμε πλήρως τόσο μεγάλους (ή τόσο κοντά στο μηδέν) αριθμούς θα χρειαζόταν να αποθηκεύσουμε μια mantissa με περίπου 128 δεκαδικά ψηφία. Αυτό θα σήμαινε ότι θα έπρεπε να διαθέσουμε πολλές δεκάδες bytes, δεκάδες πράγμα ασύμφορο. Στην πραγματικότητα διαθέτουμε συνήθως 3 bytes (24 bits) για την αποθήκευση της mantissa. Αυτό πρακτικά σημαίνει ότι στην mantissa αποθηκεύονται μόνο τα πρώτα 6-7 σημαντικά δεκαδικά ψηφία ενός πραγματικού αριθμού, δηλαδή όχι ακριβώς ο ίδιος ο αριθμός αλλά μια αρκετά ακριβής προσέγγισή του. Έτσι π.χ. δεν μπορούμε να αποθηκεύσουμε πλήρως κάποιον πραγματικό αριθμό με πολλά δεκαδικά ψηφία όπως τον 0,123456789012345, αλλά αντί γι αυτόν αποθηκεύουμε τον αριθμό 0,1234567 που αποτελεί μια καλή προσέγγισή του. Το ίδιο συμβαίνει και με τους πολύ μεγάλους αριθμούς όπως π.χ. ένα ποσόν 1.234.567.890 δρχ. που θα αποθηκευτεί σαν 1.234.567.000 δρχ. (χάνουμε τις 890 δραχμές, που είναι μάλλον ασήμαντες όταν αναφερόμαστε σε ποσά δισεκατομμυρίων). Έτσι λοιπόν, όταν αποθηκεύουμε αριθμούς τύπου Real έχουμε τόσο πεπερασμένη ακρίβεια, η οποία εξαρτάται από το μέγεθος της mantissa, όσο και πεπερασμένη περιοχή μεγέθους η οποία εξαρτάται από το μέγεθος του εκθέτη. Πάντως αν σε κάποιες επιστημονικές ή μαθηματικές εφαρμογές απαιτείται ιδιαίτερη ακρίβεια (πέρα δηλαδή από τα 6-7 δεκαδικά ψηφία), μπορεί να χρησιμοποιηθεί εναλλακτικά ένας άλλος τύπος πραγματικών αριθμών που ονομάζεται Διπλής Ακρίβειας (Double Precision) ο οποίος, έχοντας μεγαλύτερη mantissa, παρέχει ακρίβεια 10-12 δεκαδικών ψηφίων. 2.2.5. Πράξεις που ορίζονται στον πάνω τύπο Πραγματικοί (Real) Οι σημαντικότερες πράξεις που ορίζονται πάνω στους πραγματικούς και των οποίων τα αποτελέσματα ανήκουν επίσης στους πραγματικούς είναι η πρόσθεση ( < πραγματικός> + < πραγματικός > = < πραγματικός > ), η αφαίρεση ( < πραγματικός > - < πραγματικός > = < πραγματικός > ), ο πολλ/σμός ( < πραγματικός > x < πραγματικός > = < πραγματικός > ), η διαίρεση ( < πραγματικός > / < πραγματικός > = < πραγματικός> ), -5-
η ύψωση σε δύναμη ( < πραγματικός> < πραγματικός> = < πραγματικός> ) Θα πρέπει να σημειωθεί ότι η πρόσθεση, αφαίρεση, πολλαπλασιασμός και διαίρεση πραγματικών υλοποιούνται στον ηλεκτρονικό υπολογιστή με εντελώς διαφορετικές (και αρκετά περισσότερο περίπλοκες) διαδικασίες από τις αντίστοιχες πράξεις των ακεραίων. Ας μην ξεχνάμε άλλωστε ότι η εσωτερική αναπαράσταση των πραγματικών αριθμών στον ηλεκτρονικό υπολογιστή είναι -όπως διαπιστώσαμε- πιο περίπλοκη από την αντίστοιχη για τους ακέραιους. 2.3. Χαρακτήρες (Characters) Κάθε κείμενο που επεξεργάζεται ένας ηλεκτρονικός υπολογιστής (όπως και αυτό που διαβάζετε τώρα) αποτελείται από ένα σχετικά μικρό σε ποικιλία σύνολο διαφορετικών συμβόλων που συνδυάζονται μεταξύ τους για να δημιουργήσουν τις λέξεις, τις παραγράφους και τελικά το ίδιο το κείμενο. Τα σύμβολα αυτά ονομάζονται χαρακτήρες και αποτελούν έναν ακόμη απλό τύπο δεδομένων. Ο απλός τύπος δεδομένων Χαρακτήρες περιλαμβάνει το σύνολο όλων των χαρακτήρων που μπορεί να αναγνωρίσει (και κατά συνέπεια να επεξεργαστεί) ο ηλεκτρονικός υπολογιστής. Στο σύνολο αυτό ανήκουν όλα τα γράμματα της Αγγλικής αλφαβήτου ( A, a, B, b, C, c ), τα ψηφία 0, 1, 2.. 9, καθώς και ένα πλήθος από ειδικά σύμβολα όπως +, -, =, /,?,!, $, % κ.λ.π. Κάθε σύμβολο χαρακτηρίζεται από ένα μοναδικό κωδικό αριθμό (από το 0 έως και το 255). Η κωδικοποίηση αυτή είναι γνωστή και σαν Κώδικας ASCII, (προφέρεται άσκι) και είναι κοινή για κάθε τύπο υπολογιστή σε αυτόν τον πλανήτη. Ο Κώδικας ASCII (από τα αρχικά American Standard Code for Information Interchange) είναι ένας πίνακας 256 θέσεων (αριθμημένων από 0 έως 255) σε κάθε θέση του οποίου υπάρχει ένας συγκεκριμένος χαρακτήρας. Οι πρώτες 32 θέσεις (0-31) περιέχουν ειδικούς χαρακτήρες ελέγχου οι οποίοι δεν εμφανίζονται στην οθόνη (Enter, Backspace, Tab, Esc). Οι επόμενες θέσεις μέχρι και το μέσον του πίνακα (32-127) περιέχουν το αγγλικό αλφάβητο, τα ψηφία 0-9 και ένα πλήθος από ειδικά σύμβολα όπως αυτά που είδαμε παραπάνω. Οι υπόλοιπες 128 θέσεις (128-255) δεν περιέχουν πάντα τα ίδια σύμβολα, αλλά, ανάλογα με την γεωγραφική περιοχή που βρίσκεται ο ηλεκτρονικός υπολογιστής κάποια εξειδικευμένα σύμβολα απαραίτητα για να γραφτούν κείμενα σε άλλη γλώσσα εκτός της αγγλικής. Στην Ελλάδα π.χ. στις θέσεις 128 255 του κωδικού ASCII υπάρχουν τα Ελληνικά. -6-
Οι πρώτες 128 θέσεις του Κώδικα ASCII, κοινές για όλες τις γεωγραφικές περιοχές είναι: 0 16 32 space 48 0 64 @ 80 P 96 112 p 1 17 33! 49 1 65 A 81 Q 97 a 113 q 2 18 34 50 2 66 B 82 R 98 b 114 r 3 19 35 # 51 3 67 C 83 S 99 c 115 s 4 20 36 $ 52 4 68 D 84 T 100 d 116 t Ειδικοί χαρακτήρες ελέγχου Ειδικοί χαρακτήρες ελέγχου 5 21 37 % 53 5 69 E 85 U 101 e 117 u 6 22 38 & 54 6 70 F 86 V 102 f 118 v 7 23 39 55 7 71 G 87 W 103 g 119 w 8 24 40 ( 56 8 72 H 88 X 104 h 120 x 9 25 41 ) 57 9 73 I 89 Y 105 i 121 y 10 26 42 * 58 : 74 J 90 Z 106 j 122 z 11 27 43 + 59 ; 75 K 91 [ 107 k 123 { 12 28 44, 60 < 76 L 92 \ 108 l 124 13 29 45-61 = 77 M 93 ] 109 m 125 } 14 30 46. 62 > 78 N 94 ^ 110 n 126 «15 31 47 / 63? 79 O 95 _ 111 o 127 2.3.1. Πράξεις που ορίζονται στον πάνω τύπο Χαρακτήρας (Character) Υπάρχουν δυο πράξεις που ορίζονται στο σύνολο των χαρακτήρων και μας δίνουν σαν αποτέλεσμα πάλι κάποιον χαρακτήρα. Είναι οι πράξεις Προηγούμενος (Prev) και Επόμενος (Next) χαρακτήρας, που μας δίνουν τον χαρακτήρα που βρίσκεται στην προηγούμενη η αντίστοιχα επόμενη θέση του πίνακα ASCII. π.χ. το αποτέλεσμα της πράξης Prev( D ) είναι C ενώ της πράξης Next( % ) είναι & (δες τον πίνακα ASCII για επαλήθευση). Εκτός από τις δυο αυτές πράξεις υπάρχουν και άλλες πράξεις που ορίζονται μεν πάνω στο σύνολο των χαρακτήρων αλλά το αποτέλεσμά τους δεν είναι χαρακτήρας. H πιο χαρακτηριστική είναι η πράξη της συνένωσης (πρόσθεσης) χαρακτήρων, το αποτέλεσμα της οποίας είναι η δημιουργία ακολουθιών χαρακτήρων (strings) που θα δούμε πιο κάτω. π.χ. T + e + s + t = Test Ακόμα ας αναφέρουμε και τις πράξεις Ord και Char. Η πρώτη εφαρμόζεται πάνω σε ένα χαρακτήρα και μας δίνει σαν αποτέλεσμα έναν ακέραιο αριθμό που φανερώνει την θέση του συγκεκριμένου χαρακτήρα στον πίνακα ASCII π.χ. Ord( A ) είναι 65. -7-
Η δεύτερη πράξη κάνει ακριβώς το αντίστροφο. Δηλαδή εφαρμόζεται πάνω σ έναν ακέραιο αριθμό και δίνει σαν αποτέλεσμα τον χαρακτήρα που αντιστοιχεί στον αριθμό αυτό σύμφωνα με τον πίνακα ASCII. π.χ. Char(65) είναι A 2.3.2 Ακολουθίες Χαρακτήρων (Character Strings) Μια ακολουθία χαρακτήρων (character string ή σκέτο string), αποτελείται όπως φανερώνει και το όνομά της από μια σειρά διαδοχικών χαρακτήρων. Σύμφωνα με τον ορισμό αυτό, κάθε λέξη, πρόταση, γενικά κάθε κείμενο είναι μια ακολουθία χαρακτήρων. Μια ακολουθία χαρακτήρων δεν μπορεί να χαρακτηριστεί σαν στοιχειώδης τύπος δεδομένων αφού αποτελείται από δεδομένα απλούστερου τύπου (χαρακτήρες). Επειδή όμως η ακολουθία χαρακτήρων αποτελεί έναν ιδιαίτερα χρήσιμο τύπο δεδομένων συνήθως συγκαταλέγεται ανάμεσα στους απλούς τύπους δεδομένων, πλάι στον τύπο των χαρακτήρων. Οι πράξεις πάνω στον αυτόν είναι αρκετές. Ενδεικτικά αναφέρουμε την συνένωση ακολουθιών χαρακτήρων, τον εντοπισμό ενός ή περισσοτέρων χαρακτήρων μέσα σε μια ακολουθία χαρακτήρων, την αποκοπή τμήματος από την αρχή, τη μέση ή το τέλος μιας ακολουθίας χαρακτήρων, και πολλές άλλες. 2.4. Λογικοί (Logical ή Boolean) Ο τύπος αυτός περιέχει όλες τις τιμές που μπορεί να πάρει μια λογική πρόταση. Αυτές είναι δυο όλες κι όλες. Η τιμή true (αλήθεια / σωστό) και η τιμή false (ψέματα / λάθος). Οι πιο συνηθισμένες πράξεις που εφαρμόζονται πάνω σε λογικές τιμές και παράγουν επίσης λογικά αποτελέσματα είναι οι AND (λογικό και), OR (λογικό είτε), NOT (λογική άρνηση) και XOR (λογικό αποκλειστικό είτε). Στον επόμενο πίνακα βλέπουμε όλα τα πιθανά αποτελέσματα των παραπάνω λογικών πράξεων Σημειώστε ότι οι πράξεις AND, OR και XOR χρειάζονται από δυο λογικές μεταβλητές, ενώ η πράξη NOT χρειάζεται μόνο μια. -8-
Τιμή πρώτης Τιμή δεύτερης Λογική πράξη μεταβλητής μεταβλητής AND OR NOT(*) XOR True True True True False False True False False True False True False True False True True True False False False False True False (*) Εφαρμογή στην πρώτη μεταβλητή μόνο Παράδειγμα: Το αποτέλεσμα της πράξης True XOR False είναι True Οι τιμές True και False μπορούν ακόμη να προκύψουν και ως αποτέλεσμα μιας σειράς πράξεων που ονομάζονται πράξεις σύγκρισης ( <, >, =, <=, >=, <> κ.λ.π. ) οι οποίες εφαρμόζονται μεν σε άλλες κατηγορίες τύπων δεδομένων (π.χ. ακέραιοι) το αποτέλεσμα όμως που παράγουν είναι λογικός αριθμός. (πχ η σύγκριση 4 < 8 έχει την τιμή true). Παράδειγμα: Το αποτέλεσμα της πράξης (5 > 8) AND (2 <= 7) είναι False 3. Σύνθετοι ή Δομημένοι Τύποι δεδομένων (Structured Data Types) Παράγονται από τους απλούς τύπους δεδομένων και χρησιμοποιούνται για την αποθήκευση και επεξεργασία δεδομένων που έχουν πιο σύνθετη δομή. Οι πιο γνωστοί δομημένοι τύποι δεδομένων είναι: Διανύσματα / Πίνακες (Arrays / Tables) Εγγραφές (Records) Λίστες (Lists) Αρχεία (Files) Χαρακτηριστικό των δομημένων τύπων δεδομένων είναι η μεγάλη ευελιξία στη σύνθεσή τους με δομικά στοιχεία τους να είναι είτε απλοί τύποι δεδομένων (όπως αυτούς που είδαμε πριν από λίγο), είτε άλλοι αρκετά σύνθετοι δομημένοι τύποι δεδομένων. Έτσι, για παράδειγμα μπορούμε να έχουμε πίνακες ακεραίων, αλλά και πίνακες κάθε στοιχείο των οποίων να είναι ένας άλλος πίνακας ή μια εγγραφή. Ας δούμε πιο αναλυτικά καθένα από τους παραπάνω δομημένους τύπους δεδομένων. -9-
3.1. Διανύσματα / Πίνακες (Arrays / Tables) Διάνυσμα είναι ένα πεπερασμένο, διατεταγμένο σύνολο από στοιχεία του ίδιου τύπου, που έχουν κοινό όνομα. Ο όρος διατεταγμένο σημαίνει ότι μπορούμε να προσδιορίσουμε το πρώτο, δεύτερο, τελευταίο στοιχείο του διανύσματος. Τα δεδομένα ενός διανύσματος είναι όλα του ίδιου τύπου π.χ. ακέραιοι, ακολουθίες χαρακτήρων ή και ακόμη άλλα διανύσματα. Ο εντοπισμός ενός συγκεκριμένου στοιχείου κάποιου διανύσματος γίνεται με την βοήθεια του δείκτη (subscript) που είναι ένας ακέραιος αριθμός ο οποίος προσδιορίζει την ακριβή θέση του στοιχείου μέσα στο διάνυσμα. Ο δείκτης γράφεται συνήθως σε παρένθεση δίπλα στο όνομα του διανύσματος. 3.1.1. Μονοδιάστατα διανύσματα / πίνακες (one dimensional arrays / tables) Η πιο απλή μορφή ενός διανύσματος είναι το μονοδιάστατο διάνυσμα. Ένα μονοδιάστατο διάνυσμα 10 θέσεων με όνομα Α θα μπορούσε να παρασταθεί ως εξής: Α(1) Α(2) Α(3) Α(4) Α(5) Α(6) Α(7) Α(8) Α(9) Α(10) Τα στοιχεία ενός διανύσματος μπορεί να είναι ακέραιοι, πραγματικοί, χαρακτήρες ή γενικότερα οποιουδήποτε άλλου απλού ή σύνθετου τύπου. Είναι σημαντικό όμως να κατανοήσουμε ότι όλα ανεξαιρέτως τα στοιχεία είναι του ίδιου τύπου. Αυτό μεταξύ άλλων σημαίνει και ότι κάθε στοιχείο του διανύσματος καταλαμβάνει το ίδιο πλήθος bytes (πχ 1, 2, 4 κλπ) όταν αποθηκεύεται στη μνήμη ενός ηλεκτρονικού υπολογιστή. 3.1.2. Συνάρτηση απεικόνισης διανύσματος (array mapping function) 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 Α(1) Α(2) Α(3) Α(4) Α(5) Α(6) Α(7) Α(8) Α(9) Α(10) Όταν ένα διάνυσμα αποθηκεύεται στη μνήμη του ηλεκτρονικού υπολογιστή, η αποθήκευση γίνεται σε διαδοχικές θέσεις της μνήμης. Αυτό σημαίνει π.χ. ότι το στοιχείο Α(2) θα αποθηκευτεί αμέσως μετά το στοιχείο Α(1) κ.ο.κ. Ανάλογα τώρα με τον τύπο του διανύσματος, κάθε στοιχείο του απαιτεί ένα συγκεκριμένο αριθμό θέσεων μνήμης (bytes) για την αποθήκευσή του. Αν π.χ. έχουμε ένα διάνυσμα ακεραίων κάθε στοιχείο του απαιτεί 2 bytes δηλαδή 2 θέσεις μνήμης. Αν πάλι το κάθε στοιχείο είναι ένας πιο σύνθετος τύπος, πιθανόν να απαιτεί ακόμα περισσότερες θέσεις μνήμης για να αποθηκευτεί (Δεν ξεχνάμε βέβαια ότι όλα τα στοιχεία ενός διανύσματος έχουν τον ίδιο τύπο άρα και τις ίδιες απαιτήσεις μνήμης). -10-
Ας υποθέσουμε ότι ένα μονοδιάστατο διάνυσμα 10 ακεραίων με όνομα Α -ορίζεται σαν Α( 1..10) - είναι αποθηκευμένο στην μνήμη του ηλεκτρονικού υπολογιστή αρχίζοντας από την θέση 100. Αφού το διάνυσμα περιέχει ακέραιους, το κάθε στοιχείο του θα αποθηκευτεί σε 2 διαδοχικές θέσεις μνήμης. Αυτό σημαίνει ότι το στοιχείο Α(1) θα αποθηκευτεί στις θέσεις 100 και 101, το στοιχείο Α(2) θα αποθηκευτεί στις θέσεις 102 και 103 κ.ο.κ. (δες το σχετικό σχήμα). Η διεύθυνση μνήμης από την οποία ξεκινάει η αποθήκευση ενός διανύσματος ονομάζεται Διεύθυνση Βάσης [ΔΒ] (Base Address) και στο παράδειγμά μας έχει την τιμή 100 Πως μπορούμε να βρούμε από ποια θέση μνήμης αρχίζει η αποθήκευση του στοιχείου Α(j) αν γνωρίζουμε i) τον δείκτη j, ii) την διεύθυνση βάσης ΔΒ =100 και iii) το μέγεθος Μ =2 του κάθε στοιχείου; Σκεφτόμαστε ως εξής Το στοιχείο Α(1) αρχίζει από την διεύθυνση ΔΒ (=100) Το στοιχείο Α(2) αρχίζει από την διεύθυνση ΔΒ+Μ (=100 + 2 δηλ. 102) Το στοιχείο Α(3) αρχίζει από την διεύθυνση ΔΒ+2*Μ (=100 + 2 *2 δηλ. 104) Το στοιχείο Α(4) αρχίζει από την διεύθυνση ΔΒ+3*Μ (=100 + 3 *2 δηλ. 106) Επομένως γενικά το στοιχείο Α( j ) αρχίζει από την διεύθυνση ΔΒ + (j-1) * Μ Η παραπάνω σχέση ονομάζεται συνάρτηση απεικόνισης διανύσματος και είναι μια σχέση που υπολογίζει την θέση του στοιχείου Α(j) ενός διανύσματος, αποθηκευμένου στη μνήμη όταν γνωρίζουμε το j, την διεύθυνση βάσης ΔΒ και το μέγεθος Μ του κάθε στοιχείου του διανύσματος. Συνάρτηση Απεικόνισης Μονοδιάστατου Διανύσματος f (j, Μ, ΔΒ) = ΔΒ+(j-1)*Μ Εφαρμογή. Βρείτε την θέση του 5 ου στοιχείου ενός μονοδιάστατου διανύσματος ακεραίων (Μ=2) που είναι αποθηκευμένο στη μνήμη ενός ηλεκτρονικού υπολογιστή αρχίζοντας από την θέση 300. Εφαρμόζοντας την συνάρτηση απεικόνισης μονοδιάστατου διανύσματος παίρνουμε f(5, 2, 300) = 300 + (5-1) * 2 = 308. Επομένως η αποθήκευση του 5 ου στοιχείου του διανύσματος στην μνήμη αρχίζει από την θέση 308. -11-
3.1.3. Δισδιάστατοι πίνακες / διανύσματα (two dimensional arrays ) Ένα δισδιάστατο διάνυσμα, είναι ένα διάνυσμα, κάθε στοιχείο του οποίου είναι ένα άλλο διάνυσμα. Συνήθως εδώ χρησιμοποιούμε περισσότερο τον όρο πίνακας, αν και ο όρος διάνυσμα είναι απόλυτα ισοδύναμος. Β(1,1) Β(1,2) Β(1,3) Β(1,4) Β(2,1) Β(2,2) Β(2,3) Β(2,4) Β(3,1) Β(3,2) Β(3,3) Β(3,4) Β(4,1) Β(4,2) Β(4,3) Β(4,4) Β(5,1) Β(5,2) Β(5,3) Β(5,4) Στο διπλανό σχήμα απεικονίζεται ένας δισδιάστατος πίνακας ακεραίων τιμών, η πρώτη διάσταση του οποίου είναι 5 και η δεύτερη 4. Συμβολίζουμε τον πίνακα Β ως Β ( 1..5, 1..4 ) και λέμε ότι έχει διάσταση 5x4 (5 γραμμές x 4 στήλες). Ποια είναι η συνάρτηση απεικόνισής του; Για να απαντήσουμε σε αυτό το ερώτημα θα πρέπει προηγουμένως να ξεκαθαρίσουμε πως αποθηκεύεται ένας δυσδιάστατος πίνακας στην μνήμη του ηλεκτρονικού υπολογιστή που είναι από την φύση της μονοδιάστατη. Υπάρχουν δυο τεχνικές αποθήκευσης. Αποθήκευση κατά γραμμές: Αποθηκεύουμε την πρώτη γραμμή του πίνακα στην μνήμη σαν να επρόκειτο για ένα μονοδιάστατο διάνυσμα. Στη συνέχεια αποθηκεύουμε την δεύτερη γραμμή, μετά την τρίτη κ.ο.κ. μέχρι να αποθηκεύσουμε και την τελευταία γραμμή. Αποθήκευση κατά στήλες: Αποθηκεύουμε την πρώτη στήλη του πίνακα στην μνήμη σαν να επρόκειτο για ένα μονοδιάστατο διάνυσμα. Στη συνέχεια αποθηκεύουμε την δεύτερη στήλη, μετά την τρίτη κ.ο.κ. μέχρι να αποθηκεύσουμε και την τελευταία στήλη. Αποθήκευση κατά γραμμές Αποθήκευση κατά στήλες Επομένως, οι συναρτήσεις απεικόνισης είναι διαφορετικές για κάθε περίπτωση. Θα προσπαθήσουμε να κατασκευάσουμε και τις δυο. -12-
(α) (β) 500 500 Β(1,1) Β(1,1) 502 502 Β(1,2) Β(2,1) 504 504 Β(1,3) Β(3,1) 506 506 Β(1,4) Β(4,1) 508 508 Β(2,1) Β(5,1) 510 510 Β(2,2) Β(1,2) 512 512 Β(2,3) Β(2,2) 514 514 Β(2,4) Β(3,2) 516 516 Β(3,1) Β(4,2) 518 518 Β(3,2) Β(5,2) 520 520 Β(3,3) Β(1,3) 522 522 Β(3,4) Β(2,3) 524 524 Β(4,1) Β(3,3) 526 526 Β(4,2) Β(4,3) 528 528 Β(4,3) Β(5,3) 530 530 Β(4,4) Β(1,4) 532 532 Β(5,1) Β(2,4) 534 534 Β(5,2) Β(3,4) 536 536 Β(5,3) Β(4,4) 538 538 Β(5,4) Β(5,4) Αποθήκευση Αποθήκευση κατά γραμμές κατά στήλες ( και στις δυο περιπτώσεις i=1..5, j=1..4 ) Ας Παρατηρήσουμε αρχικά στο διπλανό σχήμα πως ακριβώς θα γίνει η αποθήκευση (α) κατά γραμμές και (β) κατά στήλες για τον πίνακα του παραδείγματός μας, αν η αποθήκευση αρχίσει από την θέση μνήμης 500 (διεύθυνση βάσης). Η συνάρτηση απεικόνισης εδώ έχει δυο μεταβλητές i και j δεδομένου ότι μας ενδιαφέρει η θέση του στοιχείου Β(i,j). Οι υπόλοιπες - γνωστές -παράμεροι είναι ΔΒ = 500 (η διεύθυνση βάσης) Μ = 2 (μέγεθος κελιών) i_max = 5 (μέγιστη διάσταση του i) j_max = 4 (μέγιστη διάσταση του j) Α. Αποθήκευση κατά γραμμές Για να εντοπίσουμε ένα στοιχείο που βρίσκεται στην γραμμή i, θα πρέπει αρχικά να προσπεράσουμε τις προηγούμενες i-1 γραμμές, η καθεμιά από τις οποίες έχει j_max στοιχεία, θα πρέπει δηλαδή να μετακινηθούμε j_max * (i-1) στοιχεία. Επειδή τώρα το κάθε στοιχείο του πίνακα καταλαμβάνει Μ διαδοχικές θέσεις μνήμης, ο συνολικός αριθμός θέσεων μνήμης που θα πρέπει να μετακινηθούμε για να βρεθούμε στην αρχή της γραμμής που μας ενδιαφέρει είναι j_max * (i-1)* Μ Βρισκόμενοι τώρα στην αρχή της γραμμής i, θα πρέπει να προσπεράσουμε και τα j-1 προηγούμενα στοιχεία πάνω στη γραμμή, έτσι ώστε να βρεθούμε τελικά στο στοιχείο j. Αυτό σημαίνει ότι θα πρέπει να μετακινηθούμε (j-1) * M θέσεις ακόμα πιο κάτω. Αν προσθέσουμε αυτή την μετακίνηση στην αρχική μας και λάβουμε υπόψη την διεύθυνση βάσης ΔΒ απ όπου οφείλουμε να ξεκινήσουμε, ο τύπος για τη συνάρτηση απεικόνισης δισδιάστατου πίνακα αποθηκευμένου κατά γραμμές προκύπτει: -13-
Συνάρτηση απεικόνισης δυσδιάστατου πίνακα αποθηκευμένου κατά γραμμές f (i,j,μ,δβ) = ΔΒ + (j_max)*(i-1)*μ + (j-1)*m όπου ΔΒ : η διεύθυνση βάσης της αποθήκευσης του πίνακα Μ : θέσεις μνήμης που καταλαμβάνει κάθε κελί του πίνακα (μέγεθος κελιού) i_max μέγιστη τιμή που λαμβάνει η πρώτη διάσταση i του πίνακα j_max μέγιστη τιμή που λαμβάνει η δεύτερη διάσταση j του πίνακα Εφαρμογή. Ένας δυσδιάστατος πίνακας Β ( 1..5, 1..4 ) ακεραίων (Μ=2) είναι αποθηκευμένος κατά γραμμές στη μνήμη ενός ηλεκτρονικού υπολογιστή αρχίζοντας από την θέση 500. Βρείτε την θέση του στοιχείου B(3,2). Εφαρμόζοντας τη συνάρτηση απεικόνισης δυσδιάστατου πίνακα αποθηκευμένου κατά γραμμές παίρνουμε ( εδώ j_max = 4) f(3, 2, 2, 500) = 500 + 4 * (3-1) * 2 + (2-1) * 2 = 500 + 4 *4 + 2 = 500+18 = 518. Πράγματι, ελέγχοντας το σχήμα στην προηγούμενη σελίδα προκύπτει ότι το στοιχείο Β(3,2) αρχίζει όντως από στη θέση μνήμης 518. B. Αποθήκευση κατά στήλες Σκεπτόμαστε και εργαζόμαστε με τον ίδιο ακριβώς τρόπο και καταλήγουμε στην αντίστοιχη συνάρτηση απεικόνισης δυσδιάστατου πίνακα αποθηκευμένου κατά στήλες Συνάρτηση απεικόνισης δυσδιάστατου πίνακα αποθηκευμένου κατά στήλες f (i,j,μ,δβ) = ΔΒ + (i_max)*(j-1)*μ + (i-1)*m όπου ΔΒ : η διεύθυνση βάσης της αποθήκευσης του πίνακα Μ : θέσεις μνήμης που καταλαμβάνει κάθε κελί του πίνακα (μέγεθος κελιού) i_max μέγιστη τιμή που λαμβάνει η πρώτη διάσταση i του πίνακα j_max μέγιστη τιμή που λαμβάνει η δεύτερη διάσταση j του πίνακα Εφαρμογή. Ένας δυσδιάστατος πίνακας Β ( 1..5, 1..4 ) ακεραίων (Μ=2) είναι αποθηκευμένος κατά στήλες στη μνήμη ενός ηλεκτρονικού υπολογιστή αρχίζοντας από την θέση 500. Βρείτε την θέση του στοιχείου B(4,3). -14-
Εφαρμόζοντας τη συνάρτηση απεικόνισης δυσδιάστατου πίνακα αποθηκευμένου κατά γραμμές παίρνουμε ( εδώ i_max = 5) f(4, 3, 2, 500) = 500 + 5 * (3-1) * 2 + (4-1) * 2 = 500 + 5*4 + 6 = 500+26 = 526. Πράγματι, ελέγχοντας το σχήμα στην προηγούμενη σελίδα προκύπτει ότι το στοιχείο Β(4,3) αρχίζει όντως από στη θέση 526. 3.1.4. Πολυδιάστατοι πίνακες Προκύπτουν ως γενίκευση του ορισμού των δυσδιάστατων πινάκων Ένας πολυδιάστατος πίνακας αποθηκεύεται στην μνήμη του ηλεκτρονικού υπολογιστή σαν μια σειρά μονοδιάστατων πινάκων, ενώ οι συναρτήσεις απεικόνισής τους ορίζονται με ανάλογο τρόπο. 3.1.5 Ειδικές κατηγορίες δυσδιάστατων πινάκων x o o o o o x o o o o o x o o o o o x o o o o o x x o o o o x x o o o x x x o o x x x x o x x x x x x x x x x o x x x x o o x x x o o o x x o o o o x Διαγώνιοι πίνακες. Είναι πίνακες των οποίων όλα τα στοιχεία που δεν ανήκουν στην κύρια διαγώνιο είναι μηδενικά. (Τυπικός ορισμός: Δ διαγώνιος όταν Δ(i, j)=0 για i <> j ) Προφανώς δεν έχει νόημα η αποθήκευση των στοιχείων που βρίσκονται έξω από την κύρια διαγώνιο. Κάτω τριγωνικοί πίνακες. Είναι πίνακες των οποίων όλα τα στοιχεία πάνω από την κύρια διαγώνιο είναι μηδενικά. (Τυπικός ορισμός: Κ κάτω τριγωνικός όταν Κ(i, j)=0 για i < j ) Προφανώς δεν έχει νόημα η αποθήκευση των στοιχείων που βρίσκονται πάνω από την κύρια διαγώνιο. Πάνω τριγωνικοί πίνακες. Είναι πίνακες των οποίων όλα τα στοιχεία κάτω από την κύρια διαγώνιο είναι μηδενικά. (Τυπικός ορισμός: Π πάνω τριγωνικός όταν Π(i, j)=0 για i > j ) Προφανώς δεν έχει νόημα η αποθήκευση των στοιχείων που βρίσκονται κάτω από την κύρια διαγώνιο. Λόγω του ιδιαίτερου σχήματός τους οι τρεις παραπάνω κατηγορίες δυσδιάστατων πινάκων αποθηκεύονται με ειδικό τρόπο. Προσπαθήστε να υπολογίσετε τις συναρτήσεις απεικόνισης τους. -15-
Αραιοί Πίνακες (Sparse matrices). Πρόκειται για δυσδιάστατους πίνακες συνήθως αρκετά μεγάλων διαστάσεων, των οποίων τα περισσότερα στοιχεία είναι μηδενικά, ενω τα ελάχιστα μη μηδενικά στοιχεία έχουν τυχαία κατανομή. Και εδώ επίσης δεν έχει νόημα η αποθήκευση των μηδενικών, οπότε αναπτύσσονται ειδικές τεχνικές αποθήκευσης. Η πιο γνωστή από αυτές είναι η λεγόμενη αποθήκευση τριάδων. Σύμφωνα με αυτήν την τεχνική για κάθε μη-μηδενικό στοιχείο S(i, j) ενός αραιού πίνακα αποθηκεύεται μια τριάδα τιμών [ i, j, S(i, j)], δηλαδή οι δυο δείκτες (γραμμή, στήλη) που καθορίζουν τη θέση του στοιχείου μέσα στον πίνακα καθώς και η τιμή του. Στις τριάδες που δημιουργούνται, προστίθεται συνήθως στην αρχή- ακόμη μια όπου αποθηκεύεται η αρχική διάσταση του αραιού πίνακα. 1 2 3 4 5 6 7 1 0 0 0 0 0 0 0 2 0 0 45 0 0 0 0 3 0 0 0 0 0 0 0 4 0 0 0 73 0 0 0 5 0 0 0 0 0 0 0 6 0-5 0 0 0 29 0 7 0 0 0 0 14 0 0 8 0 0 0 0 0 0 0 Παράδειγμα: Ο αραιός πίνακας Α αριστερά, παρόλο που έχει διάσταση 8x7, στην ουσία περιέχει μόνο τις παρακάτω μη- μηδενικές τιμές Στη θέση Α(2,3) την τιμή 45 Στη θέση Α(4,4) την τιμή 73 Στη θέση Α(6,2) την τιμή -5 Στη θέση Α(6,6) την τιμή 29 Στη θέση Α(7,5) την τιμή 14 1 8 7 0 2 2 3 45 3 4 4 73 4 6 2-5 5 6 6 29 6 7 5 14 Επομένως ο πίνακας Α μπορεί να συμπυκνωθεί σε ένα πίνακα Β μόλις 6 τριάδων (6x3), όπου η πρώτη τριάδα περιέχει την διάσταση του αρχικού πίνακα στις στήλες 1 και 2 (και ένα μηδενικό στην τρίτη στήλη), ενώ οι υπόλοιπες 5 τριάδες περιέχουν τις θέσεις και τις τιμές των 5 μημηδενικών στοιχείων του πίνακα Α. 3.2 Εγγραφές (Records) Πολλές φορές σ ένα πρόγραμμα χρειαζόμαστε ένα τρόπο για να ομαδοποιήσουμε δεδομένα τα οποία αν και διαφορετικού τύπου χρησιμοποιούνται συγκεντρωτικά για να αναπαραστήσουν μια σύνθετη πληροφορία. Πχ για να περιγράψουμε μια ταχυδρομική διεύθυνση χρειαζόμαστε τα εξής στοιχεία/πεδία : Οδό, Αριθμό, Πόλη, Χώρα και Ταχυδρομικό Κώδικα. Παρατηρούμε ότι κάποια από αυτά είναι πεδία κειμένου και κάποια άλλα αριθμητικά πεδία. Για να χειριζόμαστε τέτοιες καταστάσεις, χρησιμοποιούμε ενα δομημένο τύπο δεδομένων που ονομάζεται εγγραφή -16-
Ονομάζουμε εγγραφή (record) μια ομαδοποιημένη συλλογή στοιχείων τα οποία δεν είναι (υποχρεωτικά) του ίδιου τύπου μεταξύ τους. Τα στοιχεία μιας εγγραφής ονομάζονται πεδία (fields) ή μέλη (members). Η βασική διαφορά των εγγραφών από τους πίνακες είναι ότι, ενας πίνακας περιέχει πάντα στοιχεία του ίδιου τύπου, ενώ μια εγγραφή μπορεί να περιέχει και κατά κανόνα περιέχειστοιχεία διαφορετικού τύπου. Ανάλογα με τη γλώσσα προγραμματισμού, ο τύπος μιας εγγραφής δηλώνεται κάπως έτσι: TYPE <ΟΝΟΜΑ ΕΓΓΡΑΦΗΣ> = RECORD <ΟΝΟΜΑ ΠΕΔΙΟΥ 1>: <ΤΥΠΟΣ ΠΕΔΙΟΥ 1>; <ΟΝΟΜΑ ΠΕΔΙΟΥ 2>: <ΤΥΠΟΣ ΠΕΔΙΟΥ 2>;... <ΟΝΟΜΑ ΠΕΔΙΟΥ N>: <ΤΥΠΟΣ ΠΕΔΙΟΥ N>; END; Παραδείγματα δήλωσης ενός τύπου εγγραφής σε διαφορετικές γλώσσες προγραμματισμού Pascal FORTRAN Visual Basic type PRODUCT = record ID: Integer; Name, Model : String; Cost, Price : Real; end; STRUCTURE /PRODUCT/ INTEGER ID CHARACTER*16 NAME CHARACTER*8 MODEL REAL COST REAL PRICE END STRUCTURE Type PRODUCT ID As Integer; Name, Model As String; Cost, Price As Real; End Type Η δήλωση των τύπων των εγγραφών γίνεται στην κορυφή του προγράμματος, πριν από τη δήλωση των μεταβλητών. Κάθε τύπος εγγραφής που δηλώνουμε όπως παραπάνω, αποτελεί έναν νέο τύπο δεδομένων για το πρόγραμμά μας, κατά συνέπεια μπορούμε να δηλώσουμε μια ή περισσότερες μεταβλητές αυτού του τύπου. Για παράδειγμα με την επόμενη γραμμή δήλωσης μεταβλητών: CURRENT, PRIOR, STOCK(10) as PRODUCT δηλώνονται 2 μεταβλητές τύπου PRODUCT και ενας πίνακας 10 θέσεων τύπου PRODUCT Για να αναφερθούμε σε ένα συγκεκριμένο πεδίο μιας εγγραφής γράφουμε το όνομα της εγγραφής ακολουθούμενο από μια τελεία (.) και το όνομα του πεδίου. Δείτε τα επόμενα παραδείγματα CURRENT.COST = 120 PRIOR.MODEL = ZX127 TOTAL = STOCK(3).Price + STOCK(8).Price CURRENT.Price Στο τελευταίο παράδειγμα υποθέστε ότι η TOTAL είναι μια απλή μεταβλητή τύπου Real. -17-
3.3 Λίστες (Lists) Μια λίστα (κάποιες φορές ονομάζεται και ακολουθία) είναι ένας δομημένος τύπος δεδομένων που υλοποιεί μία διατεταγμένη συλλογή από τιμές, όπου η ίδια τιμή μπορεί να εμφανίζεται περισσότερες από μία φορές. Κάθε στιγμιότυπο μιας τιμής της λίστας καλείται συνήθως αντικείμενο ή στοιχείο της λίστας. Αν η ίδια τιμή εμφανίζεται πολλές φορές, κάθε εμφάνισή της θεωρείται ένα διακριτό αντικείμενο. Διακρίνουμε δυο βασικούς τύπους από λίστες Στατικές Λίστες Δυναμικές (ή Συνδεδεμένες) λίστες Οι στατικές λίστες επιτρέπουν μόνο τον έλεγχο και ενημέρωση των τιμών τους, σε αντίθεση με τις δυναμικές λίστες που επιτρέπουν την εισαγωγή, αντικατάσταση ή εξαγωγή των αντικειμένων τους. Κάποιες γλώσσες προγραμματισμού παρέχουν υποστήριξη για λίστες ως τύπο δεδομένων, και έχουν ειδική σύνταξη και σημασιολογία αλλά και λειτουργίες πάνω σε αυτές. Μια λίστα συχνά κατασκευάζεται γράφοντας τα αντικείμενά της στη σειρά, χωρισμένα με κόμμα, ερωτηματικό ή κενό, ανάμεσα σε ένα ζευγάρι οριοθετών όπως παρενθέσεις '()', αγκύλες, '[]', άγκιστρα '{}' ή γωνιακές αγκύλες '<>'. Ορισμένες γλώσσες μπορεί να επιτρέπουν τύπους λιστών να δεικτοδοτούνται ή να διαχωρίζονται όπως οι πίνακες 3.3.1 Χαρακτηριστικές Ιδιότητες Λίστας Το μέγεθος της λίστας. Υποδεικνύει πόσα στοιχεία περιέχει η λίστα. Ο Τύπος των στοιχείων της λίστας. Όλα τα στοιχεία μιας λίστας έχουν τον ίδιο τύπο, ο οποίος αν και μπορεί να είναι οποιοσδήποτε συνήθως είναι τύπος εγγραφής (record) Κάθε στοιχείο της λίστας έχει κάποιο δείκτη. Το πρώτο στοιχείο της λίστας συνήθως έχει δείκτη 0 ή 1 (ή κάποιον προκαθορισμένο ακέραιο). Γειτονικά στοιχεία έχουν δείκτες που είναι κατά 1 μεγαλύτεροι από το προηγούμενό τους στοιχείο. Το τελευταίο στοιχείο έχει δείκτη: <αρχικός δείκτης> + <μέγεθος λιστας> 1. Είναι εφικτό να ανακτήσεις ένα στοιχείο με συγκεκριμένο δείκτη. Είναι εφικτό να διατρέξεις τη λίστα σε αύξουσα σειρά των δεικτών της. Είναι εφικτό να αλλάξεις την τιμή ενός στοιχείου σε μια συγκεκριμένη θέση, χωρίς να επηρεάσεις τα υπόλοιπα στοιχεία της λίστας. Είναι εφικτό να εισάγεις ένα στοιχείο σε μια συγκεκριμένη θέση. Οι δείκτες των μεγαλύτερων στοιχείων αυξάνονται κατά 1. -18-
Είναι εφικτό να διαγράψεις ένα στοιχείο σε μια συγκεκριμένη θέση. Οι δείκτες των μεγαλύτερων στοιχείων μειώνονται κατά 1. 3.3.2. Υλοποίηση Συνδεδεμένης Λίστας Οι λίστες τυπικά υλοποιούνται είτε ως συνδεδεμένες λίστες (απλά ή διπλά) είτε ως πίνακες μεταβλητού μεγέθους (δυναμικοί πίνακες). Ο συνήθης τρόπος υλοποίησης λιστών, που προέρχεται από τη γλώσσα προγραμματισμού Lisp, είναι κάθε στοιχείο της λίστας να περιέχει εκτός από τα δεδομένα του δείκτη ή δείκτες προς τα γειτονικά του στοιχεία. Αυτό έχει ως αποτέλεσμα τη δημιουργία μίας συνδεδεμένης λίστας Απλά Συνδεδεμένες Λίστες Κάθε στοιχείο μιας απλά συνδεδεμένης λίστας, εκτός από το/τα πεδία δεδομένων, περιλαμβάνει και ένα ακόμα πεδίο (συνήθως αναφέρεται ως πεδίο Next) το οποίο περιέχει την αρχική διεύθυνση της μνήμης του επόμενου στοιχείου της λίστας. Διπλά Συνδεδεμένες Λίστες Κάθε στοιχείο μιας διπλά συνδεδεμένης λίστας, εκτός από το/τα πεδία δεδομένων, περιλαμβάνει και δυο ακόμα πεδία (συνήθως αναφέρονται ως Prev και Next) τα οποία περιέχουν αντίστοιχα τις αρχικές διευθύνσεις μνήμης του προηγούμενου και επόμενου στοιχείου της λίστας. Κυκλικά Συνδεδεμένες Λίστες Το τελευταίο στοιχείο μιας λίστας συνήθως συνδέεται σε ένα ειδικό κόμβο που ονομάζεται Null και είναι μια ειδική τιμή που χρησιμοποιείται ως ένδειξη ότι δεν υπάρχουν άλλα στοιχεία. Μια λιγότερο συχνή περίπτωση είναι σύνδεση του τελευταίου στοιχείου μιας λίστας με το πρώτο. Στην περίπτωση αυτή λέμε ότι έχουμε μία 'κυκλικά συνδεδεμένη Λίστα', διαφορετικά η λίστα ονομάζεται 'ανοικτή' ή 'γραμμική' -19-
Εισαγωγή Στοιχείου σε Συνδεδεμένη Λίστα Η εισαγωγή νέου στοιχείου κάπου ανάμεσα σε μια συνδεδεμένη λίστα γίνεται σπάζοντας την λίστα σε αυτό το σημείο και εισάγοντας/προσαρμόζοντας κατάλληλα τα πεδία σύνδεσης του νέου στοιχείου με εκείνα των στοιχείων πριν και μετά από αυτό. Κατ αναλογία σκεφτείτε το σπάσιμο μιας αλυσίδας ανθρώπων που κρατούνται χέρι-χέρι ώστε να συμπεριλάβουν έναν ακόμα άνθρωπο. Δείτε και το επόμενο γραφικό παράδειγμα εισαγωγής στοιχείου σε απλά συνδεδεμένη λίστα. Για διπλά συνδεδεμένες λίστες η διαδικασία εισαγωγής είναι ανάλογη. Διαγραφή Στοιχείου από Συνδεδεμένη Λίστα Η διαγραφή ενός στοιχείου μιας συνδεδεμένης λίστα γίνεται σπάζοντας την λίστα σε αυτό το σημείο και προσαρμόζοντας κατάλληλα τα πεδία σύνδεσης των στοιχείων πριν και μετά το στοιχείο που διαγράφεται. Κατ αναλογία σκεφτείτε το σπάσιμο μιας αλυσίδας ανθρώπων που κρατούνται χερι-χέρι ώστε να αποχωρήσει κάποιος άνθρωπος. Δείτε και το επόμενο γραφικό παράδειγμα διαγραφής στοιχείου από απλά συνδεδεμένη λίστα. Για διπλά συνδεδεμένες λίστες η διαδικασία διαγραφής είναι ανάλογη. - ΤΕΛΟΣ ΔΕΥΤΕΡΗΣ ΕΝΟΤΗΤΑΣ (στοιχεία για την δημιουργία αυτών των σημειώσεων αντλήθηκαν από την Βικιπαίδεια και άλλες πηγές από το διαδίκτυο) -20-