έντρα (Trees) Ιεραρχική οµή Εφαρµογές οµή Οργάνωση ρχείων Οργανογράµµατα Ορισµός (αναδροµικός ορισµός): Ένα δέντρο είναι ένα πεπερασµένο σύνολο κόµβων το οποίο είτε είναι κενό είτε µη κενό σύνολο τέτοιο ώστε: Yπάρχει ένας µοναδικός κόµβος, που καλείται ρίζα Οι υπόλοιποι κόµβοι χωρίζονται σε n>=0 ξένα µεταξύ τους υποσύνολα,τ,τ,,t n,κάθεένααπόταοποίαείναιένα δέντροτατ,τ,,t n καλούνταιυπόδεντρα (subtrees)της ρίζας Ο αριθµός των υποδέντρων ενός κόµβου καλείται βαθµός του κόµβου αυτού ς θεωρήσουµε το δέντρο του παρακάτω χήµατος Το δέντρο αποτελείται από 0 κόµβους {A, B,,, E, F, G, H, I, J επίπεδο ρίζα Β E F G H I J 3 Νέοι Όροι βαθµός κόµβου βαθµός δέντρου τερµατικοί κόµβοι (ή φύλλα) εσωτερικοί κόµβοι παιδί, πατέρας (ή γονέας) πρόγονος, απόγονος ύψος (ή βάθος) υαδικό δέντρο Ενα δυαδικό δέντρο είναι ένα πεπερασµένο σύνολο κόµβων, το οποίοείτεείναικενόή: Υπάρχει ένας ειδικός κόµβος που καλείται ρίζα, και Οι υπόλοιποι κόµβοι χωρίζονται σε δύο ξένα µεταξύ τους υποσύνολα, και, κάθε ένα από τα οποία είναι ένα δυαδικό δέντρο Τοείναιτοαριστερόυπόδεντροτηςρίζαςκαιτο είναι το δεξί υπόδεντρο της ρίζας Κάθε δέντρο µπορεί να παρασταθεί σαν ένα δυαδικό δέντρο
Ε F Β G Πρόταση (i) Ο µέγιστος αριθµός κόµβων στο επίπεδο i ενός δέντρου βαθµού d είναι d i, i >= και (ii) Ο µέγιστος αριθµός κόµβων ενός δέντρου βαθµού d και ύψους h είναι (d h )/(d ) πόδειξη (i) Η απόδειξη θα γίνει µε επαγωγή ν i =, τότε d i = d 0 = πράγµα που ισχύει Έστω ότι ο µέγιστος αριθµός των κόµβων στο k επίπεδο είναι d k Το µέγιστο πλήθος των κόµβων στο k + επίπεδο είναι d d k = d k (ii) Ο µέγιστος αριθµός των κόµβων σε ένα δέντρο ύψους h είναι: H J I Πόρισµα (i) Ο µέγιστος αριθµός κόµβων στο επίπεδο i ενός δυαδικού δέντρου είναι i, i >= και (ii) Ο µέγιστος αριθµός κόµβων ενός δυαδικού δέντρου ύψους h είναι h Πρόταση Ενα δυαδικό δέντρο µε n κόµβους έχει ύψος τουλάχιστον πόδειξη ν h είναι το ύψος ενός δυαδικού δέντρου, τότε από το παραπάνω πόρισµα έχουµε h >= n ή h >= log (n + ) ρα το ελάχιστο ύψος του δυαδικού δέντρου είναι Πρόταση Για ένα µη κενό δυαδικό δέντρο Τ, αν n 0 είναι το πλήθος των τερµατικών κόµβων και n είναι το πλήθος των εσωτερικών κόµβων βαθµού, τότε n 0 = n + πόδειξη n = n 0 + n + n () Επίσης n = B + όπουβ είναι το πλήθος των κλαδιών λλά επίσης B = n + n άρα n = + n + n () πό τις () και () έχουµε : n 0 = n +
Για τον πλήρη ορισµό του Τ δυαδικό δέντρο αποµένει να ορισθούν οι βασικές πράξεις του που είναι: πεικόνιση (σχεδιασµός) δυαδικών δέντρων µε πίνακα ηµιουργία Κενό 3 ριστερό παιδί εξί παιδί 5 νάκτηση εδοµένων (περιεχόµενο) 6 λλαγή εδοµένων 7 Πατέρας (γονέας) 8 ιαγραφή υποδέντρων 9 ντικατάσταση υποδέντρων 0 υγχώνευση ναζήτηση 8 H 9 I Β 5 E F 6 7 G 8 ριθµούµε τις δυνητικές θέσεις των κόµβων από έως h, όπου h το ύψος (βάθος) του δυαδικού δένδρου 3 B A υναρτήσεις πρόσβασης Πρόταση νέναπλήρεςδυαδικόδέντροµε n κόµβους (δηλ βάθος = ) παριστάνεται ακολουθιακά όπως παραπάνω, τότε για οποιονδήποτε κόµβο µε δείκτη i, <= i<= n έχουµε: () O pateras(i) είναι στη θέση αν i< > Όταν i =, τότε δεν υπάρχει πατέρας, γιατί το i είναι η ρίζα () Το apaidi(i) είναιστηθέση i αν i <= n ν i > n, τότεο κόµβος δεν έχει αριστερό παιδί (3) To dpaidi(i) είναιστηθέση i +, αν i + <= n ν i + > n, τότεο κόµβοςδενέχειδεξίπαιδί Η απεικόνιση αυτή είναι ιδανική για ένα πλήρες δυαδικό δέντρο, ωστόσο αρκετός χώρος µνήµης παραµένει ανεκµετάλευτος στα µη πλήρη δυαδικά δέντρα 3 5 6 7 8 9 dentro B E F G H I 3 5 6 7 8 9 dentro B 3
Β υνδεδεµένη παράσταση δυαδικού δέντρου µε πίνακες index αριστερό παιδί apaidi dedomena dpaidi index δεξί παιδί Ένα δυαδικό δέντρο τώρα µπορεί να παρασταθεί ως ένας πίνακας τέτοιων εγγραφών Έχουµε λοιπόν τις παρακάτω δηλώσεις : #define plithos typedef typos_stoixeiou; typedef int typossyndesis; /* όχι pointer αλλά index */ typedef struct { typos_stoixeiou dedomena; typossyndesis apaidi, dpaidi; typos_komvou; typedef typos_komvou pinakas_komvou[plithos]; υνδεδεµένη παράσταση δυαδικού δέντρου µε πίνακες : inakas_komvou Tree; A Το πρώτο στοιχείο του Tree δεν χρησιµοποιείται Η ρίζα είναι στο στοιχείο (δες συναρτήσεις) B 3 5 E 3 5 dedomena apaidi dpaidi Β E 3 5
Γ Υλοποίησηδυαδικώνδέντρωνµεδείκτες (pointers) typedef typos_stoixeiou; typedef struct typos_komvou *typos_deikti; typedef struct typos_komvou { typos_stoixeiou dedomena; typos_deikti apaidi,dpaidi; ; typos_deikti riza; την συνέχεια όλες οι υλοποιήσεις θα είναι µε δείκτες υνδεδεµένη παράσταση δυαδικού δέντρου µε δείκτες : Β H E I F G void dimiourgia_dentro(typos_deikti *riza){ /*Προ: Καµµία Μετά: Εχει δηµιουργηθεί ένα κενό δυαδικό δέντρο στο οποίο δείχνει η riza*/ *riza = NULL; int keno_dentro(typos_deikti riza){ /* Προ: Εχει δηµιουργηθεί το δέντρο στο οποίο δείχνει η riza Μετά: Το υποπρόγραµµα επιστρέφει την τιµή true ή false ανάλογα µε το αν το δέντρο είναι κενό ή όχι*/ return (riza == NULL); 5
ιαδροµή δυαδικού δέντρου Μια από τις βασικές επεξεργασίες ενός δυαδικού δέντρου είναι η επίσκεψη κάθε κόµβου του µια µόνο φορά Τρία Βήµατα Επίσκεψη της ρίζας ιαδροµή του αριστερού υποδέντρου της 3 ιαδροµή του δεξιού υποδέντρου της Τα τρία αυτά βήµατα µπορούν να εκτελεστούν µε οποιαδήποτε διάταξη ν συµβολίσουµε τα παραπάνω βήµατα µε: Κ : Επίσκεψη ενός κόµβου : ιαδροµή αριστερού υποδέντρου του : ιαδροµή δεξιού υποδέντρου του Τότε υπάρχουν έξι διατάξεις για την επίσκεψη των κόµβων ενός δυαδικού δέντρου που είναι οι: Κ Κ Κ Κ Κ Κ Κ : προδιατεταγµένη διαδροµή Κ : ενδοδιατεταγµένη διαδροµή Κ : µεταδιατεταγµένη διαδροµή Οι άλλες 3 ( ) δεν έχουν ενδιαφέρον (συµµετρικές) Οι τρεις διατάξεις επίσκεψης ενός δυαδικού δέντρου: Μ Μεταδιατεταγµένη διαδροµή Κ Μ Ε T Ε T A Z Ζ προδιατεταγµένη : ΜΕΖΤΡ ενδοδιατεταγµένη : ΕΖΜΡΤ µεταδιατεταγµένη : ΖΕΡΤΜ Πρώτα επίσκεψη ριστερού Υποδένδρου του Μ (ρίζας) 6
Ε Πρώτα επίσκεψη ριστερού Υποδένδρου του Ε Τ Επίσκεψη εξιού Υποδένδρου του Μ (ρίζας) Ζ Πρώτα επίσκεψη ριστερού Υποδένδρου του, είναι κενό Επίσκεψη εξιού Υποδένδρου του, κενό Επίσκεψη Επίσκεψη εξιού Υποδένδρου Ε ριστερό Ζ, κενό εξιό Ζ, κενό Επίσκεψη Ζ Επίσκεψη ριστερού Υ/ του Τ Επίσκεψη ριστερού Υ/ του Ρ, κενό Επίσκεψη εξιού Υ/ του Ρ, Επίσκεψη ριστερού Υ/ του, κενό Επίσκεψη εξιού Υ/ του, κενό Επίσκεψη Επίσκεψη Ρ Επίσκεψη Τ Επίσκεψη Μ Επίσκεψη Ε ναδροµικό Υποπρόγραµµα Μεταδιατεταταγµένης ιαδροµής void µεταdiataksi(typos_deikti riza){ /* Aναδροµικό υποπρόγραµµα ιατρέχει µε µεταδιατεταγµένη διαδροµή ένα δυαδικό δέντρο */ όπου η episkepsi τυπώνει το περιεχόµενο ενός κόµβου Η εντολή metadiataksi (riza) καλεί αναδροµικά την metadiataksi προκειµένου να εκτελέσει την µεταδιατεταγµένηδιαδροµήτουπαραπάνωδέντρου if (!keno_dentro(riza)){ metadiataksi(riza>apaidi); //αριστερό Υ/ metadiataksi(riza>dpaidi); //δεξί Υ/ episkepsi(riza); /* Eπίσκεψη της ρίζας */ 7
ναδροµικό Υποπρόγραµµα Ενδοδιατεταταγµένης ιαδροµής void endodiataksi(typos_deikti riza){ /* Aναδροµικό υποπρόγραµµα ιατρέχει µε ενδοδιατεταγµένη διαδροµή ένα δυαδικό δέντρο */ if (!keno_dentro(riza)){ endodiataksi(riza>apaidi); //αριστερό Υ/ episkepsi(riza); // Eπίσκεψη της ρίζας endodiataksi(riza>dpaidi); /* δεξί Υ/ όπου η episkepsi τυπώνει το περιεχόµενο ενός κόµβου Η εντολή endodiataksi (riza) καλεί τη διαδικασία endodiataksi προκειµένου να εκτελέσει την ενδοδιατεταγµένηδιαδροµήτουπαραπάνωδέντρου Η ενέργεια αυτής της διαδικασίας εµφανίζεται αναλυτικά στον ακόλουθο πίνακα: Aς υποθέσουµε ότι έχουµε το δυαδικό δέντρο: Ε riza Μ Τ Περιεχόµενο κόµβου Ενέργεια ποτέλεσµα Μ Ε Κλήση της διαδικασίας µε δείκτη στη ρίζα (Ε) του αριστερού υποδέντρου Κλήση της διαδικασίας µε δείκτη στη ρίζα () του αριστερού υποδέντρου Ζ Κλήση της διαδικασίας µε δείκτη (NULL) στη ρίζα του αριστερού υποδέντρου Κενό Κενό δέντρο, επιστροφή στον κόµβοπατέρα Εκτύπωση του περιεχοµένου του κόµβου 8
Περιεχόµενο κόµβου Ενέργεια ποτέλεσµα Κλήση της διαδικασίας µε δείκτη NULL στη ρίζατου δεξιού υποδέντρου Κενό Κενό δέντρο, επιστροφή στον κόµβοπατέρα Ε Επιστροφή στον κόµβο πατέρα Εκτύπωση του περιεχοµένου του Ε του κόµβου Ε Κλήση της διαδικασίας µε δείκτηστη ρίζα (Ζ) του δεξιού υποδέντρου Περιεχόµενο κόµβου Ενέργεια ποτέλεσµα Ζ Κλήση της διαδικασίας µε δείκτη (NULL) στη ρίζα του αριστερού υποδέντρου Κενό Κενό δέντρο, επιστροφή στον κόµβοπατέρα Ζ Εκτύπωση του περιεχοµένου του Ζ κόµβου Ζ Κλήση της διαδικασίας µε δείκτη (NULL) στη ρίζα του δεξιού υποδέντρου Περιεχόµενο κόµβου Ενέργεια ποτέλεσµα Περιεχόµενο κόµβου Ενέργεια ποτέλεσµα Κενό Κενό δέντρο, επιστροφή στον κόµβο πατέρα Τ Κλήση της διαδικασίας µε δείκτη στη ρίζα () του αριστερού υποδέντρου Ζ Ε Μ Επιστροφή στον κόµβοπατέρα Επιστροφή στον κόµβοπατέρα Εκτύπωση του περιεχοµένου του κόµβου Μ Κλήση της διαδικασίας µε δείκτη στη ρίζα (Τ) του δεξιού υποδέντρου Μ Κενό Κλήση της διαδικασίας µε δείκτη (NULL) στη ρίζα του αριστερού υποδέντρου Κενό δέντρο, επιστροφή στον κόµβοπατέρα Εκτύπωση του περιεχοµένου του κόµβου 9
Περιεχόµενο κόµβου Ενέργεια ποτέλεσµα Περιεχόµενο κόµβου Ενέργεια ποτέλεσµα Κλήση της διαδικασίας µε δείκτη στη ρίζα () του δεξιού υποδέντρου Κλήση της διαδικασίας µε δείκτη (NULL) του δεξιού υποδέντρου Κλήση της διαδικασίας µε δείκτη (NULLl) στη ρίζα του αριστερού υποδέντρου Κενό Κενό δέντρο, επιστροφή στον κόµβο πατέρα Κενό Κενό δέντρο, επιστροφή στον κόµβοπατέρα Εκτύπωση του περιεχοµένου του κόµβου Τ Επιστροφή στον κόµβοπατέρα Επιστροφή στον κόµβοπατέρα Εκτύπωση του περιεχοµένου του κόµβου Τ Περιεχόµενο κόµβου Ενέργεια ποτέλεσµα T Κενό Τ Μ Κλήση της διαδικασίας µε δείκτη (NULL) του δεξιού υποδέντρου Κενό δέντρο, επιστροφή στον κόµβοπατέρα Επιστροφή στον κόµβοπατέρα Τέλος διαδικασίας Eίναι φανερό ότι η προδιατεταγµένη και µεταδιατεταγµένη διαδροµή προκύπτουν αν απλά αλλάξουµε την σειρά των εντολών στη διαδικασία endodiataksi, όπως φαίνεται παρακάτω : void prodiataksi(typos_deikti riza){ /* προδιατεταγµένη διαδροµή */ if (!keno_dentro(riza)){ episkepsi(riza); prodiataksi(riza>apaidi); prodiataksi(riza>dpaidi); 0
void metadiataksi(typos_deikti riza){ /* µεταδιατεταγµένη διαδροµή */ Μη ναδροµικά Υποπρογράµµατα ιαδροµής riza A if (!keno_dentro(riza)){ metadiataksi(riza>apaidi); metadiataksi(riza>dpaidi); episkepsi(riza); Πολυπλοκότητα Ο(n) B F E Περνάµε από κάθε κόµβο είτε ΜΙ φορά (φύλλο) είτε ΥΟ φορές (εσωτερικός κόµβος) G Μη αναδροµικός αλγόριθµος για την ενδοδιατεταγµένη διαδροµή (µε χρήση στοίβας) trexon = riza; Όσο η στοίβα δεν είναι κενή και trexon!= NULL να εκτελούνται: α Να διατρέχονται οι αριστεροί κόµβοι του αριστερού υποδέντρου και να τοποθετούνται οι διευθύνσεις τους σε µια στοίβα {έως ότου αριστερό υπόδεντρο κενό β νη στοίβαδενείναικενήτότε (i) Εξαγωγή διεύθυνσης από στοίβα (ii) Επεξεργασία του περιεχοµένου του (iii) υνέχισε µε δεξί παιδί, trexon= δεξι παιδί void endodiataksi(typos_deikti riza){//eπαναληπτικό typos_stoivas stoiva; typos_deikti trexon = riza; dimiourgia(&stoiva); do {// ιατρέχονται οι κόµβοι των αριστερών κλαδιών while (trexon!=null){ othisi(&stoiva,trexon); trexon = trexon>apaidi; /* Tο αριστερό υπόδεντρο είναι κενό */ if (!keni(stoiva)) { exagogi(&stoiva,&trexon); episkepsi(trexon); /*Eπίσκεψη ρίζας */ trexon = trexon>dpaidi; /*δεξιός κόµβος*/ while ((!keni(stoiva)) (trexon!=null));
νοµοιογενή δυαδικά δέντρα (παραστάσεωνexpressions) υχνά τα δεδοµένα που περιέχονται σε διαφορετικούς κόµβους δεν είναι όλα του ίδιου τύπου + Για τη µετατροπή µιας ενδοδιατεταγµένης παράστασης (expression) κατασκευάζουµε δυαδικό δέντρο, το οποίο ονοµάζεται δέντρο παράστασης ε κάθε βήµα να αναζητείται ο τελεστής εκείνος ο οποίος θα εκτελεστεί τελευταίος (έχει τη µικρότερη ιεραρχία) A * Παράσταση της (A(B*))+ µε δυαδικό δέντρο Β ηµουργία δυαδικού δέντρου παράστασης της 6*(3+8)* ο Βήµα (ρίζα ο τελεστής που εκτελείται τελευταίος) ο Βήµα (αναδροµικά σε αριστερό και δεξί υποδένδρο) * 6*(3+8) * 6*(3+8)
3ο Βήµα ο Βήµα * * * * 6 + 6 3+ 3 8 typedef enum {oros,telest typos_dedomenon; typedef struct typos_komvou *typos_deikti; struct telestis { char xar; typos_deikti apaidi; typos_deikti dpaidi; ; union oros_telestis{ float arithmos; struct telestis xaraktiras; ; typedef struct typos_komvou { typos_dedomenon simadi; oros_tel dedomena; ; τους παραπάνω ορισµούς παρατηρούµε ότι µόνο οι κόµβοι που περιέχουν τελεστές έχουν πεδία δεικτών apaidi και dpaidi για τους υπόλοιπους δεν χρειάζονται γιατί είναι φύλλα τη συνέχεια παρουσιάζεται ένα αναδροµικό υποπρόγραµµα που υπολογίζει την τιµή της παράστασης 3
float ypologismos_dentrou(typos_deikti riza){ float oros,oros; char symbolo; switch (riza>simadi){ case oros:return riza>dedomenaarithmos; case telestis: oros = ypologismos_dentrou (riza>dedomenaxaraktirasapaidi); oros = ypologismos_dentrou (riza>dedomenaxaraktirasdpaidi); symbolo = riza>dedomenaxaraktirasxar; return telestis(symbolo, oros, oros);