Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

1ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι Επανάληψη: Δομές Δεδομένων και Αλγόριθμοι Επαναληπτικό Υλικό Ενδιάμεσης Εξέτασης.

Παρόμοιες παρουσιάσεις


Παρουσίαση με θέμα: "1ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι Επανάληψη: Δομές Δεδομένων και Αλγόριθμοι Επαναληπτικό Υλικό Ενδιάμεσης Εξέτασης."— Μεταγράφημα παρουσίασης:

1 1ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι Επανάληψη: Δομές Δεδομένων και Αλγόριθμοι Επαναληπτικό Υλικό Ενδιάμεσης Εξέτασης

2 Εργαλεία Εκτίμησης Πολυπλοκότητας Ορισμός: Θεωρούμε συνάρτηση Τ(n). Ορίζουμε 1. Τ(n)  Ο( f (n) ), αν υπάρχουν σταθερές c>0 και n 0  1 ώστε Τ(n)  c  f(n), για κάθε n  n Τ(n)  Ω( f(n) ), αν υπάρχουν σταθερές c>0 και n 0  1 ώστε Τ(n)  c  f(n), για κάθε n  n Τ(n)  Θ( f(n) ), αν Τ(n)  Ο(f(n)) και Τ(n)  Ω(f(n)). Αν Τ(n)  Ο(f (n)), τότε λέμε πως η συνάρτηση Τ είναι της τάξεως f(n). Αν Τ(n)  Ω(f (n)), τότε λέμε πως η Τ είναι της τάξεως ωμέγα της f (n). Αν Τ(n)  Θ(f (n)), τότε λέμε πως η Τ είναι της τάξεως θήτα της f (n). (λέγεται και ακριβής τάξη) ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι2 f(n)μπορεί να είναι οποιαδήποτε συνάρτηση => n, n 2, logn

3 Παραδείγματα Βig-O Παράδειγμα 1 7n-3 είναι Ο(n) Τεκμηρίωση Πρέπει να δείξουμε ότι υπάρχει c>0,n o  1 έτσι ώστε: 7n-3  c*n, Για c=7, n o  1 η παραπάνω ανισότητα ικανοποιείται, επομένως 7n-3 είναι Ο(n) π.χ., 7*1-3  7*1 (4  7) 7*2-3  7*2 (11  14) 7*3-3  7*3 (18  21) κοκ ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι3

4 Παραδείγματα Βig-O Παράδειγμα 2 20n 3 +10nlogn+5 είναι Ο(n 3 ) Τεκμηρίωση Πρέπει να δείξουμε ότι υπάρχει c>0,n o  1 έτσι ώστε 20n 3 +10nlogn+5  c* n 3 20n 3 +10nlogn+5  20n 3 +10n 3 +5n 3 20n 3 +10n 3 +5n 3  35n 3 (n>1) Για c=35, n o =1 η παραπάνω ανισότητα ικανοποιείται, επομένως 20n 3 +10nlogn+5 είναι Ο(n 3 ) ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι4

5 Ιδιότητες Big-O Στις περισσότερες περιπτώσεις μας ενδιαφέρει μόνο το άνω φράγμα (χείριστη περίπτωση εκτέλεσης ενός αλγορίθμου), δηλαδή το O. Η συνάρτηση O έχει τις ακόλουθες ιδιότητες: 1.O(X+Y) = O(X) + O(Y)  max (O(X),O(Y)) 2.O(X*Y) = O(X)*O(Y)  O(X * Y) 3.O(c * X) = O(X) (c σταθερά > 0 ) Παράδειγμα Έστω ότι ένας αλγόριθμος έχει την ακόλουθη συνάρτηση αύξησης f(n) = 16n 2 logn + 3n + 7 Τότε απλοποιούμε την συνάρτηση αύξησης ως εξής = 16n 2 logn (διαγράφουμε τις μικρότερες τιμές του n – Κανόνας 1) = n 2 logn (διαγράφουμε τις σταθερές – Κανόνας 3) δηλαδή f(n)  Ο(n 2 logn) ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι5 1< logn< n< nlogn< n 2 < n 3 < 2 n < n!< n n Ισχύει η ακόλουθη σειρά “<“ είναι ασυμπτωτικά μικρότερο

6 Παραδείγματα Ιδιοτήτων Big-O Παραδείγματα: 15n + 32  Ο(n)200*(n+n 7 )  Ο(n 7 ) 1324  Ο(1)(n+n 7 )*m 2  Ο(n 7 m 2 ) 5n 2  O(n 2 )5nlgn + 4  Ο(nlgn) Προφανώς, κατά την ανάλυση αλγορίθμων στόχος μας είναι αυτά τα όρια να είναι όσο το δυνατό πιο ακριβή. Εάν 7n-4 είναι Ο(n), τότε προφανώς 7n-4 είναι Ο(n 2 ), Ο(n 3 ), Ο(n 4 ), …. Ωστόσο, οι χαρακτηρισμοί big-O πρέπει να είναι όσο το δυνατό πιο μικρής τάξης. (δηλαδή το Ο(n) είναι το πιο στενό άνω όριο). ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι6

7 Παράδειγμα Ανάλυσης Υποθέστε ότι θέλετε να βρείτε την θέση κάποιου στοιχείου K σε μια λίστα Χ[] (μήκους n). int index( int X[],int n,int k){ 1 int i=0; 2 while (i < n) { 3 if (X[i]==k) // item found 4 return i; 5 i+=1; } 6 return error; } Μέγεθος δεδομένων εισόδου: n Χειρότερη Περίπτωση: εξέταση όλων των στοιχείων (π.χ. ψάχνουμε το 5) t(n) = n => O(n) Βέλτιστη Περίπτωση: το στοιχείο βρίσκετε στην θέση 1 (π.χ. ψάχνουμε το 3) t(n) = 1 => Ω(1) Άρα εκτός από το μέγεθος εισόδου και το ίδιο το στιγμιότυπο εισόδου παίζει κάποιο σημαντικό ρόλο στην ανάλυση κάποιου αλγορίθμου (η συνάρτησης) ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι Χ n 7? => θέση 2

8 8ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι Διάλεξη 05: Αφηρημένοι Τύποι Δεδομένων Στην ενότητα αυτή θα μελετηθούν τα εξής επιμέρους θέματα: - Αφηρημένοι Τύποι Δεδομένων (ΑΤΔ) - Οι ΑΤΔ Στοίβα και Ουρά - Υλοποίηση των ΑΤΔ Στοίβα και Ουρά

9 Λίστες (συν.) Οι πιο σημαντικές πράξεις στον ορισμό ενός ΑΤΔ-λίστας είναι η εισαγωγή και η εξαγωγή κόμβων στα άκρα της λίστας. Με βάση την προδιαγραφή αυτών των πράξεων, διακρίνουμε δύο βασικούς τύπους λίστας που έχουν πολλές και σημαντικές εφαρμογές σε κλάδους επιστημών που χρησιμοποιούν υπολογιστικές μεθόδους. Είναι οι ακόλουθες: Η στοίβα (stack) που έχει μόνο ένα άκρο προσιτό για εισαγωγές και εξαγωγές κόμβων. (LIFO – Last In First Out) Η ουρά (queue) όπου γίνονται εισαγωγές στο ένα άκρο και εξαγωγές από το άλλο. (FIFO – First In First Out) Υπάρχουν και άλλοι ΑΤΔ-λίστας μικρότερης πρακτικής σημασίας, όπως: ουρά με δύο άκρα, πολλαπλή στοίβα, κλπ. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι9

10 ΑΤΔ Λίστα 3 : Κυκλική Ουρά Για λόγους χώρου μνήμης μπορούμε να πραγματοποιήσουμε την ουρά με μια κυκλική διάταξη των λέξεων της μνήμης. Δηλαδή θα θεωρούμε ότι η περιοχή μνήμης δεν αρχίζει με τη λέξη Α[0] και τελειώνει με τη λέξη Α[n-1], αλλά ότι μετά την Α[n-1] ακολουθεί η Α[0]. Έτσι μετά από μια ακολουθία εισαγωγών και εξαγωγών η ουρά μας πιθανόν να έχει την πιο κάτω μορφή όπου θεωρούμε ότι η αρχή της ουράς βρίσκεται στη θέση k και το τέλος της ουράς στη θέση 4. k ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι10 A[0] A[1] A[n-1] A[n-2]...

11 ΑΤΔ Λίστα 4 : Ουρές με Δύο Άκρα Ο ΑΤΔ ‘ουρά με δύο άκρα είναι παρόμοιος με το ΑΤΔ ουρά, με τη διαφορά ότι έχει δύο άκρα και επιτρέπει εισαγωγές και εξαγωγές και στα δύο. Μια ουρά δύο άκρων ορίζεται ως μια λίστα συνοδευόμενη από τις πιο κάτω πράξεις: makeEmpty(), isEmpty() insert(x)εισήγαγε το στοιχείο x στο μπροστινό άκρο της Q eject()διέγραψε τον κόμβο στο πίσω άκρο της Q enQueue (x)εισήγαγε τον στοιχείο x στο πίσω μέρος της Q. deQueue()διέγραψε τον κόμβο στο μπροστινό άκρο της Q front(Q) δώσε τον κόμβο στο μπροστινό άκρο της Q rear(Q)δώσε τον κόμβο στο πίσω άκρο της Q ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι11

12 12ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι Διάλεξη 06: Συνδεδεμένες Λίστες & Εφαρμογές Στοιβών και Ουρών Στην ενότητα αυτή θα μελετηθούν τα εξής επιμέρους θέματα: - Υλοποίηση ΑΤΔ με Συνδεδεμένες Λίστες - Εφαρμογή Στοιβών 1: Αναδρομικές συναρτήσεις - Εφαρμογή Στοιβών 2: Ισοζυγισμός Παρενθέσεων - Εφαρμογή Στοιβών 3: Αντίστροφος Πολωνικός Συμβολ. - Εφαρμογή Ουρών 1: Διερεύνηση κατά Πλάτος

13 Συνδεδεμένες Λίστες Μία απλή συνδεδεμένη λίστα είναι μία συμπαγής δομή δεδομένων η οποία αποτελείται από μία ακολουθία κόμβων. Κάθε κόμβος αποτελείται από: Δεδομένα Δείκτη/Αναφορά προς τον επόμενο κόμβο της λίστας Επίσης μπορεί να χρησιμοποιηθεί μία βοηθητική δομή που να αποθηκεύει χρήσιμες πληροφορίες, π.χ., αναφορά στον πρώτο κόμβο, μέγεθος των στοιχείων, κτλ. datanextdatanext datanext NULL ADT Size=3 head node datanext node ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι13

14 Στοίβα ως Συνδεδεμένη Λίστα Μπορούμε να υλοποιήσουμε μία Στοίβα με μία απλά συνδεδεμένη λίστα Κάθε κόμβος αποτελείται από ένα στοιχείο (στοιχεία της στοίβας) και από ένα δείκτη (προς τον επόμενο κόμβο της στοίβας). Η κορυφή της στοίβας είναι ο πρώτος κόμβος της λίστας, Χρησιμοποιούμε μια μεταβλητή για να φυλάγουμε στοιχεία σχετικά με τη στοίβα π.χ. μέγεθος (size) και δείκτη προς την κορυφή της στοίβας (head) που βρίσκεται και το στοιχείο top. datanextdatanext datanext NULL STACK Size=3 head node top ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι14

15 Υλοποίηση Στοίβας με Συνδεδεμένη Λίστα public class Stack implements IStack private class StackNode { private E obj; private StackNode next; StackNode(E obj, StackNode head) { this.obj = obj; this.next = head; } public E getElement(){ return this.obj; } private StackNode head; private int size; public Stack() { head = null; size=0; } public boolean isEmpty(){ return this.size==0; } ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι15 public void makeEmpty(){ this.head = null; this.size=0; } public int size() { return this.size; } public E top() { return isEmpty()? null : head.getElement(); } public void push(E obj) { StackNode newNode = new StackNode (obj, head); this.head = newNode; size+=1; } public void pop() { if (!isEmpty()) { this.head = this.head.next; size-=1; } Με χρήση εσωτερικής κλάσης για τους κόμβους

16 Ουρά ως Συνδεδεμένη Λίστα Μπορούμε να υλοποιήσουμε μία Ουρά με μία απλά συνδεδεμένη λίστα Κάθε κόμβος αποτελείται από ένα στοιχείο (στοιχεία της ουράς) και από ένα δείκτη (προς τον επόμενο κόμβο της ουράς). Το πρώτο στοιχείο αποθηκεύεται στον πρώτο κόμβο Κάθε νέο στοιχείο αποθηκεύεται στο πίσω μέρος Χρησιμοποιούμε μια μεταβλητή για να φυλάγουμε στοιχεία σχετικά με την ουρά π.χ., μέγεθος (size) και δείκτες προς την κορυφή της ουράς (head) ) που βρίσκεται και το στοιχείο front και προς το τελευταίο στοιχείο της ουράς (rear). datanextdatanext datanext NULL QUEUE Size=3 head node frontrear ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι16

17 17ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι Διάλεξη 07: Λίστες Ι – Υλοποίηση & Εφαρμογές Στην ενότητα αυτή θα μελετηθούν τα εξής επιμέρους θέματα: - Ευθύγραμμες Απλά Συνδεδεμένες Λίστες (εισαγωγή, εύρεση, διαγραφή) - Ευθύγραμμες Διπλά Συνδεδεμένες Λίστες - Σύγκριση Συνδεδεμένων Λιστών με Πίνακες

18 18ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι Διάλεξη 08: Λίστες ΙΙ – Κυκλικές Λίστες Στην ενότητα αυτή θα μελετηθούν τα εξής επιμέρους θέματα: - Κυκλικές Απλά Συνδεδεμένες Λίστες - Κυκλικές Διπλά Συνδεδεμένες Λίστες

19 Κυκλικές Απλά Συνδεδεμένες Λίστες Μια κυκλική λίστα μπορεί να παίξει το ρόλο της ουράς, της οποίας και τα δύο άκρα είναι προσιτά με τη βοήθεια ενός μόνο δείκτη. Το πίσω άκρο, δηλαδή το άκρο όπου γίνονται οι εισαγωγές, είναι αυτό που δείχνεται από τον δείκτη στη λίστα (rear). Άρα οι εξαγωγές γίνονται ακριβώς μετά από τον κόμβο που δείχνεται από τον δείκτη rear. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι19 datanextdatanext datanext C-LIST Size=3 head node rear

20 Το πρόβλημα του Josephus Titus Flavius Josephus (37 – 100 μ. Χ.) N άτομα τοποθετούνται σε έναν κύκλο Αφαιρούμε το M-οστό άτομο, για κάποιο δοσμένο Μ (ξεκινώντας από το 1) Ξεκινώντας από Μ+1 αφαιρούμε πάλι το Μ- οστό άτομο κ.ο.κ. μέχρι να μείνει μόνο ένα άτομο Josephus(N,M): το άτομο που θα μείνει στο τέλος ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι Josephus(9,5)

21 Κυκλικά Απλά Συνδεδεμένης Λίστα (συν.) Άμεση λύση με χρήση κυκλικής λίστας Κατασκευή λίστας N κόμβων Ο τελευταίος κόμβος δείχνει στον πρώτο Διατρέχουμε τη λίστα μέχρι να αδειάσει Κυκλική διάσχιση χωρίς ειδικό κώδικα Διαγράφουμε το M-οστό στοιχείο κάθε φορά Εύκολη αφαίρεση στοιχείων ακολουθώντας δείκτες Δεν υπάρχει αλλαγή στις δομές (κλάσεις), μόνο στις συναρτήσεις διαγραφής και εισαγωγής Αναθέτουμε στον τελευταίο κόμβο να δείχνει στον πρώτο ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι21

22 Το πρόβλημα του Josephus: Υλοποίηση class Node { int val; Node next; Node(int v) { val = v; } } public class Josephus { public static void main(String[] args) { int N = 9; int M = 5; Node t = new Node(1); Node x = t; // t στην αρχή for (int i = 2; i <= N; i++) { x.next = new Node(i); x = x.next; } x.next = t;// τελευταίος κόμβος δείχνει την αρχή while (x != x.next) { for (int i = 1; i < M; i++) x = x.next; System.out.println("Executing " + x.next.val); x.next = x.next.next; // διαγραφή } System.out.println("Survivor is " + x.val); } ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι22

23 Το πρόβλημα του Josephus: Υλοποίηση (συν.) Γενικά μπορούμε να υλοποιούμε λίστες με πίνακες (δεν είναι πάντα βολικό όμως) Χρειαζόμαστε 2 πίνακες: val[i]: στοιχείο κόμβου i next[i]: δείκτης επόμενου κόμβου Διαγραφή κόμβου γίνεται με ενημέρωση του next[] next[x] = next[next[x]] ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι23

24 24 ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι Διάλεξη 09: Αλγόριθμοι Ταξινόμησης I Στην ενότητα αυτή θα μελετηθούν τα εξής επιμέρους θέματα: - Οι αλγόριθμοι ταξινόμησης: Α. SelectionSort – Ταξινόμηση με Επιλογή Β. InsertionSort – Ταξινόμηση με Εισαγωγή Γ. MergeSort – Ταξινόμηση με Συγχώνευση

25 A. Ταξινόμηση με Επιλογή - Selection Sort Η Ταξινόμηση με Επιλογή (Selection Sort) βασίζεται στα ακόλουθα τρία βήματα: 1.επιλογή του ελάχιστου στοιχείου 2.ανταλλαγή με το i-οστό στοιχείο (i είναι μια μεταβλητή που αυξάνεται κατά ένα). 3.επανάληψη των βημάτων 1 και 2 για τα υπόλοιπα στοιχεία. Το ελάχιστο μεταξύ i στοιχείων μπορεί να βρεθεί με τη χρήση ενός while-loop, σε χρόνο Ο(i). Άρα ο χρόνος εκτέλεσης του Selection Sort είναι: ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι25

26 Ταξινόμηση με επιλογή: SelectionSort SelectionSort: ο αλγόριθμος αυτός ταξινομεί μία λίστα με στοιχεία. Σε κάθε βήμα i βρίσκει το i-οστό πιο μικρό στοιχείο και το τοποθετεί στην θέση i. Παράδειγμα: int x = {4, 8, 2, 1, 3, 5}; swap Βήμα 1 Βήμα 2 Βήμα 3 Βήμα 4 Βήμα 5 Βήμα 6 ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι26

27 Ταξινόμηση με επιλογή: SelectionSort (συν.) Πρότυπο Συνάρτησης void selectionSort(int x[], //ο πίνακας int length) //το μέγεθος του x Αλγόριθμος Αρχικοποίησε μία μεταβλητή min_index η οποία θα αποθηκεύει τη θέση του ελάχιστου αριθμού Με ένα βρόγχο for που θα ελέγχει ένα ένα τα στοιχεία του πίνακα (i

28 SelectionSort: Παράδειγμα Εκτέλεσης Θέση Αρχικός Πίνακας Με i= Με i= Με i= Με i= Με i= ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι28 Στοιχείο που θα εισαχθεί στην θέση i min_index

29 SelectionSort: Υλοποίηση ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι29 void SelectionSort(int A[]) { int n = A.length; int min_index; int tmp; for(int i=0; i

30 SelectionSort: Ανάλυση Χρόνου Εκτέλεσης void SelectionSort(){ … for (i=0; i

31 B. Ταξινόμηση με Εισαγωγή - Insertion Sort Η Ταξινόμηση με Εισαγωγή (InsertionSort) εισάγει ένα- ένα τα στοιχεία του συνόλου που εξετάζεται, στη σωστή τους θέση. Στη φάση i: 1.υποθέτουμε πως ο πίνακας A[0..(i-1)] είναι ταξινομημένος, 2.εισάγουμε το στοιχείο Α[i] στην ακολουθία Α[0..(i-1)] στη σωστή θέση. Αυτό επιτυγχάνεται μετακινώντας όλα τα στοιχεία που είναι μεγαλύτερα του Α[i] μια θέση δεξιά. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι31

32 B. Ταξινόμηση με Εισαγωγή - Insertion Sort (συν.) Στη φάση i: 1.υποθέτουμε πως ο πίνακας A[0..(i-1)] είναι ταξινομημένος, 2.εισάγουμε το στοιχείο Α[i] στην ακολουθία Α[0..(i-1)] στη σωστή θέση. Αυτό επιτυγχάνεται μετακινώντας όλα τα στοιχεία που είναι μεγαλύτερα του Α[i] μια θέση δεξιά. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι

33 InsertionSort: Παράδειγμα Εκτέλεσης Θέση Αρχικός Πίνακας Με i= Με i= Με i= Με i= Με i= ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι33 Στοιχείο που θα εισαχθεί στην θέση i min_index

34 InsertionSort: Υλοποίηση ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι34 void InsertionSort(int A[]){ int n = x.length; int index, i, j; for (i=1; i < n; i++) { index = A[i]; for (j=i; j>0; j--){ if (A[j-1] <= index) { break; } A[j] = A[j-1]; } A[j] = index; } Τρέχον στοιχείο εισαγωγής θέλουμε να μετακινήσουμε μόνο τα A[j-1] > index τοποθέτηση στοιχείου μετακίνηση στοιχείων προς δεξιά A[j-1] j=i index=9

35 Insertion Sort: Παράδειγμα Εκτέλεσης 2 BEFORE:[8,4,8,43,3,5,2,] (Το κόκκινο δείχνει τα ταξινομημένα στοιχεία) i:1(index:4) >8 (“>” Δείχνει τις μετακινήσεις) [4,8,8,43,3,5,2,] (Νέος Πίνακας) i:2(index:8) (Τίποτα δεν μετακινείται) [4,8,8,43,3,5,2,] i:3(index:43) (Τίποτα δεν μετακινείται) [4,8,8,43,3,5,2,] i:4(index:3) >43>8>8>4 [3,4,8,8,43,5,2,] i:5(index:5) >43>8>8 [3,4,5,8,8,43,2,] i:6(index:2) >43>8>8>5>4>3 [2,3,4,5,8,8,43,] AFTER:[2,3,4,5,8,8,43,] ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι35

36 InsertionSort: Ανάλυση Χρόνου Εκτέλεσης void InsertionSort(){ … for (i=1; i0; j--){ sum++; } Εξωτερικός Βρόγχος Εσωτερικός Βρόγχος Εσωτερικός Βρόγχος: Εξωτερικός Βρόγχος: ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι36

37 Σύγκριση InsertionSort και SelectionSort Υπάρχουν δυο κριτήρια: Βήματα (μέχρι να βρω ένα στοιχείο) και Μετακινήσεις (όταν το βρω, πόσα swap κάνω). Ο αλγόριθμος Selection sort απαιτεί πάντα Ο(n²) βήματα (δεν είναι δυνατή η γρήγορη έξοδος από τους βρόχους), έτσι η βέλτιστη περίπτωση είναι η ίδια με τη χείριστη περίπτωση. Στον αλγόριθμο Insertion Sort, είναι δυνατό να βγούμε από το δεύτερο βρόχο γρήγορα. Στη βέλτιστη περίπτωση (ο πίνακας είναι ήδη ταξινομημένος), ο χρόνος εκτέλεσης είναι της τάξης Ω(n) βήματα. Παρά τούτου, το Selection Sort είναι πιο αποδοτικός αν κρίνουμε τους αλγόριθμους με βάση τον αριθμό των μετακινήσεων (swaps) που απαιτούν: το selection sort απαιτεί Ο(n) μετακινήσεις, το insertion sort, απαιτεί Ο(n²) μετακινήσεις (στη χείριστη περίπτωση όπου ο αρχικός πίνακας είναι ταξινομημένος σε φθίνουσα σειρά). ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι37

38 Γ. Ταξινόμηση με Συγχώνευση (Merge sort) Η ταξινόμηση με συγχώνευση είναι διαδικασία διαίρει και βασίλευε ( Divide and Conquer: αναδρομική διαδικασία όπου το πρόβλημα μοιράζεται σε μέρη τα οποία λύνονται ξεχωριστά, και μετά οι λύσεις συνδυάζονται. ) Περιγραφή του Mergesort 1.Διαίρεση: Αναδρομικά μοιράζουμε τον πίνακα στα δύο μέχρι να φτάσουμε σε πίνακες μεγέθους ένα (DIVIDE) 2.Συγχώνευση: Ταξινομούμε αναδρομικά τους πίνακες αυτούς με την συγχώνευση γειτονικών πινάκων (χρησιμοποιώντας βοηθητικό πίνακα). (CONQUER) ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι38

39 MergeSort: Βασική Ιδέα ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι39 Divide (split) Conquer (merge) n=7 (#στοιχείων αριστερά) (#στοιχείων δεξιά)

40 Συγχώνευση 2 Λιστών Υποθέστε ότι θέλετε να συγχωνεύσετε 2 ταξινομημένες λίστες L1, L2 και να δημιουργήσετε μια νέα ταξινομημένη λίστα TEMP Διαδικασία 1.Τοποθέτησε τους δείκτες i, j στην κεφαλή κάθε λίστας. 2.Διάλεξε το μικρότερο από την λίστα L1 και L2 και τοποθέτησε τον στον πίνακα TEMP στην θέση κ 3.Προχώρησε τον δείκτη i (αν το μικρότερο στοιχείο ήταν από την λίστα L1) ή τον δείκτη j στην αντίθετη περίπτωση. 4.Επανέλαβε τα βήματα 2-4 μέχρι να εισαχθούν όλα τα στοιχεία στον TEMP ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι40 (Το i,j ξεκινάνε από την αρχή της κάθε λίστας) κ Μέτα από 6 εκτελέσεις:

41 MergeSort: Υλοποίηση ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι41 void MergeSort(int A[], int temp[], int l, int r){ // η συνθήκη τερματισμού της ανάδρομης if (l==r) return; int mid = (l+r)/2; // για ελαχιστοποίηση overflow(για μεγάλα l,r) // int mid = l + ((r - l) / 2); // μοιράζουμε αναδρομικά τον πίνακα MergeSort(A, temp, l, mid); MergeSort(A, temp, mid+1, r); // συνεχίζεται DIVIDE

42 MergeSort: Υλοποίηση (συν.) ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι42 // Τώρα οι πίνακες [l..mid] και [mid+1..r] είναι // ταξινομημένοι  Η διαδικασία συγχώνευσης int k=l, i=l, j=mid+1; // συγχώνευση στον temp μέχρι μια από // τις λίστες αδειάσει while ((i<=mid) && (j<=r)) { if (A[i]

43 MergeSort: Υλοποίηση (συν.) ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι43 // copy όλων των υπόλοιπων στοιχείων λίστας L1 while (i<=mid) { temp[k] = A[i]; k++;i++; } // copy όλων των υπόλοιπων στοιχείων λίστας L2 while (j<=r) { temp[k] = A[j]; k++;j++; } // αντιγραφή όλων των στοιχείων από TEMP -> A for (i=l; i<=r; i++) { A[i] = temp[i]; }

44 Παράδειγμα Εκτέλεσης Merge Sort ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι44 BEFORE:[8,4,8,43,3,5,2,1,10] 0,8: [8,4,8,43,3, 5,2,1,10] 0,4: [8,4,8,43,3] 0,2: [8,4,8] 0,1: [8,4] 0,0: [8] 1,1: [4] Merging: [A0,A0] [A1,A1] => [4,8,] 2,2: [8] Merging: [A0,A1] [A2,A2] => [4,8,8,] 3,4: [43,3] 3,3: [43] 4,4: [3] Merging: [A3,A3] [A4,A4] => [3,43] Merging: [A0,A2] [A3,A4] => [3,4,8,8,43] 5,8: [5,2,1,10] 5,6: [5,2] 5,5: [5] 6,6: [2] Merging: [A5,A5] [A6,A6] => [2,5] 7,8: [1,10] 7,7: [1] 8,8: [10] Merging: [A7,A7] [A8,A8] => [1,10] Merging: [A5,A6] [A7,A8] => [1,2,5,10] Merging: [A0,A4] [A5,A8] => [1,2,3,4,5,8,8,10,43] AFTER:[1,2,3,4,5,8,8,10,43] divide Index: divide

45 MergeSort: Ανάλυση Χρ. Εκτέλ. - Αναδρομή Το πρόβλημα μοιράζει αναδρομικά σε δυο μέρη την λίστα που θέλουμε να ταξινομήσουμε. Όταν φτάσουμε στην λίστα που έχει μέγεθος 1 τότε σταματά η αναδρομή και το πρόγραμμα αρχίζει να συνδυάζει (merge) τις επιμέρους λίστες. Παρατηρούμε ότι πάνω σε μια λίστα μεγέθους Ν η αναδρομή εκτελείται 2log 2 n φορές. Δηλαδή ο πίνακας μοιράζεται ως εξής: n, n/2, n/4, …, 2, 1 ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι45 void MergeSort(int A[], int temp[], int l, int r){ if (l==r) return; int mid = (l+r)/2; MergeSort(A, temp, l, mid); MergeSort(A, temp, mid+1, r); Θ(logn)

46 MergeSort: Ανάλυση Χρ. Εκτέλ. - Συγχώνευση Σε κάθε επίπεδο της ανάδρομης περνάμε μια φορά από το κάθε στοιχείο. Επομένως η συγχώνευση των στοιχείων σε κάθε επίπεδο της εκτέλεσης χρειάζεται γραμμικό χρόνο Θ(n). Σημειώστε ότι η διαδικασία απαιτεί τη χρήση βοηθητικού πίνακα. Μπορούμε να χρησιμοποιούμε τον ίδιο βοηθητικό πίνακα temp για όλες τις (αναδρομικές) κλήσεις του ΜergeSort. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι46

47 MergeSort: Ανάλυση Χρ. Εκτέλ. - Συνολικός Η αντιγραφή και η συγχώνευση παίρνουν χρόνο Θ(n) και η αναδρομή παίρνει χρόνο Θ(log n). Συνολικά Θ(n log n). Ο χρόνος εκτέλεσης εκφράζεται και από την αναδρομική εξίσωση Τ(0) = Τ(1) = 1 Τ(n) = 2  T(n/2) + n … η οποία μπορεί να λυθεί με το Master Theorem ή με την μέθοδο της αντικατάστασης. Πλεονέκτημα MergeSort: O συνολικός χρόνος εκτέλεσης είναι Θ(n log n) (σε αντίθεση με το SelectionSort (Θ(n 2 )) και το InsertionSort (Ο(n 2 )) Μειονέκτημα: Απαιτεί τη χρήση βοηθητικού πίνακα (δηλαδή χρειάζεται διπλάσιο χώρο αποθήκευσης για την εκτέλεση του). Αυτό δεν καθιστά την μέθοδο πολύ εύχρηστη. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι47

48 48ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι Διάλεξη 10: Αλγόριθμοι Ταξινόμησης II Στην ενότητα αυτή θα μελετηθούν τα εξής επιμέρους θέματα: - Οι αλγόριθμοι ταξινόμησης: Δ. QuickSort – Γρήγορη Ταξινόμηση Ε. BucketSort – Ταξινόμηση με Κάδους - Έμμεση Ταξινόμηση - Εξωτερική Ταξινόμηση

49 Δ. Γρήγορη Ταξινόμηση (QuickSort) Η γρήγορη ταξινόμηση (QuickSort) είναι, όπως ο MergeSort, διαδικασία διαίρει και βασίλευε (divide and conquer, δηλ. αναδρομική διαδικασία όπου το πρόβλημα μοιράζεται σε μέρη τα οποία λύνονται ξεχωριστά, και μετά οι λύσεις συνδυάζονται). Δεν χρειάζεται βοηθητικό πίνακα (όπως στην MergeSort) Πρακτικά, ο πιo γρήγορος αλγόριθμος. Στη χείριστη περίπτωση ο αλγόριθμος QuickSort είναι Ο(n²) αλλά στην καλύτερη περίπτωση χρειάζεται Ω(nlogn): Τα περισσότερα συστήματα χρησιμοποιούν το QuickSort (π.χ., Unix) και οι περισσότερες γλώσσες προγραμματισμού το προσφέρουν σαν μέρος των βασικών βιβλιοθηκών τους πχ. C, JAVA, C++, etc. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι49

50 QuickSort: Αλγόριθμος Aν το δεδομένο εισόδου περιέχει 0 ή 1 στοιχεία δεν κάνουμε τίποτα. Διαφορετικά, αναδρομικά: 1.διαλέγουμε ένα στοιχείο p (ακόμα δεν ορίζουμε πιο ακριβώς), το οποίο ονομάζουμε το άξονα (pivot) στοιχείο και το αφαιρούμε από το δεδομένο εισόδου. 2.χωρίζουμε τον πίνακα σε δύο μέρη S1 και S2, όπου το S1 θα περιέχει όλα τα στοιχεία του πίνακα που είναι μικρότερα από το p, και το S2 θα περιέχει τα υπόλοιπα στοιχεία (όλα τα στοιχεία που είναι μεγαλύτερα ή ίσα από το p). 3.Καλούμε αναδρομικά τον αλγόριθμο στο S1, και παίρνουμε απάντηση το Τ1, και στο S2, και παίρνουμε απάντηση το Τ2. 4. Επιστρέφουμε τον πίνακα [Τ1, p, T2]. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι50

51 QuickSort: Βασική Ιδέα [72, 12, 1, 34, 3, 50, 28, 6, 5, 22, 91, 73] χωρίζουμε με pivot το 28 (μπορούσε να είναι οποιοδήποτε άλλο στοιχείο) Θέτουμε αριστερά του pivot τα μικρότερα και δεξιά τα μεγαλύτερα του [12, 1, 3, 6, 5, 22] 28[72,34,50,91,73] Quicksort Quicksort 1, 3, 5, 6, 12, 22 34, 50, 72, 73, 91 Αποτέλεσμα: 1, 3, 5, 6, 12, 22, 28, 34, 50, 72, 73, 91 ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι51 >= 28 < 28

52 QuickSort: Ψευδοκώδικας void Quicksort(int A[], int l, int r){ if (l>=r) return; int pivotIndex = findPivotIndex(A, l, r); int pivot = A[pivotIndex]; // κάνουμε swap τον pivot με το τελευταίο. swap(A, pivotIndex, r); /* H διαδικασία partition χωρίζει τον πίνακα Α[l…r-1] έτσι ώστε Α[l..k-1] να περιέχει στοιχεία =pivot, και επιστρέφει την τιμή k. */ int k = partition (A, l, r-1, pivot); // κάνουμε swap τον k με το τελευταίο. swap(A, k, r); Quicksort(A, l, k-1); QuickSort(A, k+1, r); } ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι52 Έστω ότι διαλέξαμε τον μεσαίο, δηλ., (l+r)/2;. Θα μπορούσαμε να διαλέξουμε οποιονδήποτε άλλο

53 Διαδικασία Partition(A, l, r, p) Με δεδομένο εισόδου τον πίνακα Α[l…r], και pivot p, θέλουμε να χωρίσουμε τον πίνακα σε δύο μέρη ως προς το p. To πιο πάνω πρέπει να επιτευχθεί χωρίς τη χρήση δεύτερου πίνακα (το sorting θα γίνει επί τόπου). Βασική Ιδέα: 1.Επαναλαμβάνουμε τα εξής μέχρις ότου τα l και r να συναντηθούν. 2.Προχώρα το r προς τα αριστερά όσο τα στοιχεία που βρίσκεις είναι μεγαλύτερα (ή ίσα) του p, 3.Προχώρα το l προς τα δεξιά όσο τα στοιχεία που βρίσκεις είναι μικρότερα του p, 4.αντάλλαξε τα στοιχεία που δείχνονται από τα l και r. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι53

54 Παράδειγμα Εκτέλεσης Partition Δεδομένο Εισόδου: pivot = 48, μετακίνηση του pivot στο τέλος (swap(4, 8)): l r εκτέλεση του Partition(A, l, r, 48): l r lr lr rl ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι54 index pivot

55 public static void QuickSort(int A[], int l, int r) { int pivot, pivotIndex; if (l >= r) return; // Διαλέγουμε το pivot pivotIndex = findPivotIndex(l, r); pivot = A[pivotIndex]; // Κάνουμε swap το pivot με το τελευταίο swap(A, pivotIndex, r); /* H διαδικασία partition χωρίζει τον πίνακα Α[l…r-1] έτσι ώστε * Α[l..k-1] να περιέχει στοιχεία < pivot, A[k…r-1] να περιέχει στοιχεία * >=pivot, και επιστρέφει την τιμή k. */ int k = partition(A, l, r - 1, pivot); // Κάνουμε swap το k με το τελευταίο if (A[r] < A[k]) swap(A, k, r); QuickSort(A, l, k - 1); QuickSort(A, k + 1, r); } Quicksort: Υλοποίηση ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι55

56 public static int findPivotIndex(int l, int r) { return (l + r) / 2; } public static void swap(int A[], int pivot, int r) { int tmp = A[pivot]; A[pivot] = A[r]; A[r] = tmp; } Quicksort: Υλοποίηση (συν.) ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι56

57 public static int partition(int A[], int l, int r, int pivot) { while (l < r) { // προχωρούμε από l στο r μέχρι να χρειαστεί ένα swap while (A[l] < pivot && l < r) l++; // leave “=pivot“ on right if (l == r) break; // τώρα κάνε το swap if (A[l] >= pivot) swap(A, l, r); // move “>=“ to the right } // επέστρεψε το σημείο στο οποίο θέλουμε να γίνει η // εισαγωγή του pivot return l; } Quicksort: Υλοποίηση (συν.) ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι57

58 Παράδειγμα Εκτέλεσης QuickSort ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι58 BEFORE:[72,6,37,48,30,42,83,75] ** QuickSort [0,7] [72,6,37,48,30,42,83,75,] PivotIndex: 3(48) => Swapping 48, 75 [72,6,37,75,30,42,83,48,] Partitioning [0,6] Swapping 72, 42 [42,6,37,75,30,72,83,48,] Swapping 75, 30 [42,6,37,30,75,72,83,48,] Inserting Pivot at Position:4 Swapping 75, 48 [42,6,37,30,48,72,83,75,] ** QuickSort [0,3] [42,6,37,30,48,72,83,75,] PivotIndex: 1(6) => Swapping 6, 30 [42,30,37,6,48,72,83,75,] Partitioning [0,2] Inserting Pivot at Position:0 Swapping 42, 6 ** QuickSort [0,-1] -> RETURN ** QuickSort [1,3] [6,30,37,42,48,72,83,75,] PivotIndex: 2(37) => Swapping 37, 42 [6,30,42,37,48,72,83,75,] Partitioning [1,2] Inserting Pivot at Position:2 Swapping 42, 37 ** QuickSort [1,1] -> RETURN ** QuickSort [3,3] -> RETURN ** QuickSort [5,7] [6,30,37,42,48,72,83,75,] PivotIndex: 6(83) => Swapping 83, 75 [6,30,37,42,48,72,75,83,] Partitioning [5,6] with pivot:83 Inserting Pivot at Position:6 ** QuickSort [5,5] -> RETURN ** QuickSort [7,7] -> RETURN AFTER:[6,30,37,42,48,72,75,83,] Index:

59 Ανάλυση του Χρόνου Εκτέλεσης Η εύρεση του pivot απαιτεί χρόνο Ο(1) και η διαδικασία Partition(Α, l, r, p) εκτελείται σε χρόνο O(n) σε κάθε επίπεδο της αναδρομής. Η αναδρομική εκτέλεση του QuickSort παίρνει στην χείριστη περίπτωση χρόνο O(n) και στην καλύτερη περίπτωση χρόνο Ω(logn) Χείριστη περίπτωση: Κάθε φορά που επιλέγουμε τον pivot όλα τα στοιχεία τυγχάνει να ταξινομούνται είτε μόνο αριστερά του (δηλαδή =pivot) πχ 9,9,9,9,9,9,9 Συνολικός χρόνος εκτέλεσης Τ(n)  O(n²). Βέλτιστη περίπτωση: Κάθε φορά που επιλέγουμε τον pivot τα μισά στοιχεία ταξινομούνται αριστερά του (δηλαδή =pivot) πχ 1,2,3,4,5,6,7 Συνολικός χρόνος εκτέλεσης Τ(n)  Ω(n log n). ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι59

60 Ανάλυση Μέσης Περίπτωσης Θεωρούμε όλες τις πιθανές περιπτώσεις της συμπεριφοράς της μεθόδου Partition(A, i, j, p), όπου j-i = n-1. Υπάρχουν n τέτοιες περιπτώσεις: το αριστερό κομμάτι του partition μπορεί να έχει από 0 μέχρι n-1 στοιχεία. Ας υποθέσουμε πως οι n αυτές περιπτώσεις είναι ισοπίθανες, δηλαδή η κάθε μια έχει πιθανότητα 1/n. Τότε η μέση περίπτωση του Τ(n) δίνεται ως Επίλυση της αναδρομικής σχέσης δίνει T(n)  O(n log n). ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι60

61 Παρατηρήσεις Πως δουλεύει η μέθοδος Partition με δεδομένο εισόδου πίνακα με πολλά στοιχεία ίσα με το pivot; Υπάρχουν άλλες στρατηγικές για επιλογή του pivot; pivot = mid(A[1], A[n], A[n/2]) Επέλεξε τυχαία κάποιο στοιχείο του πίνακα Στην πράξη, για δεδομένα εισόδου μικρού μεγέθους το InsertionSort δουλεύει πιο αποδοτικά. Επομένως μια καλή στρατηγική θα ήταν να συνδυάσουμε τους δύο αλγόριθμους ώστε σε μικρούς πίνακες (π.χ. n  10) να χρησιμοποιείται το ΙnsertionSort και σε μεγάλους το Quicksort: στη μέθοδος Quicksort ανταλλάξτε την πρώτη γραμμή με την εξής: if (j-i)<= 10 InsertionSort(A[i…j], j-i); Ακόμα ένας πιθανός τρόπος βελτίωσης του χρόνου εκτέλεσης είναι η χρήση στοίβας αντί αναδρομής. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι61

62 Κάτω φράγμα για αλγόριθμους ταξινόμησης Ξέρουμε πως το πρόβλημα ταξινόμησης μπορεί να λυθεί σε χρόνο Ο(n log n) (QuickSort και MergeSort). Υπάρχει πιο αποδοτικός αλγόριθμος ταξινόμησης; Θα δείξουμε πως κάθε αλγόριθμος ταξινόμησης είναι Ω(n log n). Ως μονάδα μέτρησης αποδοτικότητας θα χρησιμοποιήσουμε τον αριθμό συγκρίσεων που απαιτεί κάποιος αλγόριθμος. Υποθέτουμε ότι κάθε στοιχείο του πίνακα που θέλουμε να ταξινομήσουμε είναι διαφορετικό από όλα τα άλλα. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι62

63 Σειριακή διάταξη στοιχείων και ταξινόμηση Η συμπεριφορά ενός αλγόριθμου ταξινόμησης εξαρτάται μόνο από τη σχετική σειρά μεταξύ των στοιχείων που ταξινομούμε και όχι από τα συγκεκριμένα στοιχεία. Δηλαδή: αν Α και Β είναι δύο πίνακες τέτοιοι ώστε για κάθε i και j, A[i] < A[j] αν και μόνο αν Β[i] < B[j], τότε ο αριθμός των βημάτων (όπως και ο αριθμός των συγκρίσεων) που θα εκτελέσει κάποιος αλγόριθμος με δεδομένο εισόδου Α θα είναι ο ίδιος με τον ανάλογο αριθμό που θα εκτελέσει με δεδομένο εισόδου Β. Άρα, η σειριακή διάταξη των στοιχείων του δεδομένου εισόδου Α, Α[1], Α[2], …, Α[n], έχει κύρια σημασία. Υπάρχουν n! ‘διαφορετικές’ τοποθετήσεις n ξεχωριστών στοιχείων. Άρα υπάρχουν n! διαφορετικά δεδομένα εισόδου. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι63

64 Ανάλυση Αλγόριθμων Ταξινόμησης Θα περιγράψουμε τη συμπεριφορά ενός αλγόριθμου ως ένα δένδρο αποφάσεων (decision tree). Στη ρίζα επιτρέπονται όλες οι διαφορετικές ‘σειρές’ των στοιχείων. Ας υποθέσουμε πως ο αλγόριθμος συγκρίνει τα δύο πρώτα στοιχεία Α[1] και Α[2]. Τότε το αριστερό παιδί του δένδρου αντιστοιχεί στην περίπτωση Α[1] < Α[2] και το δεξί παιδί της ρίζας στην περίπτωση Α[2] < Α[1]. Σε κάθε κόμβο, μια σειρά στοιχείων είναι νόμιμη αν ικανοποιεί όλες τις συγκρίσεις στο μονοπάτι από τη ρίζα στον κόμβο. Τα φύλλα αντιστοιχούν στον τερματισμό του αλγόριθμου και κάθε φύλλο περιέχει το πολύ μια νόμιμη σειρά στοιχείων. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι64

65 Δένδρο αποφάσεων για 3 στοιχεία ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι65 a

66 Κάτω φράγμα Έστω P ένας αλγόριθμός ταξινόμησης, και έστω T το δένδρο αποφάσεων του P με δεδομένο εισόδου μεγέθους n. Ο αριθμός των φύλλων του Τ είναι n! Το ύψος του Τ είναι ένα κάτω φράγμα του χείριστου χρόνου εκτέλεσης του αλγόριθμου P. Ένα δυαδικό δένδρο ύψους d έχει το πολύ 2 d φύλλα. Άρα το Τ έχει ύψος το λιγότερο log n! Συμπέρασμα: P  Ω(log n!) = Ω(n log n). H μέση περίπτωση είναι επίσης n log n. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι66

67 Ε. Ταξινόμηση με Κάδους - BucketSort Έστω ότι ο πίνακας A n στοιχείων περιέχει στοιχεία που ανήκουν στο διάστημα [1..m]. O αλγόριθμος BucketSort βασίζεται πάνω στα ακόλουθα βήματα: 1.Δημιουργούμε ένα πίνακα buckets μήκους m και θέτουμε buckets[i]=0, για όλα τα i (Αυτά θα είναι τα buckets - κάδοι) 2.Διαβάζουμε τον πίνακα Α ξεκινώντας από το πρώτο στοιχείο. Αν διαβάσουμε το στοιχείο α, τότε αυξάνουμε την τιμή του buckets[α] κατά ένα. Επαναλαμβάνουμε το βήμα μέχρι το τελευταίο στοιχείο. 3.Τέλος, διαβάζουμε γραμμικά τον πίνακα buckets, o oποίος περιέχει αναπαράσταση του ταξινομημένου πίνακα, και θέτουμε τα στοιχεία του πίνακα Α με την ταξινομημένη ακολουθία. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι67

68 BucketSort: Βασική Ιδέα Δεδομένο Εισόδου: Τα στοιχεία είναι στο εύρος m=[0,14], n= Μετά την 1 η εκτέλεση του Bucketsort (Εισαγωγή του 1) Μετά τη 2 η εκτέλεση του Bucketsort (Εισαγωγή του 11) Μετά τη 3 η εκτέλεση του Bucketsort (Εισαγωγή του 1) Μετά την 8ή εκτέλεση του Bucketsort ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι68 n-10 m m m m

69 BucketSort: Υλοποίηση ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι69 // Α: Πίνακας για ταξινόμηση μεγέθους n // Buckets: Βοηθητικός πίνακας μεγέθους m void BucketSort(int A[], int buckets[], int n, int m){ int i, j, k=0; // Κατανομή στοιχείων στους σωστούς κάδους for (i=0; i

70 BucketSort: Χρόνος Εκτέλεσης O αλγόριθμος BucketSort πετυχαίνει ταξινόμηση του Α σε χρόνο Θ(n+m) Σημαίνει ότι ο αλγόριθμος είναι καλύτερος από τον MergeSort Θ(nlogn); Αυτό διαψεύδει το κάτω φράγμα Ω(n log n); (θυμειθείτε ότι έχουμε αποδείξει ότι όλοι οι αλγόριθμοι ταξινόμησης, με δυαδική σύγκριση, έχουν σαν κάτω φράγμα Ω(n log n)) ΟΧΙ, γιατί το μοντέλο είναι διαφορετικό. Μέχρι τώρα υποθέσαμε ότι η μόνη πράξη που μπορούμε να εφαρμόσουμε στα δεδομένα είναι η δυαδική σύγκριση ή ανταλλαγή στοιχείων. Ο αλγόριθμος BucketSort όμως στο Βήμα 2 ουσιαστικά εφαρμόζει m-αδική (m-ary) σύγκριση, σε χρόνο Ο(1). Αυτό μας υπενθυμίζει πως σχεδιάζοντας ένα αλγόριθμο και λαμβάνοντας υπόψη κάποια αποδεδειγμένα κάτω φράγματα πρέπει πάντα να αναλύουμε το μοντέλο στο οποίο δουλεύουμε. Η ύπαρξη και αξιοποίηση περισσότερων πληροφοριών πιθανόν να επιτρέπουν τη δημιουργία αποδοτικότερων αλγορίθμων. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι70

71 71ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι Διάλεξη 11: Δέντρα Ι - Εισαγωγή σε Δενδρικές Δομές Δεδομένων Στην ενότητα αυτή θα μελετηθούν τα εξής επιμέρους θέματα: - Εισαγωγή σε δενδρικές δομές δεδομένων, - Ορισμοί και πράξεις - Αναπαράσταση δενδρικών δομών δεδομένων στη μνήμη - Διάσχιση Δέντρων

72 Βάθος και ύψος ενός δένδρου Βάθος ενός κόμβου (Node Depth) (ή επίπεδο Level) => αριθμός προγόνων + 1. π.χ. το βάθος της ρίζας ενός δένδρου είναι 1. Βάθος ενός δένδρου ονομάζουμε τον μέγιστο από τα βάθη των κόμβων. Μονοπάτι ή διαδρομή (path) ενός δένδρου είναι μια ακολουθία κόμβων v 1, v 2,, …, v k, όπου κάθε v i είναι πατέρας του v i+1. Το μήκος του μονοπατιού v 1, v 2,, …, v k είναι k-1. Ύψος ενός κόμβου : το μήκος του μονοπατιού από το βαθύτερο κόμβο (στο ίδιο υπό-δένδρο) προς τον κόμβο. π.χ. το ύψος οποιουδήποτε φύλλου είναι 0. Ύψος ενός δένδρου : το ύψος της ρίζας του δένδρου. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι72 Ύψος(6): 1 Βάθος(6) = 3

73 Ορολογία Δένδρων Ρίζα(Root): κόμβος χωρίς γονέα (A) Εσωτερικός κόμβος: κόμβος με τουλάχιστον ένα παιδί (A, B, C, F) Εξωτερικός κόμβος(ή φύλλο-leaf): κόμβος χωρίς παιδιά (E, I, J, K, G, H, D) Πρόγονοι ενός κόμβου: γονιός, παππούς, προ-παππούς κτλ. Απόγονοι ενός κόμβου: παιδιά, εγγόνια, δισέγγονα, etc. Υπόδενδρο: δένδρο αποτελούμενο από ένα κόμβο και τους απογόνους του ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι73 Υποδέντροsubtree A B DC GH E F IJ K

74 Παράδειγμα ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι Βάθος (Depth/Level) κόμβου:1 Ύψος (Height) κόμβου: 0 Βάθος (Δένδρου): 2 Ύψος (Δένδρου): 1 Βάθος κόμβου 37: 1 Ύψος κόμβου 37: 1 Βάθος κόμβου 24: 2 Ύψος κόμβου 24: 0 Βάθος (Δένδρου) : 3 Ύψος (Δένδρου) : 2 Βάθος κόμβου 24: 2 Ύψος κόμβου 24: 1 Βάθος κόμβου 6: 3 Ύψος κόμβου 6: 0 ύψος βάθος Βαθμός Δένδρου = 0 Βαθμός Δένδρου = 2

75 Αναπαράσταση Δένδρων στη Μνήμη Υπάρχουν πολλοί τρόποι να αναπαραστήσουμε ένα κόμβο δέντρου στη μνήμη. Κάθε κόμβος αποτελείται από κάποιο αριθμό πεδίων: 1.Τα πραγματικά δεδομένα του κόμβου (το κλειδί), και 2.τα υπόλοιπα πεδία περιέχουν στοιχεία σχετικά με τη δομή του δένδρου, δηλαδή περιγράφουν με κάποιο τρόπο τη σχέση του συγκεκριμένου κόμβου με άλλους κόμβους του δένδρου. Για παράδειγμα: αναφορές στα παιδιά του Αν είναι η ρίζα, εσωτερικός ή φύλο ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι75

76 Αναπαράσταση Δένδρων στη Μνήμη Για δένδρο βαθμού n κάθε κόμβος έχει την πιο κάτω μορφή: Info p 1 p 2 …p n όπου ο p i είναι δείκτης στο i-οστό παιδί του κόμβου. Εναλλακτικά θα μπορούσαμε να αναπαραστήσουμε ένα δένδρο μέσα σε ένα στατικά ορισμένο πίνακα. Π.χ. όπου οι δείκτες είναι απλά αριθμοί (θέσεις του πίνακα). Και στις δυο περιπτώσεις θέλουμε 4 bytes ανά δείκτη (σε x86) ή integer θέσης πίνακα. Αν έχουμε ένα 5-αδικό δέντρο τότε κάθε κόμβος χρειάζεται επιπλέον 20 bytes. Αν ένας κόμβος δεν έχει παιδιά τότε αυτοί οι δείκτες θα μένουν αναξιοποίητοι, επομένως θα έχουμε σπάταλη χώρου. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι76

77 Αναπαράσταση Δένδρων στη Μνήμη Πρόβλημα: Μείωση της σπατάλης χώρου από αχρησιμοποίητους δείκτες/αναφορές. Λύση: Μπορούμε να μετατρέψουμε ένα δέντρο n-αδικό (κάθε κόμβος με n παιδιά) σε ένα 2-αδικό (κάθε κόμβος με 2 παιδιά) χρησιμοποιώντας την πολιτική «Πρώτο Παιδί / Επόμενο Αδέρφι» (First Child/Next Sibling) Δηλαδή κάθε κόμβος u περιέχει 1.τα δεδομένα του κόμβου, 2.δείκτη στο αριστερότερο (πρώτο) παιδί του u, 3.δείκτη στον επί δεξιά αδελφό του u, αν υπάρχει. Αυτή η πολιτική μας επιτρέπει να μειώσουμε τον αριθμό των δεικτών ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι77

78 Παράδειγμα αναπαράστασης δένδρου ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι78 A BΓΔ Ε Ζ Η Θ Ι ΒΕΖΗΘΑΓΔΙ Δένδρο Βαθμού n (n=4) Συνολικές Αναφορές: 9 nodes *4 refs = 36 Δένδρο Βαθμού n (n=2) Συνολικές Αναφορές: 9 nodes *2 refs = 18 [First Child/Next Sibling] [Normal Tree] NULL Pointer Next sibling

79 Διάσχιση Δένδρων Αν θέλουμε να επισκεφθούμε όλους τους κόμβους ενός δένδρου, μπορούμε να χρησιμοποιήσουμε ένα από τους πιο κάτω τρόπους, οι οποίοι διαφέρουν στη σειρά με την οποία εξετάζουν τους κόμβους. 1.Προθεματική Διάσχιση: (Preorder Traversal) επισκεπτόμαστε (εκτυπώνουμε) πρώτα τη ρίζα και ύστερα τα παιδιά της. Αναδρομικά η πράξη ορίζεται ως εξής: Print_Preorder(treenode u) Print u; foreach child v of u Print_Preorder(v) 2.Μεταθεματική Διάσχιση: (Postorder Traversal) επισκεπτόμαστε (εκτυπώνουμε) πρώτα τα παιδιά και ύστερα τη ρίζα του δένδρου. Αναδρομικά η πράξη ορίζεται ως εξής: Print_Postorder(treenode u) foreach child v of u Print_Postorder(v) Print u; ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι79

80 Παράδειγμα Διάσχισης δένδρου ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι80 A BΓΔ Ε Ζ Η Θ Ι Προθεματική Διάσχιση (Preorder) : Α Β Ε Γ Δ Ζ Η Θ Ι Μεταθεματική Διάσχιση (Postorder) : Ε Β Γ Ζ Η Θ Ι Δ Α Print_Preorder(treenode u) Print u; foreach child v of u Print_Preorder(v) Print_Postorder(treenode u) foreach child v of u Print_Postorder(v) Print u;

81 Άλλες Χρήσιμες Πράξεις του ΑΤΔ Δένδρο Parent(u) επέστρεψε τον πατέρα του u Children(u) επέστρεψε τα παιδιά του u FirstChild(u) επέστρεψε το πρώτο παιδί του u RightSibling(u) επέστρεψε τον κόμβο στα δεξιά του u LeftSibling(u) επέστρεψε τον κόμβο στα αριστερά του u IsLeaf(u) αν το u είναι φύλλο τότε δώσε true, διαφορετικά δώσε false IsRoot(u) αν το u είναι η ρίζα του δένδρου δώσε true, διαφορετικά δώσε false Depth(u) δώσε το βάθος του u στο δένδρο. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι81

82 82ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι Διάλεξη 12: Δέντρα ΙΙ - Δυαδικά Δέντρα Στην ενότητα αυτή θα μελετηθούν τα εξής επιμέρους θέματα: - Δυαδικά Δένδρα - Δυαδικά Δένδρα Αναζήτησης(ΔΔΑ) - Εύρεση Τυχαίου, Μέγιστου, Μικρότερου στοιχείου - Εισαγωγή στοιχείου - Διαγραφή Μικρότερου και Τυχαίου στοιχείου - Σύγκριση 2 ΔΔΑ, Διάσχιση

83 Δυαδικά Δένδρα Ένα δένδρο είναι δυαδικό αν όλοι οι κόμβοι του έχουν βαθμό  2. Ορισμός: Δυαδικό δένδρο λέγεται ένα δένδρο το οποίο : είτε είναι κενό, ή αποτελείται από μια ρίζα και δύο δυαδικά υπόδενδρα. Αναφερόμαστε στα δύο υποδένδρα ως το αριστερό και το δεξιό υπόδενδρο. Το ύψος ενός δυαδικού δένδρου με n κόμβους μπορεί να είναι το πολύ: n-1 (συνδεδεμένη λίστα)και το λιγότερο  lg n . ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι83

84 Αναπαράσταση Δένδρων στη Μνήμη Αφού κάθε κόμβος σε ένα δυαδικό δένδρο έχει το πολύ δύο παιδιά, μπορούμε να κρατούμε δείκτες στο καθένα από αυτά. Δηλαδή, ένας κόμβος μπορεί να υλοποιηθεί ως μια εγγραφή TreeNode με τρία πεδία (παρόμοια με κόμβο διπλά συνδεδεμένης λίστας). ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι84 1.key, όπου αποθηκεύουμε τo κλειδί του κόμβου, 2.left, τύπου pointer, ο οποίος δείχνει το αριστερό, υπόδενδρο που ριζώνει στον συγκεκριμένο κόμβο, και 3.right, τύπου pointer, ο οποίος δείχνει το δεξιό υπόδενδρο που ριζώνει στον συγκεκριμένο κόμβο διάφορα άλλα χρήσιμα στοιχεία private class TreeNode { E key; BinaryTreeNode left; BinaryTreeNode right; //other useful fields boolean isLeaf, isInternal, isRoot; Object data; // data BinaryTreeNode(E key){ this.key = key; this.left = null; this.right = null; }

85 Αναπαράσταση Δένδρων στη Μνήμη (συν.) Έτσι, ένα δυαδικό δένδρο υλοποιείται ως ένα δείκτης προς τη ρίζα του δένδρου, δηλαδή μία αναφορά σε εγγραφή τύπου TreeNode. Επίσης μπορεί να υλοποιηθεί σαν μία ξεχωριστή δομή Tree η οποία να περιλαμβάνει και πληροφορίες όπως μέγεθος, ύψος, κ.τ.λ. Παρόμοια με Λίστες, Στοίβες, Ουρές, κτλ. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι85 public class Tree { private class TreeNode {...} private BinaryTreeNode head; private int size; private int height; public void makeEmpty() { this.head=null; this.size=0; } public boolean isEmpty() { return this.size==0; } public int size() { return this.size; } …

86 Δυαδικά Δένδρα Αναζήτησης ΔΔΑ (Binary Search Trees) Το πιο σημαντικό πλεονέκτημα της χρήσης δυαδικών δένδρων η αποδοτική αναζήτηση σε ένα σύνολο στοιχείων Υποθέτουμε την ύπαρξη μιας σχέσης στο σύνολο των στοιχείων που επεξεργαζόμαστε, έστω τη σχέση < πάνω στο σύνολο των ακεραίων. Ένα δυαδικό δένδρο αναζήτησης (ΔΔΑ) είναι ένα δυαδικό δένδρο κάθε κόμβος u του οποίου ικανοποιεί τα εξής: 1.τα κλειδιά του αριστερού υποδένδρου του u είναι μικρότερα από το κλειδί του u 2.τα κλειδιά του δεξιού υποδένδρου του u είναι μεγαλύτερα (ή ίσο) από το κλειδί του u. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι86

87 Διαδικασία Εύρεσης Τυχαίου Στοιχείου: Υλοποίηση public BinaryTreeNode find(E key) { return this.find(key, this.head); } private BinaryTreeNode find(E key, BinaryTreeNode node) { if(node==null){ return null; } else if (key.compareTo(node.key) == 0) { return node; } else if (key.compareTo(node.key) < 0) { return find(key, node.left); } else { return find(key, node.right); } ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι87

88 Διαδικασία Εύρεσης Ελαχίστου/Μεγίστου στοιχείου Στόχος: να επιστραφεί ο κόμβος που περιέχει το μικρότερο (μεγαλύτερο) κλειδί στο δένδρο. Αλγόριθμος: Ξεκινάμε από τη ρίζα και πηγαίνουμε αριστερά (δεξιά) όσο υπάρχει ένα αριστερό (δεξιό) παιδί. Το σημείο που σταματάμε είναι το μικρότερο (μεγαλύτερο) στοιχείο. Χρόνος Εκτέλεσης; Παρόμοια με find ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι88

89 Διαδικασία Εύρεσης Ελαχ./Μεγίστ.: Υλοποίηση public E findMin(){ BinaryTreeNode tmp = this.findMin(this.head); if(tmp!=null) return tmp.key; return null; } public BinaryTreeNode findMin(BinaryTreeNode node){ if(node!=null) while(node.left!=null) node = node.left; return node; } ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι89

90 Διαδικασία Εισαγωγής Σημαντικό: παίζει ρόλο η σειρά εισαγωγής Παραδείγματα Α. Εισαγωγή 37, 24, 42, 6, 40, 60 Β. Εισαγωγή 60, 42, 6, 24, 37, 40 ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι

91 Διασχίζουμε το δέντρο, όπως θα κάναμε με τη find Εάν το X βρεθεί, δεν κάνουμε καμία ενέργεια Διαφορετικά, εισάγουμε το X στο τελευταίο σημείο του μονοπατιού που διασχίστηκε Χρονική πολυπλοκότητα= O(h - ύψος του δένδρου) ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι91 Διαδικασία Εισαγωγής Κόμβου

92 Διαδικασία Εισαγωγής Κόμβου: Υλοποίηση public void insert(E key) { this.head = this.insert(key, this.head); this.size++; } private BinaryTreeNode insert(E key,BinaryTreeNode node) { if(node==null){ node = new BinaryTreeNode (key); } else if (key.compareTo(node.key) < 0) { node.left = insert(key, node.left); } else if (key.compareTo(node.key) > 0) { node.right = insert(key, node.right); } return node; } ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι92

93 u v Εξαγωγή του μικρότερου κόμβου – DeleteMin() ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι93 1.Ακολουθούμε τους αριστερούς δείκτες όσο μπορούμε, φθάνοντας στον κόμβο με το μικρότερο στοιχείο, u. 2.Βρίσκουμε τον πατέρα v του u και αλλάζουμε τον αριστερό δείκτη του v ώστε να δείχνει στο δεξιό παιδί του u 

94 Διαδικασία Διαγραφής Στοιχείου Για να αφαιρέσουμε ένα κλειδί i από ένα ΔΔΑ: 1.Βρίσκουμε τον κόμβο u που περιέχει το i. Ας υποθέσουμε πως v είναι ο πατέρας του u. 2.Αν u είναι φύλλο, τότε αλλάζουμε τον δείκτη του v που δείχνει στο u, ώστε να γίνει null. 3.Αν ο u έχει ένα παιδί, τότε αλλάζουμε τον δείκτη του v που δείχνει τον u, ώστε να δείχνει στο παιδί του u. 4.Αν ο u έχει δύο παιδιά, αλλάζουμε το κλειδί του u ώστε να γίνει το μικρότερο από τα κλειδιά όλων των απογόνων του που έχουν κλειδιά μεγαλύτερα του i. καλούμε τη μέθοδο deleteMin στο αριστερό παιδί του u. ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι94

95 Διαγραφή στοιχείου με δύο απογόνους Βρίσκουμε το μικρότερο στοιχείο (min) στο δεξιό υπόδεντρο του κόμβου που θέλουμε να διαγράψουμε Αντικαθιστούμε το στοιχείο που θέλουμε να διαγράψουμε με το min και τώρα έχουμε το ίδιο στοιχείο 2 φορές στο δέντρο μας Εφαρμόζουμε την deleteMin στο δεξιό υπόδεντρο ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι95

96 Σύγκριση Δυαδικών Δένδρων Η σύγκριση 2 ΔΔΑ επιτυγχάνεται μην διάσχιση του κάθε κόμβου αναδρομικά. Αν όλοι οι κόμβοι έχουν το ίδιο κλειδί τότε επιστρέφει “true” και “false” στην αντίθετη περίπτωση public boolean sameTree(BinaryTree t) { return this.sameTree(this.head, t.head); } private boolean sameTree(BinaryTreeNode a, BinaryTreeNode b) { // και τα δυο δένδρα είναι κενά => άρα επιστρέφουμε true if (a == null && b == null) return true; // και τα δυο δένδρα δεν είναι κενά – συγκρίνουμε τις ρίζες τους else if (a != null && b != null) return ((a.key.compareTo(b.key) == 0) && sameTree(a.left, b.left) && sameTree(a.right, b.right)); // το ένα εκ των δυο υπό-δένδρων είναι κενό => επιστρέφουμε false else return false; } ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι96

97 Διάσχιση ΔΔΑ Αν θέλουμε να επισκεφθούμε όλους τους κόμβους ενός δένδρου, μπορούμε να χρησιμοποιήσουμε ένα από τους πιο κάτω τρόπους, οι οποίοι διαφέρουν στη σειρά με την οποία εξετάζουν τους κόμβους. 1.Προθεματική Διάσχιση: (Preorder Traversal) επισκεπτόμαστε (εκτυπώνουμε) πρώτα κάποιο κόμβο και μετά τα παιδιά του. 2.Μεταθεματική Διάσχιση: (Postorder Traversal) επισκεπτόμαστε (εκτυπώνουμε) πρώτα τα παιδιά και ύστερα τον κόμβο. 3.Ενδοθεματική Διάσχιση: (Inorder Traversal) επισκεπτόμαστε (εκτυπώνουμε) πρώτα τα αριστερά παιδιά, μετά τον κόμβο και μετά τα δεξιά παιδιά. PreOrder: PostOrder: InOrder: ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι97

98 Διάσχιση ΔΔΑ: Υλοποίηση public void preOrder() { this.preOrder(this.head); } private void preOrder(BinaryTreeNode node) { if (node != null) { System.out.print(node.key + " "); preOrder(node.left); preOrder(node.right); } public void inOrder() { this.inOrder(this.head); } private void inOrder(BinaryTreeNode node) { if (node != null) { inOrder(node.left); System.out.print(node.key + " "); inOrder(node.right); } ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι98 public void postOrder() { this.postOrder(this.head); } private void postOrder(BinaryTreeNode node) { if (node != null) { postOrder(node.left); postOrder(node.right); System.out.print(node.key + " "); }


Κατέβασμα ppt "1ΕΠΛ231 – Δομές Δεδομένων και Αλγόριθμοι Επανάληψη: Δομές Δεδομένων και Αλγόριθμοι Επαναληπτικό Υλικό Ενδιάμεσης Εξέτασης."

Παρόμοιες παρουσιάσεις


Διαφημίσεις Google