#2. Templates, η βιβλιοθήκη STL, μέτρηση χρόνου εκτέλεσης κώδικα, αλγόριθμοι ταξινόμησης, αλγόριθμοι αναζήτησης

Σχετικά έγγραφα
Ερώτημα Α 1. Να γράψετε τις εντολές που πραγματοποιούν τα ακόλουθα:

Δομές Δεδομένων και Αλγόριθμοι

#4. Heaps (σωροί), η ταξινόμηση HeapSort, η δομή std::priority_queue της STL

Αλγόριθμοι Ταξινόμησης Μέρος 2

Δομές Δεδομένων & Αλγόριθμοι

Εργαστηριακή Άσκηση 1

Προχωρημένες έννοιες προγραμματισμού σε C

ΠΛΗ111. Ανοιξη Μάθηµα 9 ο. Ταξινόµηση. Τµήµα Ηλεκτρονικών Μηχανικών και Μηχανικών Υπολογιστών Πολυτεχνείο Κρήτης

Standard Template Library (STL)

Δομές Δεδομένων & Αλγόριθμοι

Δομές Δεδομένων & Αλγόριθμοι

Εργαστήριο 2: Πίνακες

Δομές Δεδομένων και Αλγόριθμοι

Διάλεξη 09: Αλγόριθμοι Ταξινόμησης I

Ταξινόμηση. Παύλος Εφραιμίδης. Δομές Δεδομένων Ταξινόμηση 1

Διδάσκων: Κωνσταντίνος Κώστα Διαφάνειες: Δημήτρης Ζεϊναλιπούρ

Διδάσκων: Παναγιώτης Ανδρέου

ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ. Ταξινόµηση Quicksort Κεφάλαιο 7. Ε. Μαρκάκης Επίκουρος Καθηγητής

Ταξινόμηση με συγχώνευση Merge Sort

Αλγόριθμοι ταξινόμησης

Α' Εξάμηνο ΕΙΣΑΓΩΓΗ ΣΤΟ ΔΟΜΗΜΕΝΟ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ

Εργαστήριο 6: Αναζήτηση, Ανάλυση Πολυπλοκότητας

Δοµές Δεδοµένων. 11η Διάλεξη Ταξινόµηση Quicksort και Ιδιότητες Δέντρων. Ε. Μαρκάκης

Quicksort. Πρόβλημα Ταξινόμησης. Μέθοδοι Ταξινόμησης. Συγκριτικοί Αλγόριθμοι

Διαδικασιακός Προγραμματισμός

Δομές Δεδομένων και Αλγόριθμοι

Γ7.5 Αλγόριθμοι Αναζήτησης. Γ Λυκείου Κατεύθυνσης

Τεχνολογίες Υλοποίησης Αλγορίθµων

Προγραμματισμός Υπολογιστών με C++

Quicksort [Hoare, 62] Αλγόριθµοι & Πολυπλοκότητα (Χειµώνας 2011) Quicksort 1

Αναδρομικοί Αλγόριθμοι

Πληροφορική 2. Αλγόριθμοι

a 1 a 2 a n. 3. i = j 1 5. A[i + 1] = A[i] 6. i = i 1

Διάλεξη 19: Αλγόριθμοι ΤαξινόμησηςII. Διδάσκων: Παναγιώτης Ανδρέου

242 -ΕισαγωγήστουςΗ/Υ

Η εντολή if-else. Η απλή μορφή της εντολής if είναι η ακόλουθη: if (συνθήκη) { Η γενική μορφή της εντολής ifelse. εντολή_1; εντολή_2;..

Μάθημα 22: Δυαδικά δέντρα (Binary Trees)

Προγραμματιστικές Τεχνικές

Αλγόριθμοι Ταξινόμησης Μέρος 1

ΟΝΤΟΚΕΝΤΡΙΚΟΣ ΠΡΟΓΡ/ΣΜΟΣ C++

Quicksort. Επιμέλεια διαφανειών: Δ. Φωτάκης Μικροαλλαγές: Α. Παγουρτζής. Σχολή Ηλεκτρολόγων Μηχανικών και Μηχανικών Υπολογιστών

Συναρτήσεις και Πίνακες

Εκφωνήσεις ασκήσεων εργαστηρίου 1

Προγραμματιστικές Τεχνικές

Κλήση Συναρτήσεων ΚΛΗΣΗ ΣΥΝΑΡΤΗΣΕΩΝ. Γεώργιος Παπαϊωάννου ( )

Quicksort. ημήτρης Φωτάκης. Σχολή Ηλεκτρολόγων Μηχανικών και Μηχανικών Υπολογιστών. Εθνικό Μετσόβιο Πολυτεχνείο

Εργαστήριο 3 Εντολή for while, do while

ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ. Ταξινόµηση Mergesort Κεφάλαιο 8. Ε. Μαρκάκης Επίκουρος Καθηγητής

Δομές Δεδομένων και Αλγόριθμοι

#include <stdlib.h> Α. [-128,127] Β. [-127,128] Γ. [-128,128]

ιαφάνειες παρουσίασης #4

Ταξινόµηση. Παύλος Εφραιµίδης. οµές εδοµένων και

p

Α. unsigned int Β. double. Γ. int. unsigned char x = 1; x = x + x ; x = x * x ; x = x ^ x ; printf("%u\n", x); Β. unsigned char

Διαίρει-και-Βασίλευε. Διαίρει-και-Βασίλευε. MergeSort. MergeSort. Πρόβλημα Ταξινόμησης: Είσοδος : ακολουθία n αριθμών (α 1

Quicksort. ιδάσκοντες: Σ. Ζάχος,. Φωτάκης Επιμέλεια διαφανειών:. Φωτάκης. Σχολή Ηλεκτρολόγων Μηχανικών και Μηχανικών Υπολογιστών

Προγραμματισμός Ι (ΗΥ120)

Δομές Δεδομένων Standard Template Library (STL) 23/3/2017 ΜΠΟΜΠΟΤΑΣ ΑΓΟΡΑΚΗΣ

ΗΥ-150. Ταξινόµηση και Αναζήτηση

3 ΑΝΑ ΡΟΜΗ ΑΝΑΖΗΤΗΣΗ - ΤΑΞΙΝΟΜΗΣΗ. n! = 1*2*3*..(n-1)*n. n! = 1 αν n = 0, = n*(n-1)! αν n > ΑΝΑ ΡΟΜΗ Εισαγωγή

Προγραµµατισµός 1 Ταξινόµηση - Αναζήτηση

Ελληνική Δημοκρατία Τεχνολογικό Εκπαιδευτικό Ίδρυμα Ηπείρου. Πληροφορική II. Ενότητα 2 : Αλγόριθμοι. Δρ. Γκόγκος Χρήστος

Δομές δεδομένων (2) Αλγόριθμοι

ιαίρει-και-βασίλευε ημήτρης Φωτάκης Σχολή Ηλεκτρολόγων Μηχανικών και Μηχανικών Υπολογιστών Εθνικό Μετσόβιο Πολυτεχνείο

Ο αλγόριθμος Quick-Sort. 6/14/2007 3:42 AM Quick-Sort 1

Σχεδίαση και Ανάλυση Αλγορίθμων

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΜΑΘΗΜΑ 8 Ο. Ταξινόμηση και Αναζήτηση Συναρτήσεις χειρισμού οθόνης ΣΙΝΑΤΚΑΣ Ι. ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ

ΜΥΥ105: Εισαγωγή στον Προγραμματισμό. Αναζήτηση και Ταξινόμηση Χειμερινό Εξάμηνο 2016

Α Β Γ static; printf("%c\n", putchar( A +1)+2); B DB BD. int i = 0; while (++i); printf("*");

ΟΙΚΟΝΟΜΙΚΟ ΠΑΝΕΠΙΣΤΗΜΙΟ ΑΘΗΝΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ. Δοµές Δεδοµένων

Τεχνολογίες Υλοποίησης Αλγορίθµων

Δομές Δεδομένων. Λουκάς Γεωργιάδης.

Α' Εξάμηνο ΕΙΣΑΓΩΓΗ ΣΤΟ ΔΟΜΗΜΕΝΟ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ

Standard Template Library (STL) C++ library

Διάλεξη 10: Αλγόριθμοι Ταξινόμησης II

Προγραµµατιστικές Τεχνικές

Σχεδίαση Αλγορίθμων -Τμήμα Πληροφορικής ΑΠΘ - Εξάμηνο 4ο

Δοµές Δεδοµένων. 10η Διάλεξη Ταξινόµηση. E. Μαρκάκης

Προγραμματισμός Η/Υ (ΤΛ2007 )

ΕΠΛ231 Δομές Δεδομένων και Αλγόριθμοι 4. Παραδείγματα Ανάλυσης Πολυπλοκότητας Ανάλυση Αναδρομικών Αλγόριθμων

Εκφωνήσεις ασκήσεων εργαστηρίου 2 (pthreads)

Κατανεμημένα και Παράλληλα Συστήματα (εργαστήριο) Παραδείγματα με openmp

ΜΥΥ105: Εισαγωγή στον Προγραµµατισµό. Αναζήτηση και Ταξινόµηση Χειµερινό Εξάµηνο 2014

Δομές Δεδομένων και Αλγόριθμοι (Γ εξάμηνο) Τμήμα Μηχανικών Πληροφορικής ΤΕ, ΤΕΙ Ηπείρου. Άσκηση εργαστηρίου #6 (Υλοποίηση δυαδικού δένδρου αναζήτησης)

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Πίνακες Κλάσεις και Αντικείμενα

auth Αλγόριθμοι - Τμήμα Πληροφορικής ΑΠΘ - Εξάμηνο 4ο

Προγραμματισμός Υπολογιστών με C++

Αντικειμενοστραφής Προγραμματισμός

Αλγόριθμοι και πολυπλοκότητα Ταχυταξινόμηση (Quick-Sort)

Α' Εξάμηνο ΕΙΣΑΓΩΓΗ ΣΤΟ ΔΟΜΗΜΕΝΟ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ

Merge Sort (Ταξινόμηση με συγχώνευση) 6/14/2007 3:04 AM Merge Sort 1

Στόχοι και αντικείμενο ενότητας. Πέρασμα Πίνακα σε Συνάρτηση (συν.) Πέρασμα Πίνακα σε Συνάρτηση. #8.. Ειδικά Θέματα Αλγορίθμων

ΑΣΚΗΣΕΙΣ ΓΙΑ ΤΟ ΕΡΓΑΣΤΗΡΙΟ 2

Εχουμε ήδη συναντήσει μονοδιάστατους πίνακες, οι οποίοι ορίζονται ως εξής:

Δομές Επανάληψης. Εισαγωγή στη C++

Διαίρει-και-Βασίλευε. Αλγόριθµοι & Πολυπλοκότητα (Χειµώνας 2011) Διαίρει-και-Βασίλευε 2

Διάλεξη 04: Παραδείγματα Ανάλυσης

Προγραμματισμός Ι. Κλάσεις και Αντικείμενα. Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

υναµική διαχείριση µνήµης στη C++ Στην ενότητα αυτή θα µελετηθούν τα εξής επιµέρους θέµατα: ΕΠΛ 132 Αρχές Προγραµµατισµού ΙΙ 2 είκτες

Πίνακες. Οι πίνακες αποτελούν ένα σηµαντικό δοµηµένο τύπο δεδοµένων (structured data type) ή πιο απλά µία δοµή δεδοµένων (data structure).

Transcript:

Τμήμα Μηχανικών Πληροφορικής Τ.Ε. Σχολή Τεχνολογικών Εφαρμογών Ακαδημαϊκό έτος 2016-2017 ΤΕΙ Ηπείρου - Άρτα Δομές Δεδομένων και Αλγόριθμοι (εργαστήριο) Γκόγκος Χρήστος #2. Templates, η βιβλιοθήκη STL, μέτρηση χρόνου εκτέλεσης κώδικα, αλγόριθμοι ταξινόμησης, αλγόριθμοι αναζήτησης 1. Templates Τα templates είναι ένας μηχανισμός της C++ ο οποίος μπορεί να διευκολύνει τον προγραμματισμό. Η γλώσσα C++ είναι strongly typed και αυτό μπορεί να οδηγήσει στην ανάγκη υλοποίησης διαφορετικών εκδόσεων μιας συνάρτησης έτσι ώστε να υποστηριχθεί η ίδια λογική για διαφορετικούς τύπους δεδομένων. Για παράδειγμα, η εύρεση του μεγίστου ανάμεσα σε τρεις τιμές θα έπρεπε να υλοποιηθεί με δύο συναρτήσεις έτσι ώστε να υποστηρίζει τόσο τους ακέραιους όσο και τους πραγματικούς αριθμούς, όπως φαίνεται στον κώδικα που ακολουθεί. int min(int a, int b, int c){ int m = a; if (b<m) m=b; if (c<m) m=c; return m; double min(double a, double b, double c){ double m = a; if (b<m) m=b; if (c<m) m=c; return m; int main(int argc, char* argv[]){ cout << min(5,10, 7) << endl; cout << min(3.1, 2.5, 5.2) << endl; 5 2.5 Κώδικας 1. Παράδειγμα με επανάληψη λογικής κώδικα Με τη χρήση των templates μπορεί να γραφεί κώδικας που να υποστηρίζει ταυτόχρονα πολλούς τύπους δεδομένων. Ειδικότερα, χρησιμοποιείται, η δεσμευμένη λέξη template και εντός των συμβόλων < και > τοποθετείται η λίστα των παραμέτρων του template. Ο μεταγλωττιστής αναλαμβάνει να δημιουργήσει όλες τις απαιτούμενες παραλλαγές των συναρτήσεων που θα χρειαστούν στον κώδικα που μεταγλωττίζει. [1]

template <class T> T min(t a, T b, T c){ T m = a; if (b<m) m=b; if (c<m) m=c; return m; int main(int argc, char* argv[]){ cout << min(5,10, 7) << endl; cout << min(3.1, 2.5, 5.2) << endl; 5 2.5 Κώδικας 2. Παράδειγμα με χρήση template 2. Η βιβλιοθήκη STL Η βιβλιοθήκη STL (Standard Template Library) της C++ προσφέρει έτοιμη λειτουργικότητα για πολλά θέματα τα οποία ανακύπτουν συχνά στον προγραμματισμό εφαρμογών. Πρόκειται για μια generic βιβλιοθήκη, δηλαδή κάνει εκτεταμένη χρήση των templates. Βασικά τμήματα της STL είναι οι containers, οι αλγόριθμοι και οι iterators. 2.1 Containers H STL υποστηρίζει έναν αριθμό από containers στους οποίους μπορούν να αποθηκευτούν δεδομένα. Ένα από τα containers είναι το vector. Στο ακόλουθο παράδειγμα φαίνεται πως η χρήση του vector διευκολύνει τον προγραμματισμό καθώς δεν απαιτούνται εντολές διαχείρισης μνήμης ενώ η δομή είναι δυναμική, δηλαδή το μέγεθος της μπορεί να μεταβάλλεται κατά τη διάρκεια εκτέλεσης του προγράμματος. #include <vector> int main(int argc, char* argv[]){ int x; cout << "Enter size of vector: "; cin >> x; vector<int> v(x); for(int i=0;i<x;i++) v[i]=i; v.push_back(99); for(int i=0;i<v.size();i++) cout << v[i] << " "; Enter size of vector: 10 0 1 2 3 4 5 6 7 8 9 99 Κώδικας 3. Παράδειγμα με χρήση του container, vector 2.2 Αλγόριθμοι H STL διαθέτει πληθώρα αλγορίθμων που μπορούν να εφαρμοστούν σε διάφορα προβλήματα. Για παράδειγμα, προκειμένου να ταξινομηθούν δεδομένα μπορεί να χρησιμοποιηθεί η συνάρτηση sort της STL η οποία υλοποιεί τον αλγόριθμο Introspective Sort. #include <algorithm> [2]

int a[]={45,32,16,11,7,18,21,16,11,15; cout << "BEFORE: "; for (int i = 0; i < 10; i++) cout << a[i] << " "; cout << endl; sort(a, a + 10); cout << "AFTER: "; for (int i = 0; i < 10; i++) cout << a[i] << " "; cout << endl; return 0; BEFORE: 45 32 16 11 7 18 21 16 11 15 AFTER: 7 11 11 15 16 16 18 21 32 45 Κώδικας 4. Ταξινόμηση πίνακα με τη συνάρτηση sort της STL Αντίστοιχα, για να γίνει αναζήτηση ενός στοιχείου σε έναν ταξινομημένο πίνακα μπορεί να χρησιμοποιηθεί η συνάρτηση binary_search, όπως φαίνεται στον ακόλουθο κώδικα. #include <algorithm> int a[] = { 45, 32, 16, 11, 7, 18, 21, 16, 11, 15 ; int key; sort(a, a + 10); cout << "Enter a value "; cin >> key; if (binary_search(a, a + 10, key)) cout << "found" << endl; else cout << "not found" << endl; Enter a value 7 found Enter a value 8 not found Κώδικας 5. Αναζήτηση στοιχείου σε ταξινομημένο πίνακα με τη συνάρτηση binary_search της STL 2.3 Iterators Οι iterators αποτελούν γενικεύσεις των δεικτών και επιτρέπουν την πλοήγηση στα στοιχεία ενός container με τέτοιο τρόπο έτσι ώστε να μπορούν να χρησιμοποιηθούν οι ίδιοι αλγόριθμοι σε περισσότερα του ενός containers. Στον ακόλουθο κώδικα παρουσιάζεται το πέρασμα από τα στοιχεία ενός vector με 3 τρόπους. Καθώς το container είναι τύπου vector παρουσιάζεται αρχικά το πέρασμα από τις τιμές του με τη χρήση δεικτοδότησης τύπου πίνακα. Στη συνέχεια χρησιμοποιείται ένας iterator για πέρασμα από την αρχή προς το τέλος και μετά ένας reverse_iterator για πέρασμα από το τέλος προς την αρχή. #include <vector> #include <algorithm> // vector<int> v = {23,13,31,17; // c++11 feature vector<int> v; v.push_back(23); v.push_back(13); [3]

v.push_back(31); v.push_back(17); cout << "iteration with index: "; for(int i=0;i<v.size();i++) cout << v[i] << " "; sort(v.begin(), v.end()); cout << endl << "forward iteration with iterator: "; vector<int>::iterator iter; for(iter=v.begin();iter!=v.end();iter++) cout << *iter << " "; cout << endl << "backward iteration with iterator: "; vector<int>::reverse_iterator riter; for(riter=v.rbegin();riter!=v.rend();riter++) cout << *riter << " "; iteration with index: 23 13 31 17 forward iteration with iterator: 13 17 23 31 backward iteration with iterator: 31 23 17 13 Κώδικας 6. Διάσχιση στοιχείων ενός vector με τη χρήση iterator 3. Μέτρηση χρόνου εκτέλεσης κώδικα Ο ακόλουθος κώδικας μετράει το χρόνο που απαιτεί ο υπολογισμός του αθροίσματος των τετραγωνικών ριζών δέκα εκατομμυρίου τυχαίων ακέραιων αριθμών με τιμές στο διάστημα από 0 έως 10 4. Η μέτρηση του χρόνου πραγματοποιείται με τη συνάρτηση clock() η οποία επιστρέφει τον αριθμό από clock ticks που έχουν περάσει από τη στιγμή που το πρόγραμμα ξεκίνησε την εκτέλεση του. Ο αριθμός των δευτερολέπτων που έχουν περάσει προκύπτει διαιρώντας τον αριθμό των clock ticks με τη σταθερά CLOCKS_PER_SEC. #include <ctime> #include <random> #include <cmath> clock_t t1, t2; t1 = clock(); int seed = 1729; int lower = 0; int upper = 10000; mt19937 mt(seed); uniform_int_distribution<int> dist(lower, upper); double sum = 0.0; for (int i=1;i<=10000000;i++){ int x = dist(mt); sum += sqrt(x); cout << sum << endl; t2 = clock(); double elapsed_time = (double) (t2-t1)/clocks_per_sec; cout << "Elapsed time " << elapsed_time << endl; 6.66793e+008 Elapsed time 0.565 Κώδικας 7. Μέτρηση χρόνου με την clock() Ένας άλλος τρόπος με τον οποίο μπορεί να μετρηθεί ο χρόνος εκτέλεσης ενός κώδικα είναι με τη χρήση των time_points, όπως στο παράδειγμα που ακολουθεί. #include <random> #include <cmath> [4]

#include <chrono> using namespace std::chrono; high_resolution_clock::time_point t1 = high_resolution_clock::now(); int seed = 1729; int lower = 0; int upper = 10000; mt19937 mt(seed); uniform_int_distribution<int> dist(lower, upper); double sum = 0.0; for (int i=1;i<=10000000;i++){ int x = dist(mt); sum += sqrt(x); cout << sum << endl; high_resolution_clock::time_point t2 = high_resolution_clock::now(); auto duration = duration_cast<microseconds>( t2 - t1).count(); cout << "Time elapsed: " << duration << " microseconds " << duration / 1000000.0 << " seconds" << endl; 6.66793e+008 Time elapsed: 550031 microseconds 0.550031 seconds Κώδικας 8. Μέτρηση χρόνου εκτέλεσης με time_point (c++11) 4. Αλγόριθμοι ταξινόμησης 4.1 Ταξινόμηση με εισαγωγή (insertion-sort) Ο κώδικας ταξινόμησης με εισαγωγή καθώς και η κλήση του από κύριο πρόγραμμα για την αύξουσα ταξινόμηση ενός πίνακα 10 θέσεων παρουσιάζεται στον κώδικα που ακολουθεί. Η ταξινόμηση με εισαγωγή 1 λειτουργεί δημιουργώντας μια ταξινομημένη λίστα στο αριστερό άκρο των δεδομένων και επαναληπτικά τοποθετεί το στοιχείο το οποίο βρίσκεται δεξιά της ταξινομημένης λίστας στη σωστή θέση σε σχέση με τα ήδη ταξινομημένα στοιχεία. void insertion_sort(t a[], int n) { for (int i = 1; i < n; i++) { T key = a[i]; int j = i - 1; while ((j >= 0) && (key < a[j])) { a[j + 1] = a[j]; j--; a[j + 1] = key; int a[]={45,32,16,11,7,18,21,16,11,15; insertion_sort(a, 10); for(int i=0;i<10;i++) cout << a[i] << " "; 7 11 11 15 16 16 18 21 32 45 Κώδικας 9. Ταξινόμηση με εισαγωγή 1 http://rosettacode.org/wiki/sorting_algorithms/insertion_sort [5]

4.2 Ταξινόμηση με συγχώνευση (merge-sort) Ο κώδικας ταξινόμησης με συγχώνευση παρουσιάζεται στη συνέχεια. Η ταξινόμηση με συγχώνευση 2 είναι αναδρομικός αλγόριθμος και στηρίζεται στη συγχώνευση ταξινομημένων υποακολουθιών έτσι ώστε να δημιουργούνται νέες ταξινομημένες υποακολουθίες. void merge(t a[], int l, int m, int r) { T la[m - l + 1]; T ra[r - m]; for (int i = 0; i < m - l + 1; i++) la[i] = a[l + i]; for (int i = 0; i < r - m; i++) ra[i] = a[m + 1 + i]; int i = 0, j = 0, k = l; while ((i < m - l + 1) && (j < r - m)) { if (la[i] < ra[j]) { a[k] = la[i]; i++; else { a[k] = ra[j]; j++; k++; if (i == m - l + 1) { while (j < r - m) { a[k] = ra[j]; j++; k++; else { while (i < m - l + 1) { a[k] = la[i]; i++; k++; void merge_sort(t a[], int l, int r) { if (l < r) { int m = (l + r) / 2; merge_sort(a, l, m); merge_sort(a, m + 1, r); merge(a, l, m, r); void merge_sort(t a[], int N) { merge_sort(a, 0, N - 1); int a[]={45,32,16,11,7,18,21,16,11,15; merge_sort(a, 10); for(int i=0;i<10;i++) 2 http://rosettacode.org/wiki/sorting_algorithms/merge_sort [6]

cout << a[i] << " "; 7 11 11 15 16 16 18 21 32 45 Κώδικας 10. Ταξινόμηση με συγχώνευση 4.3 Γρήγορη ταξινόμηση (quick-sort) Ο κώδικας της γρήγορης ταξινόμησης 3 παρουσιάζεται στη συνέχεια. Πρόκειται για κώδικα ο οποίος καλείται αναδρομικά σε υποακολουθίες των δεδομένων και σε κάθε κλήση επιλέγει ένα στοιχείο (pivot) και διαχωρίζει τα υπόλοιπα στοιχεία έτσι ώστε αριστερά να είναι τα στοιχεία που είναι μικρότερα του pivot και δεξιά αυτά τα οποία είναι μεγαλύτερα. int partition(t a[], int l, int r) { int p = l; int i = l + 1; for (int j = l + 1; j <= r; j++) { if (a[j] < a[p]) { swap(a[j], a[i]); i++; swap(a[p], a[i - 1]); return i - 1; void quick_sort(t a[], int l, int r) { if (l >= r) return; else { int p = partition(a, l, r); quick_sort(a, l, p - 1); quick_sort(a, p + 1, r); void quick_sort(t a[], int N) { quick_sort(a, 0, N - 1); int a[]={45,32,16,11,7,18,21,16,11,15; quick_sort(a, 10); for(int i=0;i<10;i++) cout << a[i] << " "; 7 11 11 15 16 16 18 21 32 45 Κώδικας 11.Γρήγορη ταξινόμηση 4.4 Σύγκριση χρόνου εκτέλεσης αλγορίθμων ταξινόμησης Στη συνέχεια παρουσιάζεται μια σύγκριση των χρόνων εκτέλεσης για τους «γρήγορους» αλγορίθμους ταξινόμησης merge-sort, quick-sort καθώς και για τον αλγόριθμο ταξινόμησης της βιβλιοθήκης STL (συνάρτηση sort). Η σύγκριση αφορά τυχαία ακέραια δεδομένα με τιμές στο διάστημα από 0 έως 10 6 επιλεγμένα από ομοιόμορφη κατανομή. Τα 3 http://rosettacode.org/wiki/sorting_algorithms/quicksort [7]

μεγέθη των πινάκων εισόδου είναι: 5.000, 10.000, 20.0000, 40.000, 80.000, 160.0000 και 320.000. Τα αποτελέσματα της σύγκρισης παρουσιάζονται στον Πίνακα 1 και στην Εικόνα 1. Μέγεθος εισόδου Merge Sort Quick Sort C++ std::sort 5000 0.001 0.002 0.001 10000 0.003 0.002 0.002 20000 0.005 0.006 0.005 40000 0.012 0.012 0.010 80000 0.023 0.028 0.017 160000 0.045 0.056 0.036 320000 0.094 0.100 0.070 Πίνακας 1 Εικόνα 1 Ο κώδικας με τον οποίο επιτυγχάνεται η εμπειρική σύγκριση των αλγορίθμων ταξινόμησης ακολουθεί στη συνέχεια. #include <random> #include <iomanip> #include <algorithm> #include <ctime> #include <cmath> void merge(t a[], int l, int m, int r) { T la[m - l + 1]; T ra[r - m]; for (int i = 0; i < m - l + 1; i++) la[i] = a[l + i]; for (int i = 0; i < r - m; i++) ra[i] = a[m + 1 + i]; int i = 0, j = 0, k = l; while ((i < m - l + 1) && (j < r - m)) { if (la[i] < ra[j]) { a[k] = la[i]; i++; [8]

else { a[k] = ra[j]; j++; k++; if (i == m - l + 1) { while (j < r - m) { a[k] = ra[j]; j++; k++; else { while (i < m - l + 1) { a[k] = la[i]; i++; k++; void merge_sort(t a[], int l, int r) { if (l < r) { int m = (l + r) / 2; merge_sort(a, l, m); merge_sort(a, m + 1, r); merge(a, l, m, r); void merge_sort(t a[], int N) { merge_sort(a, 0, N - 1); int partition(t a[], int l, int r) { int p = l; int i = l + 1; for (int j = l + 1; j <= r; j++) { if (a[j] < a[p]) { swap(a[j], a[i]); i++; swap(a[p], a[i - 1]); return i - 1; void quick_sort(t a[], int l, int r) { if (l >= r) return; else { int p = partition(a, l, r); quick_sort(a, l, p - 1); quick_sort(a, p + 1, r); void quick_sort(t a[], int N) { quick_sort(a, 0, N - 1); void benchmark_sort_algorithm(string alg) { clock_t t1, t2; mt19937 mt(1729); uniform_int_distribution<int> dist(0, 1000000); [9]

int sizes[] = { 5000, 10000, 20000, 40000, 80000, 160000, 320000 ; for (int i = 0; i < 7; i++) { int N = sizes[i]; int *a = new int[n]; for (int i = 0; i < N; i++) a[i] = dist(mt); t1 = clock(); if (alg.compare("merge-sort") == 0) merge_sort(a, N); else if (alg.compare("quick-sort") == 0) quick_sort(a, N); else if (alg.compare("stl-sort") == 0) sort(a, a + N); t2 = clock(); double elapsed_time = (double) (t2 - t1) / CLOCKS_PER_SEC; cout << fixed << setprecision(3); cout << "Elapsed time " << alg << "\t" << sizes[i] << "\t" << elapsed_time << endl; delete [] a; benchmark_sort_algorithm("merge-sort"); benchmark_sort_algorithm("quick-sort"); benchmark_sort_algorithm("stl-sort"); Κώδικας 12. Σύγκριση χρόνου εκτέλεσης αλγορίθμων ταξινόμησης 4.5 Ένας ακόμη αλγόριθμος ταξινόμησης Υπάρχουν πολλοί άλλοι αλγόριθμοι ταξινόμησης. Ένας από αυτούς είναι ο αλγόριθμος κατάταξης (rank-sort) o οποίος λειτουργεί ως εξής: Για κάθε στοιχείο του δεδομένου πίνακα a που επιθυμούμε να ταξινομήσουμε υπολογίζεται μια τιμή κατάταξης (rank). Η τιμή κατάταξης ενός στοιχείου του πίνακα είναι το πλήθος των μικρότερων από αυτό στοιχείων συν το πλήθος των ίσων με αυτό στοιχείων που έχουν μικρότερο δείκτη σε σχέση με αυτό το στοιχείο (δηλαδή βρίσκονται αριστερά του). Δηλαδή ισχύει ότι η τιμή κατάταξης ενός στοιχείου x του πίνακα είναι ίση με το άθροισμα 2 όρων: του πλήθους των μικρότερων στοιχείων του x από όλο τον πίνακα και του πλήθους των ίσων με το x στοιχείων που έχουν μικρότερο δείκτη σε σχέση με το x. Για παράδειγμα στην ακολουθία τιμών a=[44, 21, 78, 16, 56, 21] θα πρέπει να δημιουργηθεί ένας νέος πίνακας r = [3, 1, 5, 0, 4, 2]. Έχοντας υπολογίσει τον πίνακα r θα πρέπει τα στοιχεία του a να αντιγραφούν σε ένα νέο βοηθητικό πίνακα temp έτσι ώστε κάθε τιμή που υπάρχει στον πίνακα r να λειτουργεί ως δείκτης για το που πρέπει να τοποθετηθεί το αντίστοιχο στοιχείο του a στον πίνακα temp. Τέλος θα πρέπει να αντιγραφεί ο πίνακας temp στον πίνακα a. Στη συνέχεια παρουσιάζεται ο κώδικας του αλγορίθμου rank-sort. Παρουσιάζονται δύο υλοποιήσεις. Η πρώτη υλοποίηση (rank_sort) αφορά τον αλγόριθμο όπως έχει περιγραφεί παραπάνω ενώ η δεύτερη (rank_sort_in_place) είναι από το βιβλίο «Δομές Δεδομένων, Αλγόριθμοι και Εφαρμογές στη C++ του Sartaj Sahnii, Εκδόσεις Τζιόλα, 2004» στη σελίδα 63 (πρόγραμμα 2.11) και δεν απαιτεί τη χρήση του βοηθητικού πίνακα temp, συνεπώς είναι αποδοτικότερος. #include <algorithm> void rank_sort(t a[], int n) { int r[n]={0; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) [10]

if (a[j] < a[i] (a[j] == a[i] && j < i)) r[i]++; int temp[n]; for (int i = 0; i < n; i++) temp[r[i]] = a[i]; for (int i = 0; i < n; i++) a[i] = temp[i]; void rank_sort_in_place(t a[], int n){ int r[n] = {0; for (int i=0;i<n;i++) for(int j=0;j<i;j++) if (a[j]<=a[i]) r[i]++; else r[j]++; for (int i=0;i<n;i++) while(r[i]!=i){ int t = r[i]; swap(a[i], a[t]); swap(r[i], r[t]); int a[]={45,32,16,11,7,18,21,16,11,15; cout << "RANK SORT: "; rank_sort(a,10); for(int i=0;i<10;i++) cout << a[i] << " "; cout << endl << "RANK SORT (IN PLACE): "; int b[]={45,32,16,11,7,18,21,16,11,15; rank_sort_in_place(b,10); for(int i=0;i<10;i++) cout << b[i] << " "; RANK SORT: 7 11 11 15 16 16 18 21 32 45 RANK SORT (IN PLACE): 7 11 11 15 16 16 18 21 32 45 Κώδικας 13. Ταξινόμηση κατάταξης 5. Αλγόριθμοι αναζήτησης 5.1 Σειριακή αναζήτηση (sequential-search) Η σειριακή αναζήτηση είναι ο απλούστερος αλγόριθμος αναζήτησης. Εξετάζει τα στοιχεία ένα προς ένα στη σειρά μέχρι να βρει το στοιχείο που αναζητείται. Το πλεονέκτημα του αλγορίθμου είναι ότι μπορεί να εφαρμοστεί σε μη ταξινομημένους πίνακες. int sequential_search(t a[], int n, T key) { for (int i = 0; i < n; i++) { if (a[i] == key) return i; return -1; int main(int argc, char** argv){ int a[]={5,11,45,23,10,17,32,8,9,4; [11]

int key; cout << "Search for: "; cin >> key; int pos = sequential_search(a, 10, key); if (pos==-1) cout << "Not found" << endl; else cout << "Found at position " << pos << endl; Search for: 45 Found at position 2 Search for: 99 Not found Κώδικας 14. Σειριακή αναζήτηση 5.2 Δυαδική αναζήτηση (binary-search) Η δυαδική αναζήτηση μπορεί να εφαρμοστεί μόνο σε ταξινομημένα δεδομένα. Διαιρεί επαναληπτικά την ακολουθία σε 2 υποακολουθίες και απορρίπτει την ακολουθία στην οποία συμπεραίνει ότι δεν μπορεί να βρεθεί το στοιχείο. int binary_search(t a[], int l, int r, T key) { int m = (l + r) / 2; if (l > r) { return -1; else if (a[m] == key) { return m; else if (key < a[m]) { return binary_search(a, l, m - 1, key); else { return binary_search(a, m + 1, r, key); int binary_search(t a[], int n, T key) { return binary_search(a, 0, n-1, key); int main(int argc, char** argv){ int a[]={11,45,53,60,67,72,88,91,94,98; int key; cout << "Search for: "; cin >> key; int pos = binary_search(a, 10, key); if (pos==-1) cout << "Not found" << endl; else cout << "Found at position " << pos << endl; Search for: 60 Found at position 3 Search for: 51 Not found Κώδικας 15. Δυαδική αναζήτηση [12]

5.3 Αναζήτηση με παρεμβολή (interpolation-search) Η αναζήτηση με παρεμβολή (interpolation-search) είναι μια παραλλαγή της δυαδικής αναζήτησης και μπορεί να εφαρμοστεί μόνο σε ταξινομημένα δεδομένα. Αντί να χρησιμοποιηθεί η τιμή 50% για να διαχωριστούν τα δεδομένα σε 2 ισομεγέθεις λίστες (όπως συμβαίνει στη δυαδική αναζήτηση) υπολογίζεται μια τιμή η οποία εκτιμάται ότι θα οδηγήσει πλησιέστερα στο στοιχείο που αναζητείται. Αν l είναι ο δείκτης του αριστερότερου στοιχείου της ακολουθίας και r o δείκτης του δεξιότερου στοιχείου της ακολουθίας τότε υπολογίζεται ο συντελεστής c = (key a[l])/(a[r] a[l]) όπου key είναι το στοιχείο προς αναζήτηση και a είναι η ακολουθία τιμών στην οποία αναζητείται το key. Η ακολουθία των δεδομένων διαχωρίζεται με βάση τον συντελεστή c σε δύο υποακολουθίες. Η διαδικασία επαναλαμβάνεται ανάλογα με τη δυαδική αναζήτηση. Στη συνέχεια παρουσιάζεται ο κώδικας της αναζήτησης με παρεμβολή. int interpolation_search(t a[], int l, int r, T key) { int m; if (l > r) { return -1; else if (l == r) { m = l; else { double c = (double) (key - a[l]) / (double) (a[r] - a[l]); if ((c < 0) (c > 1)) return -1; m = (int) (l + (r - l) * c); if (a[m] == key) { return m; else if (key < a[m]) { return interpolation_search(a, l, m - 1, key); else { return interpolation_search(a, m + 1, r, key); int interpolation_search(t a[], int n, T key) { return interpolation_search(a, 0, n-1, key); int main(int argc, char** argv){ int a[]={11,45,53,60,67,72,88,91,94,98; int key; cout << "Search for: "; cin >> key; int pos = interpolation_search(a, 10, key); if (pos==-1) cout << "Not found" << endl; else cout << "Found at position " << pos << endl; Search for: 60 Found at position 3 Search for: 51 Not found Κώδικας 16. Αναζήτηση με παρεμβολή [13]

5.4 Σύγκριση χρόνου εκτέλεσης αλγορίθμων αναζήτησης Στη συνέχεια παρουσιάζεται μια σύγκριση των χρόνων εκτέλεσης των αλγορίθμων αναζήτησης binary-search, interpolation-search και του αλγορίθμου αναζήτησης της βιβλιοθήκης STL (συνάρτηση binary_search) για ταξινομημένα ακέραια δεδομένα με τιμές στο διάστημα από 0 έως 10 6. Η σύγκριση εξετάζει τα ακόλουθα μεγέθη πινάκων: 5.000, 10.000, 20.000, 40.000, 80.000, 160.000 και 320.000. Οι χρόνοι εκτέλεσης αφορούν τους συνολικούς χρόνους που απαιτούνται έτσι ώστε να αναζητηθούν 100.000 τυχαίες τιμές με καθένα από τους αλγορίθμους. Τα αποτελέσματα της σύγκρισης παρουσιάζονται στον Πίνακα 2 και στην Εικόνα 2. Μέγεθος εισόδου Binary Search Interpolation Search C++ std::binary_search 5000 0.021 0.012 0.032 10000 0.021 0.014 0.032 20000 0.022 0.014 0.035 40000 0.024 0.014 0.038 80000 0.027 0.014 0.038 160000 0.029 0.017 0.040 320000 0.031 0.018 0.046 Πίνακας 2 Εικόνα 2 Ο κώδικας με τον οποίο επιτυγχάνεται η εμπειρική σύγκριση των αλγορίθμων αναζήτησης ακολουθεί στη συνέχεια. #include <random> #include <iomanip> #include <algorithm> #include <ctime> #include <cmath> int binary_search(t a[], int l, int r, T key) { int m = (l + r) / 2; if (l > r) { return -1; else if (a[m] == key) { return m; else if (key < a[m]) { return binary_search(a, l, m - 1, key); else { return binary_search(a, m + 1, r, key); [14]

int interpolation_search(t a[], int l, int r, T key) { int m; if (l > r) { return -1; else if (l == r) { m = l; else { double c = (double) (key - a[l]) / (double) (a[r] - a[l]); if ((c < 0) (c > 1)) return -1; m = (int) (l + (r - l) * c); if (a[m] == key) { return m; else if (key < a[m]) { return interpolation_search(a, l, m - 1, key); else { return interpolation_search(a, m + 1, r, key); void benchmark_search_algorithm(string alg) { clock_t t1, t2; mt19937 mt(1729); uniform_int_distribution<int> dist(0, 1000000); int M = 100000; int keys[m]; for (int i = 0; i < M; i++) { keys[i] = dist(mt); int sizes[] = { 5000, 10000, 20000, 40000, 80000, 160000, 320000 ; for (int i = 0; i < 7; i++) { int N = sizes[i]; int *a = new int[n]; for (int i = 0; i < N; i++) a[i] = dist(mt); sort(a, a + N); t1 = clock(); int c = 0; if (alg.compare("binary-search") == 0) { for (int j = 0; j < M; j++) if (binary_search(a, 0, N - 1, keys[j])!= -1) c++; else if (alg.compare("interpolation-search") == 0) { for (int j = 0; j < M; j++) if (interpolation_search(a, 0, N - 1, keys[j])!= -1) c++; else if (alg.compare("stl-binary-search") == 0) for (int j = 0; j < M; j++) if (binary_search(a, a + N, keys[j])) c++; t2 = clock(); double elapsed_time = (double) (t2 - t1) / CLOCKS_PER_SEC; cout << fixed << setprecision(3); cout << "Values found " << c << " Elapsed time " << alg << "\t" << sizes[i] << "\t" << elapsed_time << endl; delete [] a; benchmark_search_algorithm("binary-search"); benchmark_search_algorithm("interpolation-search"); benchmark_search_algorithm("stl-binary-search"); [15]

Κώδικας 17. Σύγκριση χρόνου εκτέλεσης αλγορίθμων αναζήτησης Χρήσιμοι σύνδεσμοι 1. http://www.yolinux.com/tutorials/cpp-templates.html 2. http://www.yolinux.com/tutorials/linuxtutorialc++stl.html 3. http://www.sorting-algorithms.com/ 4. http://visualgo.net/sorting.html 5. https://www.cs.usfca.edu/~galles/visualization/comparisonsort.html 6. http://www.algomation.com/ 7. https://www.youtube.com/watch?v=t8g-iyghpea 8. https://www.cs.usfca.edu/~galles/visualization/search.html 9. http://www.programming-algorithms.net/article/40348/interpolation-search 10. https://dzone.com/articles/algorithm-week-interpolation [16]