Διάλεξη 28: O Αλγόριθμος Ταξινόμησης HeapSort Στην ενότητα αυτή θα μελετηθούν τα εξής επιμέρους θέματα: - Η διαδικασία PercolateDown, Δημιουργία Σωρού - O Αλγόριθμος Ταξινόμησης HeapSort - Υλοποίηση, Παραδείγματα Διδάσκων: Παναγιώτης Ανδρέου ΕΠΛ035 Δομές Δεδομένων και Αλγόριθμοι για Ηλ. Μηχ. Και Μηχ. Υπολ. 1
Διαδικασία Καθόδου PercolateDown Έστω ένας πίνακας Α[1..n] και μια τιμή i, θα ορίσουμε διαδικασία PercoladeDown(i), η οποία μετακινεί το στοιχείο Α[i] μέσα στον σωρό προς τα κάτω όσο χρειάζεται. Έστω ότι Α[i] = k. Θεωρούμε πως η i είναι άδεια θέση. Αν η άδεια θέση έχει παιδί που περιέχει στοιχείο μικρότερο του k και xείναι το μικρότερο τέτοιο παιδί, τότε μετακινούμε το στοιχείο του xστην κενή θέση και μετακινούμε την κενή θέση στο x. Επαναλαμβάνουμε την ίδια διαδικασία μέχρι τη στιγμή που η κενήθέσηδεν έχει παιδιά με στοιχεία μικρότερα του k. Τότε αποθηκεύουμε το k στην θέση αυτή. Ο χρόνος εκτέλεσης είναι ανάλογος του ύψους του κόμβου που αντιστοιχεί στη θέση i του σωρού. Δηλαδή, στη χείριστη περίπτωση, όπου i=n, Ο(lgn). ΕΠΛ035 Δομές Δεδομένων και Αλγόριθμοι για Ηλ. Μηχ. Και Μηχ. Υπολ. 2
Διαδικασία Καθόδου PercolateDown(συν.) Μη αναδρομική διαδικασία PercolateDown void PercolateDown(type A[], int n, int i) { type k = A[i]; int j; while( 2*i <=n ) { j = 2*i; if (j<n && A[j+1]<A[j]) j++; if (k > A[j]) { A[i] = A[j]; i=j; } else break; } A[i] = k; } ΕΠΛ035 Δομές Δεδομένων και Αλγόριθμοι για Ηλ. Μηχ. Και Μηχ. Υπολ. 3
Παράδειγμα Εκτέλεσης PercolateDown int A[]={-1, 13, 8, 15, 4, 7, 20, 18, 5, 2}; i=2, n=9, PercolateDown(A, 9, 2); k=8 Aν φανταστούμε τον πίνακα σαν δυαδικό δέντρο k=8 1. 13 4<7, k>4 13 2. 8 4 7 5 2 4. break Set to k 4 2 7 15 20 18 13 2<5, k>2 2:Move Up 15 20 18 3. 5 2 4 7 13 15 20 18 5. 4:Move Up 4 7 5 2 4 2 7 13 15 20 18 15 20 18 5 5 8 ΕΠΛ035 Δομές Δεδομένων και Αλγόριθμοι για Ηλ. Μηχ. Και Μηχ. Υπολ. 4
Παράδειγμα Εκτέλεσης PercolateDown int A[]={-1, 13, 8, 15, 4, 7, 20, 18, 5, 2}; i=2, n=9, PercolateDown(A, 9, 2); k=8 Aν φανταστούμε τον πίνακα σαν δυαδικό δέντρο 1. 2. 3. 4. 5. ΕΠΛ035 Δομές Δεδομένων και Αλγόριθμοι για Ηλ. Μηχ. Και Μηχ. Υπολ. 5
Διαδικασία DeleteMin(2) Αφαιρούμε το στοιχείο της ρίζας (είναι το μικρότερο κλειδί τουσωρού). Μεταφέρουμε το τελευταίο κλειδί στη ρίζα, και εφαρμόζουμε τη διαδικασία PercoladeDown(A, n, 1): type DeleteMin(HEAP* heap) { type min=null; type swap=null; if(!isemptyheap(heap)){ min = heap->contents[1]; swap(contents[1],contents[size]); heap->size --; PercolateDown(heap->contents, heap->size, 1); } return min; } Χρόνος Εκτέλεσης: O(h) = Ο(logn) ΕΠΛ035 Δομές Δεδομένων και Αλγόριθμοι για Ηλ. Μηχ. Και Μηχ. Υπολ. 6
Παράδειγμα DeleteMin 3 Delete Min Swap with last 28 Percolate Down 28 22 27 22 27 22 27 44 26 28 44 26 28 44 26 22<27, 28>22 22: Move up 22 26<44, 28>26 26: Move up 22 22 27 27 26 27 44 26 44 26 44 28 0 1 2 3 4 5 6 0 22 26 27 44 28 break Set to 28 ΕΠΛ035 Δομές Δεδομένων και Αλγόριθμοι για Ηλ. Μηχ. Και Μηχ. Υπολ. 7
Από πίνακες σε σωρούς Έστω πίνακας Α[1..n]. Μπορούμε να θεωρήσουμε τον πίνακα ως ένα πλήρες δυαδικό δένδρο με n κόμβους. Αν για μια τιμή i το αριστερό και το δεξί υπόδενδρο του i ικανοποιούντις ιδιότητες ενός σωρού, τότε, αν καλέσουμε τη διαδικασίαpercolatedown(a, n, i) θα έχουμε σαν αποτέλεσμα το υπόδενδρο πουριζώνει στη θέση i να ικανοποιεί τις ιδιότητες ενός σωρού. ΕΠΛ035 Δομές Δεδομένων και Αλγόριθμοι για Ηλ. Μηχ. Και Μηχ. Υπολ. 8
Κτίσιμο σωρού από ένα πίνακα Μπορούμε να μετατρέψουμε ένα πίνακα Α[1..n] σε ένα σωρό με διαδοχικήεφαρμογή της διαδικασίας PercoladeDown() από κάτω προς τα πάνω. Παρατήρηση: οι θέσεις > n/2 αντιστοιχούν σε φύλλα. void BuildHeap( int A[], int n) { for (int i=n/2; i>0; i--) PercolateDown(A,n,i); } Ορθότητα(αποδεικνύεται με τη μέθοδο της επαγωγής):μετά από την εφαρμογή της διαδικασίας PercoladeDown(A,n,i), τα υπόδενδρα που ριζώνουν στις θέσεις i,..., n, ικανοποιούν τις ιδιότητες σωρού. Ανάλυση του Χρόνου Εκτέλεσης:Ο ολικός χρόνος εκτέλεσης είναι ανάλογος τουαθροίσματος των υψών όλων των εσωτερικών κόμβων, το οποίο είναι Ο(n). ΕΠΛ035 Δομές Δεδομένων και Αλγόριθμοι για Ηλ. Μηχ. Και Μηχ. Υπολ. 9
Τι κάνει ο πιο κάτω αλγόριθμος; void mystery (type A[], int n) { BuildHeap(A, n); type swap; for (int i=n; i>1; i--){ swap (A[1], A[i]); PercolateDown(A, i-1, 1); } } ΕΠΛ035 Δομές Δεδομένων και Αλγόριθμοι για Ηλ. Μηχ. Και Μηχ. Υπολ. 10
Παράδειγμα Εκτέλεσης Διαδικασίας mystery Είσοδος, Α={ -, 34, 8, 64, 57, 32, 21} 34 8 64 57 32 21 Μετά την εκτέλεση της γραμμής BuildHeap 8 32 21 57 34 64 ΕΠΛ035 Δομές Δεδομένων και Αλγόριθμοι για Ηλ. Μηχ. Και Μηχ. Υπολ. 11
Παράδειγμα Εκτέλεσης Διαδικασίας mystery Μετά από την πρώτη επανάληψη του for 21 32 64 57 34 8 Μετά από την δεύτερη επανάληψη του for 32 34 64 57 21 8 ΕΠΛ035 Δομές Δεδομένων και Αλγόριθμοι για Ηλ. Μηχ. Και Μηχ. Υπολ. 12
Παράδειγμα Εκτέλεσης Διαδικασίας mystery Μετά από την τρίτη επανάληψη του for 34 57 64 32 21 8 Μετά από την τέταρτη επανάληψη του for 57 64 34 32 21 8 ΕΠΛ035 Δομές Δεδομένων και Αλγόριθμοι για Ηλ. Μηχ. Και Μηχ. Υπολ. 13
Παράδειγμα Εκτέλεσης Διαδικασίας mystery Μετά από την πέμπτη επανάληψη του for 64 57 34 32 21 8 Σε επίπεδο πίνακα - 64 57 34 32 21 8 ΕΠΛ035 Δομές Δεδομένων και Αλγόριθμοι για Ηλ. Μηχ. Και Μηχ. Υπολ. 14
Ο αλγόριθμος ταξινόμησης HeapSort H διαδικασία mysteryταξινομεί ένα πίνακα σε φθίνουσα σειρά. Αρχικά δημιουργεί ένα σωρό σε χρόνο Ο(n). Στη συνέχεια επαναλαμβάνει το εξής: αφαιρεί το μικρότερο στοιχείο(της ρίζας του σωρού) και το μετακινεί στο τέλος (εκτελεί τηνpercolatedown). Κάθε εκτέλεση της PercoladeDown χρειάζεται χρόνο της τάξης Ο(log n). Ολικός Χρόνος Εκτέλεσης: Ο(n log n) O αλγόριθμος ονομάζεται Heapsort Μπορούμε εύκολα να αλλάξουμε τον κώδικα ώστε να επιστρέφεται η λίστα σε αύξουσα σειρά. ΕΠΛ035 Δομές Δεδομένων και Αλγόριθμοι για Ηλ. Μηχ. Και Μηχ. Υπολ. 15
Άλλες διαδικασίες σε σωρούς Παρόλο που εύρεση του ελάχιστου κλειδιού σε ένα σωρό μπορεί να πραγματοποιηθεί σε σταθερό χρόνο, η εύρεση τυχαίου στοιχείου στηχειρότερη περίπτωση επιβάλλει διερεύνηση ολόκληρης της δομής(δηλαδή, είναι της τάξης Ο(n)). Αν όμως γνωρίζουμε τη θέση στοιχείων με κάποιο άλλο τρόπο, διαδικασίες σε σωρούς πραγματοποιούνται εύκολα, π.χ. οι πιο κάτω εκτελούνται σε χρόνο λογαριθμικό. Increase_Key(P,Δ), αυξάνει την προτεραιότητα του κλειδιού P,κατά Δ. Χρησιμοποιείται από χειριστές λειτουργικών συστημάτων για αύξηση της προτεραιότητας σημαντικών διεργασιών. Η συμμετρική διαδικασία Decrease_Key(P,Δ) συχνά εκτελείται αυτόματα σε λειτουργικά συστήματα σε περίπτωση που κάποια δουλειά χρησιμοποιεί υπερβολικά μεγάλη ποσότητα χρόνου του CPU. Remove(I), αφαιρεί τον κόμβο της θέσης Ι (χρήσιμη σε περίπτωση τερματισμού διαδικασίας). ΕΠΛ035 Δομές Δεδομένων και Αλγόριθμοι για Ηλ. Μηχ. Και Μηχ. Υπολ. 16