ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ Βασικές Ιδιότητες και Διάσχιση Κεφάλαιο 5 (5.1-5.2 και 5.4-5.6) Ε. Μαρκάκης Επίκουρος Καθηγητής
Περίληψη Δέντρα Βασικοί ορισµοί Μαθηµατικές ιδιότητες Διάσχιση δέντρων Preorder, postorder, inorder, levelorder Δοµές Δεδοµένων 10-2
Δέντρα Γράφηµα ή γράφος Οποιοδήποτε σύνολο κορυφών (κόµβων) και πλευρών (ακµών) Κάθε πλευρά συνδέει δύο κορυφές Η ακµή µπορεί να είναι κατευθυνόµενη ή όχι Μονοπάτι: ακολουθία από διαδοχικές πλευρές Δέντρο: ειδική µορφή γραφήµατος Ανάµεσα σε δύο κόµβους υπάρχει ένα ακριβώς µονοπάτι Μας βοηθά στην αναπαράσταση της εκτέλεσης αλγορίθµων (union-find, divide and conquer, ) Δέντρο µε ρίζα: Δέντρο όπου ένας κόµβος ορίζεται ως ρίζα Συνήθως θεωρούµε ότι οι ακµές κατευθύνονται προς ή από τη ρίζα Σχεδόν πάντα αναφερόµαστε σε δέντρα µε ρίζα Υποδέντρο: δέντρο που ξεκινά από κόµβο διαφoρετικό από τη ρίζα Δοµές Δεδοµένων 10-3
Δέντρα Ορολογία δέντρων Γονέας ενός κόµβου: ο αµέσως από πάνω κόµβος (µε κατεύθυνση προς τη ρίζα) Η ρίζα είναι ο µόνος κόµβος που δεν έχει γονέα Παιδιά ενός κόµβου: οι αµέσως από κάτω κόµβοι Αδέλφια: παιδιά του ίδιου γονέα Μη τερµατικός κόµβος: έχει ένα τουλάχιστον παιδί Φύλλο ή τερµατικός κόµβος: δεν έχει κανένα παιδί Δάσος: συλλογή από δέντρα ξένα µεταξύ τους Δοµές Δεδοµένων 10-4
Δέντρα Διατεταγµένο δέντρο Ένα δέντρο στο οποίο η σειρά των παιδιών έχει σηµασία Παράδειγµα: τα παιδιά έχουν αύξουσα διάταξη κλειδιών Μ-αδικό δέντρο Κάθε µη τερµατικός κόµβος έχει M παιδιά Κάποιες φορές το ορίζουµε ως «κάθε κόµβος έχει Μ παιδιά» Συχνά θεωρούµε ότι υπάρχουν εξωτερικοί κόµβοι (ίσοι µε null) Χρησιµεύουν στο να έχουν όλοι οι κόµβοι ακριβώς Μ παιδιά Δυαδικό δέντρο Ειδική περίπτωση διατεταγµένου Μ-αδικού δέντρου µε Μ=2 Ονοµάζουµε τα παιδιά αριστερό και δεξιό Δοµές Δεδοµένων 10-5
Δέντρα Αναδροµικοί ορισµοί δέντρων: χρήσιµοι στην απόδειξη ιδιοτήτων τους µε επαγωγή Αναδροµικός ορισµός δυαδικού δέντρου: Βάση: Είτε ένας κόµβος χωρίς παιδιά (τερµατικός κόµβος) Βήµα επαγωγής: Είτε ένας κόµβος µε παιδιά δύο δυαδικά δέντρα Δοµές Δεδοµένων 10-6
Δέντρα Αναπαράσταση δέντρων Μπορεί να γίνει µε πολλούς τρόπους ανάλογα µε την εφαρµογή 1. Πίνακες ή λίστες γειτνίασης (ισχύει για κάθε γράφηµα) 2. Πίνακας parent parent[i] δείχνει τον γονέα του i Για τη ρίζα µπορούµε να κάνουµε τη σύµβαση ότι parent[i] = i Δοµές Δεδοµένων 10-7
Δέντρα Αναπαράσταση δυαδικών δέντρων Ορίζουµε κόµβους µε στοιχείο και δύο συνδέσµους προς αριστερό και δεξιό υποδέντρο Οι κόµβοι χωρίς παιδιά έχουν συνδέσµους null Class Node { Item item; Node l; Node r; Node(Item v, Node l, Node r) { this.item = v; this.l = l; this.r = r; }} Κατάλληλη για κίνηση προς τα κάτω Για κίνηση προς τα πάνω προσθέτουµε σύνδεσµο στο γονέα Δοµές Δεδοµένων 10-8
Δέντρα Αναπαράσταση γενικών δέντρων Στα Μ-αδικά δέντρα γενικεύουµε τα δυαδικά δέντρα Είτε Μ επώνυµοι σύνδεσµοι, είτε πίνακας µε Μ συνδέσµους Στα γενικά δέντρα χρήση συνδεδεµένης λίστας παιδιών Αριστερός δείκτης: λίστα παιδιών, δεξιός δείκτης: επόµενος αδελφός Υπάρχει ισοδύναµη αναπαράσταση µε δυαδικό δέντρο Δοµές Δεδοµένων 10-9
Μαθηµατικές ιδιότητες Ικανές και αναγκαίες συνθήκες: ένας γράφος G µε Ν κορυφές είναι δέντρο αν και µόνο αν ισχύει µία από τις συνθήκες: Ο G έχει Ν-1 πλευρές και κανένα κύκλο Ο G έχει Ν-1 πλευρές και είναι συνδεδεµένος (για κάθε ζεύγος κορυφών υπάρχει µονοπάτι που τις συνδέει) Κάθε ζεύγος κορυφών συνδέεται µε ένα µόνο µονοπάτι Ο G είναι συνδεδεµένος αλλά παύει να είναι αν αφαιρέσουµε οποιαδήποτε πλευρά Ο G είναι συνδεδεµένος, δεν έχει κύκλους, και η προσθήκη οποιασδήποτε επιπλέον πλευράς δηµιουργεί κάποιο κύκλο Οι συνθήκες αυτές είναι ισοδύναµες µεταξύ τους Δοµές Δεδοµένων 10-10
Μαθηµατικές ιδιότητες Ιδιότητες δυαδικών δέντρων Αποδεικνύονται µε επαγωγή (δοµική επαγωγή structural induction) Πλήθος κόµβων Έστω δυαδικό δέντρο µε Ν εσωτερικούς κόµβους Το δέντρο έχει Ν+1 τερµατικούς κόµβους Πλήθος ακµών Έστω δυαδικό δέντρο µε Ν εσωτερικούς κόµβους Το δέντρο έχει 2Ν συνδέσµους Ν-1 σύνδεσµοι µεταξύ εσωτερικών κόµβων Ν+1 σύνδεσµοι από εξωτερικούς κόµβους Δοµές Δεδοµένων 10-11
Μαθηµατικές ιδιότητες Άλλοι ορισµοί δέντρων Επίπεδο κόµβου Η ρίζα έχει επίπεδο 0 Άλλοι κόµβοι: επίπεδο ίσο µε 1 παραπάνω από τον γονέα τους Ύψος δέντρου: µέγιστο επίπεδο κόµβων Μήκος διαδροµής: άθροισµα επιπέδων όλων των κόµβων Μήκος εσωτερικής και εξωτερικής διαδροµής Πλήρες δυαδικό δέντρο (complete binary tree): όλα τα επίπεδα γεµάτα εκτός τελευταίου Στο τελευταίο επίπεδο είναι γεµάτοι οι αριστερότεροι κόµβοι Δοµές Δεδοµένων 10-12
Μαθηµατικές ιδιότητες - Παραδείγµατα Ύψος δέντρου Έστω δυαδικό δέντρο µε Ν εσωτερικούς κόµβους Το ύψος είναι τουλάχιστον logn και το πολύ N-1 Δοµές Δεδοµένων 10-13
Διάσχιση δέντρου Διάσχιση δέντρου (tree traversal) Έστω ότι θέλουµε να επεξεργαστούµε όλους τους κόµβους ενός δέντρου µε συστηµατικό τρόπο 4 βασικές επιλογές διάσχισης Προδιατεταγµένη (preorder): επεξεργαζόµαστε πρώτα έναν κόµβο, και µετά επεξεργαζόµαστε το αριστερό και δεξιό υποδέντρο Ενδοδιατεταγµένη (inorder): επεξεργαζόµαστε πρώτα το αριστερό υποδέντρο, µετά τον κόµβο, και µετά το δεξί υποδέντρο Μεταδιατεταγµένη (postorder): αριστερό υποδέντρο, δεξί υποδέντρο, και στο τέλος ο κόµβος Διάσχιση ανά επίπεδο (level-order): πρώτα η ρίζα, µετά όλοι οι κόµβοι στο επίπεδο 1, κ.ο.κ. (ή µε ανάποδη σειρά από κάτω προς τα πάνω) Δοµές Δεδοµένων 10-14
Διάσχιση δέντρου Αναδροµική υλοποίηση για preorder, inorder, postorder Γενική µορφή κώδικα διάσχισης (preorder) /*έστω visit() µία µέθοδος που επεξεργάζεται έναν κόµβο H διάσχιση παίρνει ως όρισµα τον δείκτη από όπου ξεκινάµε π.χ. τη ρίζα του δέντρου */ private void traverser(node h) { if (h == null) return; h.item.visit(); traverser(h.l); traverser(h.r); } void traverse() { traverser(root); } Παρόµοιος κώδικας για inorder, postorder Δοµές Δεδοµένων 10-15
Διάσχιση δέντρου Παράδειγµα διάσχισης Σειρά επίσκεψης/επεξεργασίας των κοµβων: Α) προδιατεταγµένη: 20, 15, 10, 18, 19, 32, 27, 21, 29, 35 Β) ενδοδιατεταγµένη: 10, 15, 18, 19, 20, 21, 27, 29, 32, 35 Γ) µεταδιατεταγµένη: 10, 19, 18, 15, 21, 29, 27, 35, 32, 20 Δ) ανά επίπεδο: 20, 15, 32, 10, 18, 27, 35, 19, 21, 29 Δοµές Δεδοµένων 10-16
Διάσχιση δέντρου Μη αναδροµική διάσχιση δέντρου (για preorder, inorder, postorder) Στην αναδροµή οι κλήσεις µπαίνουν στη στοίβα Χρησιµοποιώντας τη δική µας στοίβα δεν χρειάζεται αναδροµή Αντί για κλήση, ωθούµε τον κόµβο ή το υποδέντρο στη στοίβα private void traverses(node h) {//παράδειγµα για preorder NodeStack s = new NodeStack(max); s.push(h); while (!s.isempty()) { h = s.pop(); h.item.visit(); if (h.r!= null) s.push(h.r); if (h.l!= null) s.push(h.l); } } void traverses() { traverses(root); } Δοµές Δεδοµένων 10-17
Διάσχιση δέντρου Διάσχιση δέντρου ανά επίπεδο (level-order) Επισκεπτόµαστε τους κόµβους στο ίδιο επίπεδο µε τη σειρά Απλά αντικαθιστούµε τη στοίβα µε ουρά Eπεξεργαζόµαστε τους κόµβους µε τη σειρά που τους βλέπουµε Δεν υπάρχει προφανής αναδροµική υλοποίηση private void traverseq(node h) { NodeQueue q = new NodeQueue(max); q.put(h); while (!q.isempty()) { h = q.get(); h.item.visit(); if (h.l!= null) q.put(h.l); if (h.r!= null) q.put(h.r); } } void traverseq() { traverseq(root); } Δοµές Δεδοµένων 10-18