Δομές Δεδομένων & Αναζήτηση & Ταξινόμηση 1
Αναζήτηση Έχω έναν πίνακα Α με Ν στοιχεία. Πρόβλημα: Βρες αν το στοιχείο x ανήκει στον πίνακα Αν ο πίνακας είναι αταξινόμητος τότε μόνη λύση σειριακή αναζήτηση for (i=0; i<n; i++) if (A[i]==x) return i;//th thesh toy stoixeioy return -1; //-1 dhlonei apotyxia Χειρότερη και Μέση περίπτωση: O(N) 2
Δυαδική Αναζήτηση Αν ο πίνακας είναι ταξινομημένος μπορώ να εφαρμόσω δυαδική αναζήτηση (binary search)! ΜΕΘΟΔΟΛΟΓΙΑ - Πήγαινε στο μεσαίο στοιχείο του πίνακα (έστω Α[mid]) - Αν Α[mid]==x επέστρεψε επιτυχία - Αν Α[mid]<x τότε πήγαινε στη μέση του υποπίνακα mid+1..n-1 - Αν Α[mid]>x τότε πήγαινε στη μέση του υποπίνακα 0..mid-1 - Συνέχισε αναδρομικά 3
Δυαδική Αναζήτηση-Κώδικας #include <iostream> using namespace std; int binarysearch (int A[], int x, int left, int right){ int mid; if (left>right) return -1; mid=(left+right)/2; if (A[mid]==x) return mid; if (A[mid]<x) return binarysearch(a,x,mid+1,right); else return binarysearch(a,x,left,mid-1); } void main(){ int A[10]={0,1,2,3,4,5,6,7,8,9}; cout << binarysearch(a,8,0,9) << endl; cout << binarysearch(a,10,0,9) << endl; } 4
Δυαδική Αναζήτηση-Ανάλυση Χειρότερη περίπτωση: To στοιχείο δε βρίσκεται στον πίνακα! Μας ενδιαφέρει το πλήθος συγκρίσεων που γίνονται. Σε κάθε κλήση της αναδρομής ο αλγόριθμος κάνει μια σύγκριση και κατόπιν συνεχίζει για το μισό πίνακα που απομένει. Έστω Τ(Ν) η πολυπλοκότητα για μέγεθος πίνακα Ν. Τότε έχω Τ(Ν)<=Τ( N / 2 ) +1 με αρχική τιμή Τ(1)=1 Για τη λύση της αναδρομής διακρίνω 2 περιπτώσεις: - To N είναι δύναμη του 2 - Το Ν δεν είναι δύναμη του 2 5
Δυαδική Αναζήτηση-Ανάλυση Αν το Ν είναι δύναμη του 2 τότε έχω: T(N) <= T(N/2) +1 T(N/2) <= T(N/4) +1 T(N/4) <= T(N/8) + 1.. T(N/2 logn-1 ) <= T(N/2 logn ) + 1 Αθροίζοντας παίρνω Τ(Ν) <= logn + 1 6
Δυαδική Αναζήτηση-Ανάλυση Αν το Ν δεν είναι δύναμη του 2 αποδεικνύω επαγωγικά ότι ισχύει Τ(Ν)<= logn + 1 - Για Ν=3 ισχύει αφού χρειάζομαι 2 συγκρίσεις (Τ(Ν)=2 ) - Έστω ότι ισχύει για k<ν - Θα δείξω για k=n Έχω: T(N) <= T( N / 2 ) + 1 <= (από επαγωγική υπόθεση) log N / 2 + 1 + 1 <= log(( N 1) / 2) +1 +1 <= log( N 1) + 1 <= log N + 1 Επομένως ο αλγόριθμος στη χειρότερη περίπτωση (όπου δε βρίσκουμε αυτό που αναζητούμε) έχει πολυπλοκότητα Ο(logN). 7
Δυαδική Αναζήτηση-Ανάλυση Μέση Περίπτωση: Στη μέση περίπτωση το στοιχείο μπορεί να βρίσκεται στον πίνακα σε οποιαδήποτε θέση του ή και να μη βρίσκεται. - Υπάρχουν 2Ν + 1 καταστάσεις στις οποίες μπορεί να τερματίσει η αναζήτηση. - Οι Ν αντιστοιχούν σε επιτυχή αναζήτηση (μία για κάθε θέση του πίνακα που μπορεί να βρεθεί το στοιχείο) - Οι υπόλοιπες Ν+1 αντιστοιχούν στις θέσεις που μπορεί να τερματίσει η αναζήτηση ανεπιτυχώς (Ν-2 ενδιάμεσα των στοιχείων και 2 στις άκρες του πίνακα) Αν θεωρήσω ισοπίθανα τα 2Ν+1 ενδεχόμενα αθροίζοντας προκύπτει πάλι Ο(logN) (η απόδειξη αφήνεται) 8
Αναζήτηση Παρεμβολής (Interpolation Search) Γενικώς, αν τα στοιχεία του πίνακα είναι οποιασδήποτε μορφής (αρκεί να ορίζεται σχέση διάταξης) πχ. αλφαριθμητικά, μπορεί να αποδειχτεί ότι δεν υπάρχει αλγόριθμος που να λύνει το πρόβλημα της αναζήτησης σε χρόνο λιγότερο του Ο(logN). Στην ειδική περίπτωση που τα στοιχεία είναι αριθμοί μπορούμε να θεωρήσουμε το χρόνο στη μέση περίπτωση. Μεθοδολογία Αναζήτησης Παρεμβολής Ίδια με Δυαδική αναζήτηση (Binary Search) μόνο που σαν mid επιλέγεται το: x A[ left] ( right left) left A[ right] A[ left] 9
Αναζήτηση Παρεμβολής (Interpolation Search) ΠΑΡΑΔΕΙΓΜΑ 1 Έστω πίνακας Α={2,4,6,...,20} και x = 20 Τότε στην πρώτη κλήση επιλέγεται: x A[ left] ( right A[ right] A[ left] mid=(20-2)/(20-2) * (9-0) + 0 δηλ. 1*9+0 δηλ. η θέση 9 left) left Με άλλα λόγια ο αλγόριθμος θα βρει κατευθείαν το ζητούμενο κάνοντας μια μόνο σύγκριση (σε αντίθεση με τη δυαδική αναζήτηση) Γενικά αν τα στοιχεία του πίνακα αντιπροσωπεύουν αριθμητική πρόοδο η αναζήτηση παρεμβολής έχει πολυπλοκότητα Ο(1). 10
Αναζήτηση Παρεμβολής (Interpolation Search) ΠΑΡΑΔΕΙΓΜΑ 2 Έστω πίνακας Α={0,1,2,3,4,5,6,7,8,9000} και x = 8 Τότε στην πρώτη κλήση επιλέγεται: x A[ left] ( right left) left A[ right] A[ left] mid=(8-0)/(9000-0) * (9-0) + 0 δηλ. 72/9000 δηλ. η θέση 0 Η δεύτερη κλήση θα είναι για left =1 mid=8-1/9000-1 *(9-1) + 1 = 56/8999 +1 δηλ η θέση 1 Κατόπιν θα ελεγχθεί η θέση 2,3,4...8 Με άλλα λόγια στη χειρότερη περίπτωση ο αλγόριθμος έχει πολυπλοκότητα Ο(Ν) Στη μέση περίπτωση μπορεί να αποδειχτεί ότι είναι Ο(loglogN) 11
Ταξινόμηση Οι αλγόριθμοι που λύνουν το πρόβλημα της ταξινόμησης ενός πίνακα εμπίπτουν σε δύο κατηγορίες: - Βασιζόμενους σε συγκρίσεις στοιχείων (συγκριτικοί) - Μη συγκριτικοί αλγόριθμοι Στην πρώτη κατηγορία ανήκουν οι: - Selection Sort (ταξινόμηση με επιλογή) - Insertion Sort (ταξινόμηση με εισαγωγή) - Bubble Sort (ταξινόμηση φυσαλίδας) - Quick Sort (ταχεία ταξινόμηση) - Heap Sort (ταξινόμηση σωρού) 12
Ταξινόμηση με Επιλογή (Selection Sort) ΜΕΘΟΔΟΛΟΓΙΑ - Ψάξε όλον τον πίνακα για να βρεις το μικρότερο στοιχείο - Αντιμετάθεσε με το πρώτο - Επανέλαβε για το κομμάτι του πίνακα που απομένει void SelectionSort(int A[],int Ν){ int min; for (int i=0; i<ν-1; i++){ //το τελευταίο στοιχείο δε min=i; //χρειάζεται ταξινόμηση for (j=i+1; j<ν, j++) if A[j]<A[min] min=j; swap(a[i], A[min]); } 13
Ταξινόμηση με Επιλογή (Selection Sort) ΠΑΡΑΔΕΙΓΜΑ 4 3 5 6 2 3 1 1 3 5 6 2 3 4 125 6 3 3 4 1 2 3 6 5 3 4 1 2 3 3 5 6 4 1 2 3 3 4 65 1 2 3 3 4 5 6 ΠΟΛΥΠΛΟΚΟΤΗΤΑ Το πλήθος των συγκρίσεων που κάνει ο αλγόριθμος είναι i=0 (Ν-1) i=1 (N-2). i=n-1 0 Άρα συνολικά 1+2 +... +(Ν-1) = Ν(Ν-1)/2 = Ο(Ν 2 ) 14
Ταξινόμηση με εισαγωγή (Insertion Sort) ΜΕΘΟΔΟΛΟΓΙΑ Εισάγουμε ένα- ένα τα στοιχεία στη σωστή τους θέση Ο αλγόριθμος λειτουργεί σε βήματα Αρχικά (βήμα 0) μόνο ο πίνακας Α[0...0] (δηλ. το στοιχείο Α[0]) είναι ταξινομημένο Στο βήμα 1 προσθέτουμε το στοιχείο Α[1] (αντιμεταθέτοντας με το Α[0] αν χρειάζεται) Γενικά στο βήμα i το κομμάτι του πίνακα Α[0...i-1] είναι ταξινομημένο και βάζουμε το στοιχείο Α[i] στη σωστή του θέση έτσι ώστε με το πέρας της φάσης το κομμάτι του πίνακα Α[0...i] να είναι ταξινομημένο 15
Ταξινόμηση με εισαγωγή (Insertion Sort) void InsertionSort(int A[], int N){ for (int i=1; i<n; i++) for (int j=i; (j>0)&&(a[j]<a[j-1]); j--) swap(a[j], A[j-1]); } ΠΑΡΑΔΕΙΓΜΑ 4 3 5 6 2 3 1 4 3 5 6 2 3 1 3 4 5 6 2 3 1 3 4 5 6 2 3 1 3 4 5 6 2 3 1 2 3 4 5 6 3 1 2 3 3 4 5 6 1 1 2 3 3 4 5 6 16
Ταξινόμηση με εισαγωγή (Insertion Sort) ΠΟΛΥΠΛΟΚΟΤΗΤΑ ΧΕΙΡΟΤΕΡΗΣ ΠΕΡΙΠΤΩΣΗΣ Στη χειρότερη περίπτωση ο πίνακας είναι αντίστροφα ταξινομημένος. Οι συγκρίσεις που θα εκτελεστούν είναι: 1 + 2 +. +N-1 δηλ. Ο(Ν 2 ) Παρατηρήστε ότι όταν ο πίνακας είναι ήδη ταξινομημένος οι συγκρίσεις που απαιτούνται είναι Ο(Ν) (σε αντίθεση με πχ. το Selection Sort που εξακολουθεί να είναι Ο(Ν 2 )) 17
Ταξινόμηση με εισαγωγή (Insertion Sort) ΠΟΛΥΠΛΟΚΟΤΗΤΑ ΜΕΣΗΣ ΠΕΡΙΠΤΩΣΗΣ Στη μέση περίπτωση κατά τη διάρκεια της φάσης i δηλ. όταν πάμε να βάλουμε το στοιχείο Α[i] στον ήδη ταξινομημένο πίνακα Α[0...i-1] είναι ισοπίθανο το να μπει το Α[i] σε οποιαδήποτε από της i+1 δυνατές θέσεις. Αν μπει στη θέση i θα έχω κάνει μια σύγκριση Αν στη i-1, 2 συγκρίσεις (και 1 αντιμετάθεση) Στη i-2 3, κ.ο.κ Συνολικά δηλαδή κατά την ένθεση του i-οστού στοιχείου θα έχω κόστος = 1/i+1 + 2/i+1 + 3/i+1 +.. + i/i+1 = i/2 Άρα το πλήθος των συγκρίσεων για τον αλγόριθμο θα είναι 1/2 + 2/2 + 3/2 +... + (N-1)/2 = Ν(Ν-1)/4 => Ο(Ν 2 ) 18
BubbleSort-Ταξινόμηση φυσαλίδας ΜΕΘΟΔΟΛΟΓΙΑ Σάρωνε τον πίνακα από αριστερά προς τα δεξιά αντιμεταθέτοντας γειτονικά στοιχεία που είναι εκτός διάταξης. Συνέχισε μέχρι να ταξινομηθεί ο πίνακας. Το όνομα του αλγορίθμου προκύπτει από το γεγονός ότι το μεγαλύτερο στοιχείο σε κάθε πέρασμα οδηγείται προς τα δεξιά του πίνακα (σαν φυσαλίδα που ανεβαίνει προς τα πάνω) void BubbleSort(int A[], int N){ for (int i=1; i<n-1; i++) for (int j=0; j<n-i; j++) if (A[j]>A[j+1]) swap(a[j], A[j+1]); } Για πιο αποδοτική υλοποίηση μπορούμε να βάλουμε ένα flag για να ελέγχουμε αν σε κάποιο πέρασμα δεν έγινε καμιά αντιμετάθεση (ο πίνακας τότε έχει ταξινομηθεί) 19
ΠΑΡΑΔΕΙΓΜΑ 435 6 2 3 1 3 4 2315 6 3 4 5 6 2 3 1 3 4 2 3 1 5 6 3 4 5 6 2 3 1 3 2 4 3 1 5 6 3 4 5 6 2 3 1 3 2 3 415 6 3 4 5 2 6 3 1 3 2 3 1 4 5 6 3 4 5 2 3 6 1 3 2 3 1 4 5 6 3 4 5 2 3 1 6 2 3 3 1 4 5 6 3 4 52316 233 1 4 5 6 3 4 5 2316 2313 4 5 6 3 4 5 2 3 1 6 2 3 1 3 4 5 6 3 4 2 5 3 1 6 2 3 1 3 4 5 6 3 4 2 3 5 1 6 2 1 3 3 4 5 6 3 4 2 3 1 5 6 2 1 3 3 4 5 6 1 233456 BubbleSort 20
BubbleSort ΠΟΛΥΠΛΟΚΟΤΗΤΑ Στη χειρότερη περίπτωση συγκρίσεις/αντιμεταθέσεις = Ν-1 + Ν-2 +... +1 => Ο(Ν 2 ) 21