Διδάσκων: Δρ. Τσίντζα Παναγιώτα ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ Διδάσκων: Δρ. Τσίντζα Παναγιώτα
ΓΕΝΙΚΕΣ ΠΛΗΡΟΦΟΡΙΕΣ Διδάσκων: Τσίντζα Παναγιώτα Στοιχεία Επικοινωνίας: iota.t@hotmail.it Σελίδα μαθήματος: e-class
Προτεινόμενο σύγγραμμα Δομές Δεδομένων, 2η έκδοση Συγγραφείς: Μποζάνης Π. Εκδοτικός οίκος Τζίολα & Υιοί Α.Ε. Κωδικός Εύδοξου: 59357253
Μαθησιακοί Στόχοι – Σκοπός μαθήματος Βασικές Δομές Δεδομένων Εισαγωγή στην ταξινόμηση Συγκριτικοί αλγόριθμοι Αλγόριθμοι κατανομής Δέντρα αναζήτησης Κατακερματισμός
Ορισμός Στην επιστήμη των υπολογιστών μία δομή δεδομένων είναι ένας συγκεκριμένος τρόπος αποθήκευσης και οργάνωσης δεδομένων στον υπολογιστή με σκοπό αυτά τα δεδομένα να μπορούν να χρησιμοποιηθούν με τον πιο αποδοτικό τρόπο.
Τύπος δεδομένου και τιμές Ένας τύπος δεδομένων αποτελείται από 2 συστατικά: ένα σύνολο τιμών (δλδ. οι δυνατές τιμές που μπορούν να εκχωρηθούν σε κάθε δεδομένο) ένα σύνολο από πράξεις που μπορούν να εκτελεστούν πάνω σε αυτές τις τιμές
Παραδείγματα τιμών και πράξεων Οι τιμές των δεδομένων εξαρτώνται από τον τρόπο χρήσης και τον λόγο υλοποίησης ενός αλγόριθμου: Παράδειγμα για την υλοποίηση μιας συνάρτησης boolean (λογικού προγραμματισμού) χρειαζόμαστε 2 λογικές τιμές: true, false Πράξεις που μπορούν να πραγματοποιηθούν πάνω στις λογικές τιμές: AND, OR, NOT, κ.τ.λ Για την υλοποίηση μιας συνάρτησης στους πραγματικούς αριθμούς χρειαζόμαστε τιμές R Πράξεις που μπορούν να πραγματοποιηθούν πάνω στους πραγματικούς αριθμούς: πρόσθεση, αφαίρεση, κ.τ.λ
Εισαγωγικέσ έννοιεσ
Αλγόριθμος Ο όρος αναϕέρεται σε οποιαδήποτε καλά ορισµένη υπολογιστική διαδικασία που δέχεται κάποια τιµή ή κάποιο σύνολο τιµών ως είσοδο και δίνει κάποια τιµή ή κάποιο σύνολο τιµών ως έξοδο. Ένας αλγόριθµος είναι µια ακολουθία υπολογιστικών βηµάτων που µετασχηµατίζει την είσοδο στην έξοδο. Μπορούµε επίσης να θεωρήσουµε τον αλγόριθµο ως ένα εργαλείο για την επίλυση ενός καλά καθορισµένου υπολογιστικού προβλήµατος. Η διατύπωση του προβλήµατος καθορίζει σε γενικές γραµµές την επιθυµητή σχέση εισόδου-εξόδου. Ο αλγόριθµος περιγράϕει µια συγκεκριµένη υπολογιστική διαδικασία για την επίτευξη αυτής της σχέσης εισόδου-εξόδου.
Ένα παράδειγμα Ταξινόμηση μιας ακολουθίας αριθμών κατά αύξουσα σειρά Ορισμός του προβλήματος: Είσοδος: Μια ακολουθία n αριθµών <a1, a2,...,an>. Έξοδος: Μια µετάθεση (αναδιάταξη) <a’1, a’2,...,a’n> της ακολουθίας εισόδου τέτοια ώστε a’1 ≤ a’2 ≤ ···≤ a’n. Παράδειγμα, αν η ακολουθία εισόδου είναι <31, 41, 59, 26, 41, 58> ένας αλ- γόριθµος ταξινόµησης επιστρέϕει ως έξοδο την ακολουθία <26, 31, 41, 41, 58, 59>. Κάθε τέτοια ακολουθία εισόδου ονοµάζεται στιγµιότυπο του προβλήµατος ταξινόµησης. Εν γένει, ο όρος στιγµιότυπο προβλήµατος δηλώνει την είσοδο η οποία απαιτείται για να υπολογιστεί µια λύση του προβλήµατος (εννοείται ότι η είσοδος αυτή θα ικανοποιεί όλους τους περιορισµούς που επιβάλλει η διατύπωση του προβλήµατος).
Ο πρώτος αλγόριθμος Ο πρώτος αλγόριθµος αποδίδεται στον Ευκλείδη και αφορά την εύρεση του µέγιστου κοινού διαιρέτη Υπάρχει και το κινέζικο θεώρηµα υπολοίπου από τον Κινέζο µαθηµατικό Sun-Chu: Ποιοι είναι οι ακέραιοι αριθµοί x που δίνουν υπόλοιπο – 2 , 3, 2 όταν διαιρεθούν µε – 3, 5, 7 αντίστοιχα. Και τα δύο θεωρήµατα ανήκουν στη θεωρία αριθµών και βρίσκουν εφαρµογή στη σύγχρονη κρυπτογραφία δηµοσίου κλειδιού
Αλγόριθμος μέγιστου αριθμού Είσοδος: Πίνακας Α µε θετικούς ακέραιους αριθµούς Έξοδος: Ο µέγιστος ακέραιος στον πίνακα Α int max = -1; for (int i = 0; i < A.length; i++ ) { if (max < A[i]) max = A[i]; } return max;
Ανάλυση αλγορίθμου Θέματα Ορθότητα Χρονική αποδοτικότητα Χωρική αποδοτικότητα Βελτιστότητα
Πολυπλοκότητα αλγόριθμου Πολυπλοκότητα Χρόνου: Καθορίζεται κυρίως από το πλήθος των υπολογιστικών πράξεων Πολυπλοκότητα Χώρου: Οι απαιτήσεις σε µνήµη – χώρο αποθήκευσης Για παράλληλους αλγορίθµους: Το πλήθος των επεξεργαστών που απαιτεί ο αλγόριθµος
Εκτίµηση Πολυπλοκότητας Χρόνου Απόδοση χρόνου σε κάθε πράξη Μέτρηση των κυριάρχων πράξεων Ασυµπτωτικές εκτιµήσεις Εύρεση χρόνου µέσω αναδροµικών σχέσεων
Μέγεθος Προβλήµατος (1) Πολυπλοκότητα και Μέγεθος: Η πολυπλοκότητα ενός αλγορίθµου εκφράζεται κατά κανόνα σε σχέση µε το µέγεθος του προβλήµατος Παράδειγµα: Η αλγόριθµος ταξινόµησης QuickSort απαιτεί O(Ν log(Ν) ) βήµατα για την ταξινόµηση N αριθµών Μέγεθος του προβλήµατος: Στο παραπάνω παράδειγµα θεωρούµε ότι για κάθε στιγµιότυπο του προβλήµατος της ταξινόµησης αριθµών το µέγεθος του προβλήµατος είναι το πλήθος των αριθµών
Μέγεθος Προβλήµατος (2) Ανάλογα µε το Πρόβληµα: Η έννοια του µεγέθους προβλήµατος µπορεί να διαφέρει ή να προσαρµόζεται ανάλογα µε το πρόβληµα Πρόβληµα συντοµότερης διαδροµής ∆ίνονται Ν κόµβοι και οι αποστάσεις ανα δύο µεταξύ τους. Για συγκεκριµένους κόµβους s και t ζητείται να βρεθεί η συντοµότερη διαδροµή µεταξύ τους. Ποιο είναι το µέγεθος του προβλήµατος; Ο αριθµός των κόµβων Ν; Το πλήθος των ακµών – διαδροµών µεταξύ όλων των ζευγών κόµβων N(N-1)/2 ;
Μέγεθος Προβλήµατος (3) Σε προβλήµατα όπου εµφανίζονται πολύ µεγάλοι αριθµοί µπορούµε να χρησιµοποιήσουµε το πλήθος των δυαδικών ψηφίων όλων των αριθµών ως µέγεθος του προβλήµατος. Όταν µελετούµε την πολυπλοκότητα ενός προβλήµατος οφείλουµε να αποσαφηνίζουµε τι θεωρούµε ως µέγεθος του προβλήµατος
Ρυθµός Ανάπτυξης Κατά την ανάλυση της πολυπλοκότητας ενός αλγορίθµου πολλές φορές δεν µπορούµε να βρούµε την ακριβή πολυπλοκότητα, ή δεν µας ενδιαφέρει η ακριβής πολυπλοκότητα, και απλά µελετούµε το ρυθµό ανάπτυξης των συναρτήσεων που εκφράζουν την πολυπλοκότητα Ασυµπτωτική Εκτίµηση: Χρησιµοποιούµε ασυµπτωτικές εκτιµήσεις για να περιγράψουµε την πολυπλοκότητα του αλγορίθµου
Ασυµπτωτικές Εκτιµήσεις Βασικοί Συµβολισµοί και Ορισµοί: Ο(Ν): ασυµπτοτικό άνω όριο Ω(Ν): ασυµπτωτικό κάτω όριο Θ(Ν): ασυµπτωτικό άνω και κάτω ή σφικτό (tight) όριο ο(Ν): ασυµπτωτικό άνω όριο που δεν είναι tight ω(Ν): ασυµπτωτικό κάτω όριο που δεν είναι tight
Ο(Ν) => Ασυµπτωτικό Άνω Όριο Ο(Ν) => Ασυµπτωτικό Άνω Όριο c*f(N) O(N)=g(N)
Ω(Ν) Ασυμπτωτικό κάτω όριο
Θ(Ν): ασυµπτωτικό άνω και κάτω ή σφικτό (tight) όριο c*f(N) O(N)=g(N) c’*f(N)
Στοιχειώδεις δομές δεδομένων Οι πιο βασικές δομές δεδομένων είναι 2 Πίνακες (array) Λίστες Πάνω σε αυτές τις 2 δομές οικοδομούνται όλες οι υπόλοιπες, πιο πολύπλοκες, δομές δεδομένων
Μονοδιάστατος πίνακας Πίνακες Μονοδιάστατος πίνακας Μήκος πίνακα Δισδιάστατος πίνακας Μήκος 1ης διάστασης Μήκος 2ης διάστασης Είναι μία σταθερή συλλογή δεδομένων ίδιου τύπου τα οποία αποθηκεύονται ακολουθιακά σε κάποιο σημείο της μνήμης. Χαρακτηριστικά Σταθερό μέγεθος Ένας τύπος δεδομένων Συνεχόμενη αποθήκευση στην μνήμη Τυχαία πρόσβαση (RAM - random access memory)
Πίνακες: Πλεονεκτήματα και μειονεκτήματα προσπέλαση στοιχείου σε σταθερό χρόνο, O(1) τυχαία προσπέλαση Μειονεκτήματα σταθερό μέγεθος δεν μπορούμε να προσθέσουμε στοιχεία στη μέση ενός πίνακα αναδιάταξη στοιχείων μόνο με αντιγραφή
Δήλωση πίνακα σε C++ Όπως για όλες τις δομές πρέπει να δηλωθεί ο τύπος των δεδομένων πριν η δομή να χρησιμοποιηθεί (Προσοχή όλες οι δηλώσεις γίνονται στην αρχή του προγράμματος). Η γενική δήλωση ενός πίνακα σε C++ γίνεται με την παρακάτω τύπο δήλωσης: type name [elements]; Τύπος δεδομένων του πίνακα Όνομα του πίνακα Αριθμητική τιμή που εκφράζει το μέγεθος του πίνακα Π.χ. int A[5]
Δισδιάστατοι Πίνακες πίνακες με 2 αριθμοδείκτες, πχ int array[3][2] αντιστοιχούν σε μήτρες (matrices) υλοποιούνται με μονοδιάστατους πίνακες, πχ για 5x5 μεγέθους πίνακα έχουμε array[i][j] = array[5* i + j] άρα κάθε στοιχείο χρειάζεται O(1) χρόνο για να προσπελαστεί
Πίνακες - Προσπέλαση Α: Ένα στοιχείο του πίνακα προσδιορίζεται από το όνομα του πίνακα και ένα αριθμό που προσδιορίζει τη σειρά του Ο αριθμός που προσδιορίζει την σειρά ονομάζεται δείκτης Τα στοιχεία του πίνακα είναι συνεχόμενα στη μνήμη Το πρώτο στοιχείο έχει πάντα σειρά 0 Τo μέγεθος του πίνακα είναι πάντα ακέραιο 25.2 25.5 26.6 26.0 25.9 22.8 27.9 Α: Α[0] Α[1] Α[2] Α[3] Α[4] Α[5] Α[6]
Παράδειγμα – Αρχικοποίηση στοιχείων Ένα πρόγραμμα στη C++ μπορεί να περιέχει πολλές συναρτήσεις όμως θα πρέπει οπωσδήποτε να περιέχει μία που να ονομάζεται main(). Όταν εκτελείται ένα πρόγραμμα στη C++ η πρώτη εντολή που εκτελείται θα είναι στην αρχή μιας συνάρτησης που ονομάζεται main(). Εάν δεν έχετε συμπεριλάβει στο πρόγραμμά σας συνάρτηση που να ονομάζεται main() τότε ο συνδέτης (linker) δίνει σήμα ότι βρήκε σφάλμα. main() { int k[20],i; //αρχικοποίηση όλων των στοιχείων του πίνακα με την τιμή 5 for (i=0; i<20; i++) k[i] = 5; } Το σώμα μιας συνάρτησης περικλείεται σε άγκιστρα. Βήμα Αρχικοποίηση δείκτη Συνθήκη τερματισμού
Ταυτόχρονη δήλωση και αρχικοποίηση int A[20] = {3,1,2,56,78}; Τα 5 πρώτα στοιχεία του Α θα έχουν τις τιμές που δηλώνονται εντός των αγκυλών. Ο πίνακας είναι 20 θέσεων Αν απουσιάζει το μέγεθος του πίνακα, ο πίνακας έχει τόσα στοιχεία όσα δηλώνονται στις αγκύλες Πχ int A = {3,12,6} είναι πίνακας 3 θέσεων
Δισδιάστατοι πίνακες – Πολλαπλασιασμός πινάκων c11 c12 ... c1p a11 a12 ... a1m b11 b12 ... b1p c21 c22 ... c2p a21 a22 ... a2m b21 b22 ... b2p ... = ... Χ ... cn1 cn2 ... cnp an1 an2 ... anm bm1 bm2 ... bmp // να προστεθεί ορισμός και αρχικοποίηση πινάκων for ( i = 0; i < n ; i++ ) for ( j = 0; j < p ; j++ ) for ( k = 0 , c [ i ] [ j ] = 0 . 0 ; k < m ; k++ ) c [ i ] [ j ] += a [ i ] [ k ] * b [ k ] [ j ] ; Η πολυπλοκότητα είναι O(npm)
Άσκηση 1 Δημιουργήστε πρόγραμμα το οποίο δοθέντος ενός πίνακα 3Χ2 προσθέτει όλα τα στοιχεία του πίνακα #include <iostream> using namespace std; main() { int a[3][2] = { {5,3}, {1,2}, {6,4} }; int sum = 0; int i, j; for (i=0; i < 3; i++) { for (j=0; j < 2; j++) { sum += a[i][j]; // διαφορετικά μπορώ να γράψω sum=sum + a[i][j]; } } cout << "Sum = " << sum << endl; }
Άσκηση 2 Να δημιουργηθεί πρόγραμμα που υπολογίζει το άθροισμα ανά γραμμή ενός πίνακα. Τα αποτελέσματα θα πρέπει να απεικονίζονται σε άλλο πίνακα #include <iostream> using namespace std; main() { int a[3][2] = { {5,3}, {1,2}, {6,4} }; int sum[3]; int i, j; for (i=0; i < 3; i++) { sum[i] = 0; } for (i=0; i < 3; i++) { for (j=0; j < 2; j++) { sum[i] += a[i][j]; } } for (i=0; i < 3; i++) { cout << "sum[" << i <<"] = " << sum[i] << endl;
Άσκηση 3: Να βρεθεί και να εκτυπωθεί το μέγιστο και το ελάχιστο στοιχείο ενός μονοδιάστατου πίνακα 50 πραγματικών αριθμών #include <iostream> #include <stdio.h> using namespace std; main() { double min, max; double x[50]; //λείπει αρχικοποίηση του πίνακα int N, i = 0; min = max = x[0]; for (i=1; i < 50; i++) { if (x[i] > max) { max = x[i]; } if (x[i] < min) min = x[i]; } cout << "End of input " << endl; printf("Min = %.6f\n", min); printf("Max = %.6f\n", max); }
Άσκηση 4 Δίνονται δύο μονοδιάστατοι πίνακες ακεραίων a,b, με ίσο πλήθος στοιχείων. Να γραφεί ένα πρόγραμμα που να συγκρίνει τα στοιχεία των δύο πινάκων και να εξάγει το πόσες φορές οι τιμές του a είναι μεγαλύτερες των αντίστοιχων τιμών του b. Επίσης πόσες φορές οι τιμές του b είναι μεγαλύτερες των αντίστοιχων τιμών του a. for (i=0; i<100; i++) { if (a[i] > b[i]) { ++ka; //διαφορετικά ka = ka+1; } if (b[i] > a[i]) ++kb; } cout << endl; cout << ka << " φορές μεγαλύτερο το a" << endl; cout << kb << " φορές μεγαλύτερο το b" << endl; } #include <iostream> using namespace std; main() { int a[100]; int b[100]; int i = 0; int ka = 0; // απαριθμητές int kb = 0;
Άσκηση 5. Tο προηγούμενο παράδειγμα με εισαγωγή στοιχείων από το πληκτρολόγιο Λογικό και while (cin >> a[i] && cin >> b[i]) { if (a[i] > b[i]) { ++ka; } if (b[i] > a[i]) ++kb; ++i; } cout << endl; cout << ka << " φορές μεγαλύτερο το a" << endl; cout << kb << " φορές μεγαλύτερο το b" << endl; } #include <iostream> #define NMAX 1000 //αρχικοποίηση μεταβλητής global using namespace std; main() { int a[NMAX]; int b[NMAX]; int i = 0; int ka = 0; // απαριθμητές int kb = 0; // προαιρετικά ένα μήνυμα στο χρήστη cout << "Δώσε δύο αριθμούς ανά γραμμή μέχρι CTRL+D " << endl; Δεν γνωρίζουμε πόσες επαναλήψεις Εισαγωγή στοιχείων. Η εντολή μεταφράζεται: ‘Όσο εισάγονται στοιχεία’