1.1 Εισαγωγή 1. Ο ΑΤΔ ΔΕΝΔΡΟ Μέχρι τώρα είδαμε τις ΑΤΔ Στοίβα, ΑΤΔ Ουρά και τέλος την ΑΤΔ Λίστα η οποία αποτελεί μια γενίκευση των άλλων 2. Γενικά είδαμε δομές που τηρούν την γραμμική ακολουθία των στοιχείων τους που σημαίνει πάντα ότι υπάρχει μόνο ένα επόμενο και μόνο ένα προηγούμενο για κάθε στοιχείο του ΑΤΔ εκτός του πρώτου και του τελευταίου. Σε αυτό το κεφάλαιο θα δούμε τον ΑΤΔ Δένδρο ο οποίος δεν τηρεί την γραμμική ακολουθία αλλά την ιεραρχική. Σε μια ιεραρχική δομική σχέση ένα στοιχείο έχει το πολύ ένα προηγούμενο αλλά μπορεί να έχει πολλά επόμενα. Η ιεραρχική-δενδρική δομή παρατηρείται σε πολλές περιπτώσεις ιεράρχησης ατόμων ή αντικειμένων. Χαρακτηριστικό παράδειγμα αποτελούν συνήθη πρότυπα οργάνωσης και διοίκησης στον επιχειρηματικό κόσμο, όπου «ρίζα» του δέντρου μπορεί να θεωρηθεί ο Γενικός Διευθυντής μιας επιχείρησης οποίος βρίσκεται πάνω από τους διευθυντές των επιμέρους τμημάτων ενώ ακολουθούν οι προϊστάμενοι για να καταλήψουμε στους απλούς υπαλλήλους που αποτελούν τα «φύλλα»-τερματικούς κόμβους του δένδρου. Στον κόσμο της πληροφορικής οι δενδρικές δομές συνηθίζεται κυρίως να χρησιμοποιούνται σε ευρετήρια για ταχύτερη αναζήτηση δεδομένων σε ταξινομημένες Βάσεις Δεδομένων. Κάποιες άλλες από τις γενικές χρήσεις των δενδρικών δομών είναι οι εξής: Γενικά για αναπαράσταση ιεραρχικών δεδομένων Για αναπαράσταση ταξινομημένων λιστών δεδομένων Στην διαδικασία σύνθεσης ψηφιακών εικόνων για την βέλτιστη απόδοση οπτικών αποτελεσμάτων Στους αλγορίθμους δρομολόγησης δικτύων 1.2 Ορισμός Ο ΑΤΔ Δένδρο είναι ένα πεπερασμένο μη κενό σύνολο κόμβων τέτοιο ώστε να ισχύουν τα εξής: Υπάρχει ένας μοναδικός κόμβος που καλείται ρίζα ο οποίος δεν έχει προηγούμενο. Οι υπόλοιποι κόμβοι χωρίζονται σε n>= ξένα μεταξύ τους υποσύνολα Τ1, Τ2,..., ΤΝ, κάθε ένα από τα οποία είναι ένα δέντρο. Τα Τ1, Τ2,..., ΤΝ καλούνται υποδέντρα της ρίζας. Αυτός είναι ο γενικός ορισμός του δέντρου. Επειδή υπάρχουν πολλές κατηγορίες δέντρων διευκρινίζεται ότι σε αυτό το κεφάλαιο παρουσιάζονται υλοποιήσεις και δοκιμές που αφορούν Δυαδικά Δέντρα Αναζήτησης (ΔΔΑ) και AVL Δέντρα. 1.2.1 Δεδομένα Οι περιορισμοί για ένα ΔΔΑ t είναι οι εξής: όλα τα περιεχόμενα στο αριστερό υποδέντρο του t είναι μικρότερα (αριθμητικά ή αλφαβητικά) από το περιεχόμενο της ρίζας του t. Δ.Μήλιος 1
όλα τα περιεχόμενα στο δεξί υποδέντρο του t είναι μεγαλύτερα (αριθμητικά ή αλφαβητικά) από το περιεχόμενο της ρίζας του t. Το δεξί και το αριστερό υποδέντρο του t είναι και αυτά ΔΔΑ. Οι περιορισμοί για ένα AVL δέντρο είναι οι εξής: Ένα AVL δέντρο είναι ένα ισοζυγισμένο κατά ύψος 1-δέντρο. Για κάθε κόμβο ενός AVL δέντρου ισχύει h L -h R <=1 όπου h L και h R είναι τα ύψη του δεξιού και αριστερού υποδέντρου αντίστοιχα. Σε κάθε κόμβο του του AVL δέντρου αντιστοιχεί ο παράγων ισοζύγισης, ο οποίος είναι αριστερά υψηλός, ίσος ή δεξιά υψηλός ανάλογα με το αν το αριστερό υποδέντρο έχει μεγαλύτερο, ίσο ή μικρότερο ύψος από το δεξί υποδέντρο αντίστοιχα. 1.2.2 Πράξεις Όπου υπάρχει η φράση «τρέχοντας δείκτης» διευκρινίζεται ότι αφορά τόσο την θέση ενός κόμβου σε υλοποιήσεις με πίνακα όσο και σε υλοποιήσεις με χρήση δεικτών. Οι βασικές πράξεις του ΔΔΑ είναι: Tree_dimioyrgia: δημιουργεί ένα κενό δένδρο. Tree_katastrofi: καταστρέφει ένα δένδρο. Tree_keno: ελέγχει αν το δένδρο είναι κενό. Tree_eisagogi: εισάγει ένα νέο στοιχείο στο δένδρο, στην θέση που πρέπει για να διατηρηθεί η ιδιότητα του ΔΔΑ, εκτός και αν υπάρχει ήδη το στοιχείο ή δεν έγινε για κάποιο λόγο η δέσμευση κόμβου (υλοποιήσεις με χρήση δείκτη) ή η θέση του στοιχείου έχει την ειδική τιμή not_spec-μη έγκυρη τιμή (υλοποιήσεις με απλό πίνακα) Tree_diagrafi: διαγράφει ένα στοιχείο από το δένδρο, εκτός και αν το στοιχείο που έχει δοθεί για να διαγραφεί δεν υπάρχει. Tree_apaidi: μετακινεί τον τρέχοντα δείκτη στον κόμβο που αντιπροσωπεύει το αριστερό παιδί του κόμβου που δείχνει ο δείκτης, εκτός και αν ο δείκτης είναι εκτός ορίωνή έχει μη έγκυρη τιμή (για υλοποιήσεις με πίνακα) ή δεν δείχνει κάπου (για υλοποιήσεις με χρήση δεικτών). Tree_dpaidi: μετακινεί τον τρέχοντα δείκτη στον κόμβο που αντιπροσωπεύει το δεξί παιδί του κόμβου που δείχνει ο δείκτης, οι εναλλακτικές σε περίπτωση λάθους είναι οι ίδιες με της Tree_apaidi. Tree_pateras: μετακινεί τον τρέχοντα δείκτη στον κόμβο που αντιπροσωπεύει τον πατέρα του κόμβου που δείχνει ο τρέχοντας δείκτης, εκτός και αν ο τρέχοντας δείκτης δείχνει στην ρίζα ή έχει μη έγκυρη τιμή ή είναι εκτός ορίων (για υλοποιήσεις με πίνακα) ή δεν δείχνει κάπου (για υλοποιήσεις με χρήση δεικτών). Tree_anazitisi: ψάχνει το δένδρο για το στοιχείο που ζητήθηκε από τον χρήστη και επιστρέφει τον δείκτη στην θέση του στοιχείου αυτού, εκτός και αν το στοιχείο δεν υπάρχει στο δένδρο ή ο τρέχοντας δείκτης δεν δείχνει στο δένδρο άρα η αναζήτηση θεωρείται άκυρη. Tree_allagi: αντικαθιστά ένα στοιχείο στο δένδρο με ένα νέο διατηρώντας την ιδιότητα του ΔΔΑ, εκτός και αν δεν υπάρχει το στοιχείο αυτό στο δένδρο. Δ.Μήλιος 2
Tree_periexomeno: επιστρέφει το περιεχόμενο του κόμβου στον οποίο βρίσκεται ο τρέχοντας δείκτης, εκτός και αν δείκτης δείχνει εκτός ορίων (για υλοποιήσεις με πίνακα) ή δεν δείχνει κάπου (για υλοποιήσεις με χρήση δεικτών). Οι βασικές πράξεις του AVL δένδρου είναι: AVLTree_dimioyrgia: δημιουργεί ένα κενό δένδρο. AVLTree_katastrofi: καταστρέφει ένα δένδρο. AVLTree_keno: ελέγχει αν το δένδρο είναι κενό. AVLTree_eisagogi: εισάγει ένα νέο στοιχείο στο δένδρο, στην θέση που πρέπει για να διατηρηθεί η ιδιότητα του AVL, εκτός και αν το στοιχείο υπάρχει ήδη ή υπάρχει αδυναμία δέσμευσης κόμβου. AVLTree_diagrafi: διαγράφει ένα στοιχείο από το δένδρο, εκτός και αν το στοιχείο δεν υπάρχει στο δέντρο ή το δέντρο είναι κενό. AVLTree_apaidi: μετακινεί τον τρέχοντα δείκτη στον κόμβο που αντιπροσωπεύει το αριστερό παιδί του κόμβου που δείχνει ο δείκτης, εκτός και αν ο τρέχοντας δείκτης δεν δείχνει κάπου. AVLTree_dpaidi: μετακινεί τον δείκτη στον κόμβο που αντιπροσωπεύει το δεξί παιδί του κόμβου που δείχνει ο δείκτης, εκτός και αν ο τρέχοντας δείκτης δεν δείχνει κάπου. AVLTree_pateras: μετακινεί τον τρέχοντα δείκτη στον κόμβο που αντιπροσωπεύει τον πατέρα του κόμβου που δείχνει ο τρέχοντας δείκτης, εκτός και αν ο τρέχοντας δείκτης δείχνει στην ρίζα ή το δέντρο είναι κενό ή ο τρέχοντας δείκτης δεν δείχνει κάπου. AVLTree_anazitisi: ψάχνει το δένδρο για το στοιχείο που ζητήθηκε από τον χρήστη και επιστρέφει τον τρέχοντα δείκτη στην θέση του στοιχείου αυτού, εκτός και αν το στοιχείο δεν βρεθεί ή το δένδρο είναι κενό. AVLTree_allagi: αντικαθιστά ένα στοιχείο στο δένδρο με ένα νέο διατηρώντας την ιδιότητα του AVL, εκτός και αν δεν υπάρχει αυτό το στοιχείο στο δένδρο. AVLTree_periexomeno: επιστρέφει το περιεχόμενο του κόμβου στον οποίο βρίσκεται ο δείκτης, εκτός και αν ο δείκτης δεν δείχνει κάπου. 1.3 Υλοποιήσεις Στις επόμενες υποενότητες ακολουθεί η ανάλυση των 2 υλοποίησεων (ΔΔΑ, AVL) 1.3.1 Υλοποίηση 1 η : Υλοποίηση με δυαδικό δέντρο αναζήτησης Καταρχάς να διευκρινιστεί ότι ένα δυαδικό δέντρο αναζήτησης αποτελεί υποκατηγορία ενός δυαδικού δέντρου. Ένα δυαδικό δένδρο ορίζεται ως ένα πεπερασμένο σύνολο κόμβων το οποίο είτε είναι κενό ή: Υπάρχει ένας ειδικός κόμβος που καλείται ρίζα και Οι υπόλοιποι κόμβοι χωρίζονται σε 2 ξένα μεταξύ τους υποσύνολα, Α και Δ, κάθε ένα από τα οποία είναι ένα δυαδικό δέντρο. Το Α είναι το αριστερό υποδέντρο της ρίζας και το Δ είναι το δεξί υποδέντρο της ρίζας. Επιπρόσθετα σε αυτά λοιπόν για ένα δυαδικό δένδρο αναζήτησης (ΔΔΑ) t ισχύουν τα εξής: Δ.Μήλιος 3
όλα τα περιεχόμενα στο αριστερό υποδέντρο του t είναι μικρότερα (αριθμητικά ή αλφαβητικά) από το περιεχόμενο της ρίζας του t. όλα τα περιεχόμενα στο δεξί υποδέντρο του t είναι μεγαλύτερα (αριθμητικά ή αλφαβητικά) από το περιεχόμενο της ρίζας του t. Το δεξί και το αριστερό υποδέντρο του t είναι και αυτά ΔΔΑ. Το ΔΔΑ έχει υλοποιηθεί με χρήση πίνακα ακολουθιακά και μη και με χρήση δεικτών. Σε κάθε υλοποίηση παρουσιάζονται 2 περιπτώσεις, αναδρομικής ή επαναληπτικής συμπεριφοράς των πράξεων του ΑΤΔ. 1.3.1.1 Υλοποίηση ακολουθιακά ΑΤΔ δέντρου αναζήτησης με πίνακα Στην συγκεκριμένη υλοποίηση γίνεται χρήση Μερικής Απόκρυψης. Η αναπαράσταση του δέντρου γίνεται από έναν πίνακα σταθερού μήκους που δέχεται τα δεδομένα της δομής. Η δομή περιλαμβάνει μια μεταβλητή τύπου στοιχείου δέντρου που δέχεται τα δεδομένα του κόμβου, καθώς και μια μεταβλητή ακεραίου που δηλώνει αν ο κόμβος είναι έγκυρος, αν δηλαδή υπάρχει στο δέντρο μας την δεδομένη στιγμή. Τα στοιχεία του δέντρου στην συγκεκριμένη υλοποίηση έχουν συγκεκριμένη θέση στον πίνακα, οπότε ανάλογα με την θέση αυτή μπορούμε να ξέρουμε ανά πάσα στιγμή σε ποιο κόμβο αναφερόμαστε διαχειριζόμενοι το δένδρο. Η ρίζα βρίσκεται πάντα στην πρώτη θέση του πίνακα, και από κει και πέρα μπορούμε να βρούμε οποιοδήποτε κόμβο δεδομένου ότι κάθε αριστερό παιδί βρίσκεται στη θέση 2* (x+1) -1 και κάθε δεξί παιδί στην θέση 2* (x+1), αν x η θέση του πατέρα. 1.3.1.1.1 Υλοποίηση ακολουθιακά ΑΤΔ δέντρου αναζήτησης με πίνακα με επανάληψη 1.3.1.1.1.1 Αρχεία Διεπαφής-Υλοποίησης Στο αρχείο Διεπαφής δηλώνεται η δομή του δέντρου που αναλύεται πιο πάνω και οι συναρτήσεις, αλλά κυρίως εντοπίζεται το include του τύπου στοιχείου δέντρου το οποίο δεν περιλαμβάνει συγκεκριμένο μονοπάτι που να προσδιορίζει το αρχείο του τύπου στοιχείου δένδρου αλλά περιγράφει τον ρόλο του συγκεκριμένου include. Τέλος δηλώνεται και ο μέγιστος αριθμός στοιχείων του δέντρου. Ακολουθεί ο κώδικας του αρχείου Διεπαφής: #ifndef BST_SEQARRAY_ITERATIVE #define BST_SEQARRAY_ITERATIVE #include "to antistoixo.h typou stoixeiou" /*edo analoga tin efarmogi i to test tou tipou stoixeiou mpainei to antoistixo.h tou tipou stoixeiou */ #define PLITHOS 100 /*diloseis tipon*/ Δ.Μήλιος 4
typedef struct typos_komboy { TStoixeioyTree dedomena; int egkyro; typos_komboy; typedef typos_komboy typos_dentroy[plithos]; /*diloseis synarthseon*/ /*dimiourgia/katastrofi dentrou*/ void Tree_dimiourgia(typos_dentroy tree); void Tree_katastrofi(typos_dentroy tree); /*Prakseis elegxou*/ int Tree_keno(typos_dentroy tree); /*Prakseis prosvasis */ void Tree_apaidi(typos_dentroy tree, int pateras, int *paidi, int *error); void Tree_dpaidi(typos_dentroy tree, int pateras, int *paidi, int *error); void Tree_pateras(typos_dentroy tree, int paidi, int *pateras, int *error); /*Prakseis diaxeirisis */ void Tree_eisagogi(typos_dentroy tree, TStoixeioyTree stoixeio, int *error); void Tree_diagrafi(typos_dentroy tree, TStoixeioyTree stoixeio, int *error); /*Prakseis anazitisis*/ void Tree_anazitisi(typos_dentroy tree, TStoixeioyTree stoixeio, int *thesi, int *found); void Tree_periexomeno(typos_dentroy tree, int thesi, TStoixeioyTree *stoixeio,int * error); void Tree_allagi(typos_dentroy tree, TStoixeioyTree old, TStoixeioyTree new, int *error); Ακολουθεί ο κώδικας του αρχείου Υλοποίησης: #include <stdio.h> #include <stdlib.h> #include "BST_SeqArray-Iterative.h" #include <math.h> Δ.Μήλιος 5
void Tree_dimiourgia(typos_dentroy tree) {/* Pro: kamia * Meta: Dimiourgia enos diadikou dentrou anazitisis */ int i; for(i=0;i<plithos;i++) tree[i].egkyro=0; void Tree_katastrofi(typos_dentroy tree) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: Diagrafi olon ton kombon tou dentrou */ Tree_dimiourgia(tree); int Tree_keno(typos_dentroy tree) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: epistrefei 1 an to dentro einai keno,diaforetika 0*/ return!tree[0].egkyro; Δ.Μήλιος 6
void Tree_apaidi(typos_dentroy tree, int pateras, int *paidi, int *error) {/* Pro: o pateras deixnei ena kombo se duadiko dentro anazitisis * Meta: epistrefei to aristero paidi pou deixnei o pateras */ int temp; if(pateras==-1) { return; if(tree[pateras].egkyro==0) { return; temp=2*(pateras+1)-1; if(temp<plithos) { *paidi=temp; if(tree[*paidi].egkyro==0) Δ.Μήλιος 7
void Tree_dpaidi(typos_dentroy tree, int pateras, int *paidi, int *error) {/* Pro: o pateras deixnei ena kombo se ena diadiko dentro anazitisis * Meta: epistrefei to deksi paidi pou deixnei o pateras */ int temp; if(pateras==-1) { return; if(tree[pateras].egkyro==0) { return; temp=2*(pateras+1); if(temp<plithos) { *paidi=temp; if(tree[*paidi].egkyro==0) void Tree_pateras(typos_dentroy tree, int paidi, int *pateras, int *error) {/* Pro: to paidi deixnei ena kombo se ena diadiko dentro anazitisis * Meta: epistrefei ton patera ston "pateras" tou kombou pou deixnei to paidi*/ int temp; if(0<paidi) { if(tree[paidi].egkyro==0) { return; *pateras=floor((paidi+1)/2)-1; Δ.Μήλιος 8
void Tree_eisagogi(typos_dentroy tree, TStoixeioyTree stoixeio, int *error) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: Eisagogi tou kombou sto dentro efoson autos den iparxei idi */ int thesi,error2; thesi=error2=*error=0; while(tree[thesi].egkyro==1) { if(tstree_iso(stoixeio, tree[thesi].dedomena)) { return; if(tstree_mikrotero(stoixeio, tree[thesi].dedomena)) Tree_apaidi(tree, thesi, &thesi,&error2); Tree_dpaidi(tree, thesi, &thesi,&error2); TStree_setValue(&(tree[thesi].dedomena), stoixeio); tree[thesi].egkyro=1; Δ.Μήλιος 9
void Tree_diagrafi(typos_dentroy tree, TStoixeioyTree stoixeio, int *error) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: Diagrafi tou kombou me periexomeno "stoixeio" */ int thesi, found, pateras, apaidi, dpaidi, next, ypodentro, error1, error2, i, j, stoixeia, check; thesi=found=apaidi=dpaidi=error1=error2=ypodentro=0; Tree_anazitisi(tree, stoixeio, &thesi, &found); if(found) { Tree_dpaidi(tree, thesi, &dpaidi, &error2); Tree_apaidi(tree, thesi, &apaidi, &error1); if((!tree[apaidi].egkyro error1) && (!tree[dpaidi].egkyro error2))//den iparxoun paidia { tree[thesi].egkyro=0; return; if(tree[apaidi].egkyro && tree[dpaidi].egkyro &&!error1 &&!error2) //an iparxoun kai ta 2 paidia { next=dpaidi; pateras=thesi; Tree_apaidi(tree, next, &apaidi, &error1); while(tree[apaidi].egkyro &&!error1) { pateras=next; next=apaidi; Tree_apaidi(tree, next, &apaidi, &error1); TStree_setValue(&(tree[thesi].dedomena), tree[next].dedomena); thesi=next; Tree_apaidi(tree, thesi, &apaidi, &error1); ypodentro=dpaidi; if(!tree[ypodentro].egkyro error2) ypodentro=apaidi; if(ypodentro==apaidi) check=1; if(ypodentro==dpaidi) check=0; ypodentro=thesi; error1=0; i=0; while(!error1) { error1=0; if(check) Δ.Μήλιος 10
Tree_apaidi(tree, ypodentro, &apaidi, &error1); Tree_dpaidi(tree, ypodentro, &dpaidi, &error1); stoixeia=pow(2, i); j=0; while((j<stoixeia)&&(apaidi+j<plithos)&&(dpaidistoixeia+j+1<plithos)&&(!error1)) { if(check)//dpaidi ypodentro {TStree_setValue(&(tree[ypodentro+j].dedomena), tree[apaidi+j].dedomena); tree[ypodentro+j].egkyro=tree[apaidi+j].egkyro; //apaidi ypodentro { TStree_setValue(&(tree[ypodentro-stoixeia+j+1].dedomena), tree[dpaidi-stoixeia+j+1].dedomena); tree[ypodentrostoixeia+j+1].egkyro=tree[dpaidistoixeia+j+1].egkyro; j++; if((apaidi+j>=plithos) (dpaidi-stoixeia+j+1>=plithos)) error1=1; i++; if(check) ypodentro=apaidi; ypodentro=dpaidi; /*found */ Δ.Μήλιος 11
void Tree_anazitisi(typos_dentroy tree, TStoixeioyTree stoixeio, int *thesi, int *found) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: epistrefei tin thesi tou kombou pou periexei to "stoixeio" */ int temp, error; error=temp=0; *found=0; while((tree[temp].egkyro==1) &&!error) { if(tstree_iso(stoixeio, tree[temp].dedomena)) { *thesi=temp; *found=1; return; if(tstree_mikrotero(stoixeio, tree[temp].dedomena)) Tree_apaidi(tree, temp, &temp, &error); Tree_dpaidi(tree, temp, &temp, &error); void Tree_periexomeno(typos_dentroy tree, int thesi, TStoixeioyTree *stoixeio,int * error) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: Epistrefei sto "stoixeio" tin timi ton dedomenon pou iparxoun ston kombo * pou deixnei i "thesi" */ *error=0; if(thesi==-1) { return; if(tree[thesi].egkyro==1) TStree_setValue(stoixeio, tree[thesi].dedomena); Δ.Μήλιος 12
void Tree_allagi(typos_dentroy tree, TStoixeioyTree old, TStoixeioyTree new, int *error) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: Enimenronei ton kombo pou exei tin timi old allazontas tin timi se new */ int thesi, found; *error=thesi=found=0; Tree_anazitisi(tree, old, &thesi, &found); if(found) { Tree_diagrafi(tree, old, error); Tree_eisagogi(tree, new, error); 1.3.1.1.1.2 Αρχεία Δοκιμής Στα αρχεία δοκιμής περιλαμβάνεται το αρχείο main που χρησιμοποιείται ως αρχείο test για τις πράξεις του ΔΔΑ. Πρέπει να διευκρινιστεί εδώ πως στα αρχεία-main που χρησιμοποιούνται στα δένδρα έχουν προστεθεί οι εξής συναρτήσεις: episkepsi, riza, prodiataksi, endodiataksi, metadiataksi. Η episkepsi εκτυπώνει τα περιεχόμενα του κόμβου του οποίου τον δείκτη παίρνει παράμετρο. Η riza ουσιαστικά επιστρέφει τον τρέχον δείκτη της δοκιμής-test στον κόμβο ρίζα του δέντρου, η συγκεκριμένη συνάρτηση καλείται σε μια από τις επιλογές του χρήστη ως πράξη δένδρου παρ ότι δεν δηλώνεται στο αντίστοιχο αρχείο Υλοποίησης καθώς είναι συνάρτηση-πράξη που εξυπηρετεί μόνο την συγκεκριμένη εφαρμογή. Οι άλλες 3 ουσιαστικά εξαρτώνται πολύ από τον τρόπο υλοποίησης του δένδρου. Επειδή συγκεκριμένα εδώ αναλύουμε την υλοποίηση με επανάληψη για να υλοποιηθούν οι 3 αυτές συναρτήσεις (prodiataksi, endodiataksi, metadiataksi) πρέπει να κάνουν χρήση του ΑΤΔ Στοίβα με Ολική Απόκρυψη που είδαμε στο 3 ο κεφάλαιο. Συνεπώς στα αρχεία Δοκιμής περιλαμβάνονται και τα αρχεία Διεπαφής-Υλοποίησης της στοίβας με Ολική Απόκρυψη (για τον κώδικα τους ανατρέξτε στο 3 ο κεφάλαιο στην ενότητα 3. 3. 2 Υλοποιήση με Ολική Απόκρυψη-3. 3. 2. 1 Αρχεία Διεπαφής- Υλοποίησης), τα αρχεία Διεπαφής-Υλοποίησης του τύπου στοιχείου δένδρου (για τον κώδικα τους ανατρέξτε στο 3 ο κεφάλαιο στην ενότητα 3. 3. 3) και τέλος τα αρχεία Διεπαφής-Υλοποίησης, εκτός πάντα του path για τον τύπο στοιχείου, ίδια με τα πρότυπα αρχεία. Ακολουθεί ο κώδικας του αρχείου δοκιμής: #include <stdio.h> #include "Stack-OA.h" #include "TStoixeioyStoivas.h" #include "BST_SeqArray-Iterative.h" Δ.Μήλιος 13
#include "../../../../TS/TStoixeioyTree.h" void print_options(void); void episkepsi(typos_dentroy tree, int thesi); int riza(); void endodiataksi(typos_dentroy tree); void prodiataksi(typos_dentroy tree); void metadiataksi(typos_dentroy tree); int main(void) { int option, error, found, cur,created,out_err; typos_dentroy tree; TStoixeioyTree x, x1; created=0; cur=-1; do{ printf("\n\no kersoras brisketai sth 8esh %d\n", cur); error=0; print_options(); scanf("%d", &option); switch(option) {case 1: Tree_dimiourgia(tree); created=1; printf("\nto dentro dimiourgithike!\n"); case 2: { printf("\nden uparxei dentro gia na eisaxthei stoixeio!\n"); printf("dwse ena stoixeio gia eisagwgh sto dentro: "); out_err=tstree_readvalue(stdin,&x); if(!out_err) { printf("\n error stin readvalue!\n"); Tree_eisagogi(tree, x, &error); if(error) printf("\nerror! Paidi ektos oriwn pinaka 'h stoixeio yparxei hdh!\n"); Δ.Μήλιος 14
printf("to stoixeio eishx8h!\n"); case 3: { printf("\nden uparxei dentro gia na diagrafei stoixeio!\n"); printf("dwse ena stoixeio gia diagrafh apo to dentro: "); out_err=tstree_readvalue(stdin,&x); if(!out_err) { printf("\n error stin readvalue!\n"); Tree_diagrafi(tree, x, &error); if(error) printf("\nerror! To stoixeio den yparxei sto dentro!\n"); printf("to stoixeio diagrafhke!\n"); case 4: { printf("\nden uparxei dentro gia na elegxthei an einai keno!\n"); if(tree_keno(tree)) printf("\nto dentro einai keno!\n"); printf("\nto dentro DEN einai keno!\n"); case 5: { printf("\nden uparxei dentro gia na anazithithei stoixeio tou!\n"); printf("dwse ena stoixeio gia anazhthsh sto dentro: "); out_err=tstree_readvalue(stdin,&x); if(!out_err) { printf("\n error stin readvalue!\n"); Δ.Μήλιος 15
Tree_anazitisi(tree, x, &cur, &found); if(found) case 6: printf("\nto stoixeio bre8hke!\n"); printf("\nto stoixeio DEN bre8hke!\n"); { printf("\nden uparxei dentro gia na epistrafei to periexomeno enos komboy tou!\n"); Tree_periexomeno(tree, cur, &x,&error); if(error) printf("\nerror! O deiktis einai NULL!\n"); { printf("\nto periexomeno toy komboy einai "); case 7: out_err=tstree_writevalue(stdout,x); if(out_err <0) { printf("\n error stin writevalue!\n"); { printf("\nden uparxei dentro gia na allaxthei to periexomeno enos komboy tou!\n"); printf("dwse to stoixeio poy 8es na allaksei: "); out_err=tstree_readvalue(stdin,&x); if(!out_err) { printf("\n error stin readvalue!\n"); printf("dwse to stoixeio poy 8es na eisageis sth thesh tou "); out_err=tstree_writevalue(stdout,x); if(out_err <0) { printf("\n error stin writevalue!\n"); Δ.Μήλιος 16
out_err=tstree_readvalue(stdin,&x1); if(!out_err) { printf("\n error stin readvalue!\n"); Tree_allagi(tree, x, x1, &error); if(error) 3anaprospa8hste!\n"); printf("\nerror! Sthn eisagwgh 'h diagrafh twn stoixeiwn.\ Δ.Μήλιος 17 Elegkste ta stoixeia kai to dentro kai printf("\nh allagh egine!\n"); case 8: { printf("\nden uparxei dentro gia na metakinithei o dromeas sto aristero paidi tou trexonta!\n"); Tree_apaidi(tree, cur, &cur, &error); if(error) { printf("\nerror! Paidi ektos oriwn pinaka 'h kersoras se mh egkyrh thesh 'h den yparxei aristero paidi!\n"); case 9: cur=riza(); printf("\no kersoras allakse!\n"); { printf("\nden uparxei dentro gia na metakinithei o dromeas sto deksi paidi tou trexonta!\n"); Tree_dpaidi(tree, cur, &cur, &error); if(error) { printf("\nerror! Paidi ektos oriwn pinaka 'h kersoras se mh egkyrh thesh 'h den yparxei deksi paidi!\n"); cur=riza(); printf("\no kersoras allakse!\n"); case 10:
{ printf("\nden uparxei dentro gia na metakinithei o dromeas ston patera tou trexonta!\n"); thesh!\n"); Tree_pateras(tree, cur, &cur, &error); if(error) case 11: printf("\nerror! O kersoras brisketai sth riza 'h se mh egkyrh printf("\no kersoras allakse!\n"); { printf("\nden uparxei dentro gia na metakinithei o dromeas sti riza tou dentrou!\n"); cur=riza(); printf("o deiktis deixnei stin riza!\n"); case 12: { printf("\nden uparxei dentro gia na katastrafei!\n"); Tree_katastrofi(tree); created=0; printf("\nto dentro katastrafike!\n"); case 13: { printf("\nden uparxei dentro gia na ginei endodiataksi!\n"); printf("\nendodiataksi!\n"); endodiataksi(tree); case 14: { printf("\nden uparxei dentro gia na ginei prodiataksi!\n"); Δ.Μήλιος 18
printf("\nprodiataksi!\n"); prodiataksi(tree); case 15: { printf("\nden uparxei dentro gia na ginei metadiataksi!\n"); printf("\nmetadiataksi!\n"); metadiataksi(tree); while(option); return 0; void print_options(void) { printf("\n1. Dhmioyrgia dentroy\n\ 2. Eisagwgh stoixeioy sto dentro\n\ 3. Diagrafh stoixeioy apo to dentro\n\ 4. Elegxos gia keno dentro\n\ 5. Anazhthsh stoixeioy sto dentro\n\ 6. Epistrofh periexomenoy enos komboy\n\ 7. Allagh toy periexomenoy enos komboy\n\ 8. Metakinhsh toy dromea sto aristero paidi\n\ 9. Metakinhsh toy dromea sto deksi paidi\n\ 10.Metakinhsh toy dromea ston patera\n\ 11.Metakinhsh toy dromea stin riza\n\ 12.Katastrofh dentroy\n\ 13.Endodiatetagmenh diadromh\n\ 14.Prodiatetagmenh diadromh\n\ 15.Metadiatetagmenh diadromh\n\n\ Dwste thn epilogh sas(1-15, 0 gia eksodo):"); void episkepsi(typos_dentroy tree, int thesi) { int error; TStoixeioyTree x; Tree_periexomeno(tree, thesi, &x,&error); TStree_writeValue(stdout,x); Δ.Μήλιος 19
int riza() { return 0; void endodiataksi(typos_dentroy tree) { HandleStoivas stoiva; int error, cur; stoiva=stoiva_constructor(); error=cur=0; do { while(tree[cur].egkyro) { Stoiva_othisi(stoiva, cur, &error); Tree_apaidi(tree, cur, &cur, &error); if(!stoiva_keni(stoiva)) { Stoiva_exagogi(stoiva, &cur, &error); episkepsi(tree, cur); Tree_dpaidi(tree, cur, &cur, &error); while((!stoiva_keni(stoiva)) (tree[cur].egkyro)); Stoiva_Destructor(&stoiva); void prodiataksi(typos_dentroy tree) { HandleStoivas stoiva; int error, cur, temp, last; stoiva=stoiva_constructor(); temp=last=error=cur=0; do { while(tree[cur].egkyro) { episkepsi(tree, cur); Stoiva_othisi(stoiva, cur, &error); Tree_apaidi(tree, cur, &cur, &error); while(!stoiva_keni(stoiva)) { last=cur; Stoiva_exagogi(stoiva, &cur, &error); Tree_dpaidi(tree, cur, &temp, &error); Δ.Μήλιος 20
if((tree[temp].egkyro)&&(temp!=last)) { Stoiva_othisi(stoiva, cur, &error); cur=temp; while(!((cur==0)&&(temp==last)) && (!Stoiva_keni(stoiva))); Stoiva_Destructor(&stoiva); void metadiataksi(typos_dentroy tree) { HandleStoivas stoiva; int error, cur, temp, last; stoiva=stoiva_constructor(); temp=last=error=cur=0; do { while(tree[cur].egkyro) { Stoiva_othisi(stoiva, cur, &error); Tree_apaidi(tree, cur, &cur, &error); while(!stoiva_keni(stoiva)) { last=cur; Stoiva_exagogi(stoiva, &cur, &error); Tree_dpaidi(tree, cur, &temp, &error); if((!tree[temp].egkyro) ((tree[temp].egkyro)&&(temp==last))) episkepsi(tree, cur); { Stoiva_othisi(stoiva, cur, &error); cur=temp; while(!stoiva_keni(stoiva)); Stoiva_Destructor(&stoiva); Δ.Μήλιος 21
1.3.1.1.2 Υλοποίηση ακολουθιακά ΑΤΔ δέντρου αναζήτησης με πίνακα με αναδρομή 1.3.1.1.2.1 Αρχεία Διεπαφής-Υλοποίησης Στο αρχείο Διεπαφής δηλώνεται η δομή του δέντρου που αναλύεται πιο πάνω και οι συναρτήσεις, αλλά κυρίως εντοπίζεται το include του τύπου στοιχείου δέντρου το οποίο δεν περιλαμβάνει συγκεκριμένο μονοπάτι που να προσδιορίζει το αρχείο του τύπου στοιχείου δένδρου αλλά περιγράφει τον ρόλο του συγκεκριμένου include. Τέλος δηλώνεται και ο μέγιστος αριθμός στοιχείων του δέντρου. Ακολουθεί ο κώδικας του αρχείου Διεπαφής: #ifndef BST_SEQARRAY_RECURSIVE #define BST_SEQARRAY RECURSIVE_ #include "to antistoixo.h typou stoixeiou" /*edo analoga tin efarmogi i to test tou tipou stoixeiou mpainei to antoistixo.h tou tipou stoixeiou */ #define PLITHOS 100 /*diloseis tipon*/ typedef struct typos_komboy { TStoixeioyTree dedomena; int egkyro; typos_komboy; typedef typos_komboy typos_dentroy[plithos]; /*diloseis synarthseon*/ /*dimiourgia/katastrofi dentrou*/ void Tree_dimiourgia(typos_dentroy tree); void Tree_katastrofi(typos_dentroy tree); /*Prakseis elegxou*/ int Tree_keno(typos_dentroy tree); /*Prakseis prosvasis*/ void Tree_apaidi(typos_dentroy tree, int pateras, int *paidi, int *error); void Tree_dpaidi(typos_dentroy tree, int pateras, int *paidi, int *error); void Tree_pateras(typos_dentroy tree, int paidi, int *pateras, int *error); Δ.Μήλιος 22
/*Prakseis diaxeirisis */ void Tree_eisagogi(typos_dentroy tree, TStoixeioyTree stoixeio, int riza, int *error); void Tree_diagrafi(typos_dentroy tree, TStoixeioyTree stoixeio, int riza, int *error); /*Prakseis anazitisis*/ void Tree_anazitisi(typos_dentroy tree, TStoixeioyTree stoixeio, int riza, int *thesi, int *found); void Tree_periexomeno(typos_dentroy tree, int thesi, TStoixeioyTree *stoixeio,int *error); void Tree_allagi(typos_dentroy tree, TStoixeioyTree old, TStoixeioyTree new, int *error); #endif /*#ifndef BST_SEQARRAY RECURSIVE */ Ακολουθεί ο κώδικας του αρχείου Υλοποίησης: #include <stdio.h> #include <stdlib.h> #include "BST_SeqArray-Recursive.h" #include <math.h> void Tree_dimiourgia(typos_dentroy tree) {/* Pro: kamia * Meta: Dimiourgia enos diadikou dentrou anazitisis*/ int i; for(i=0;i<plithos;i++) tree[i].egkyro=0; void Tree_katastrofi(typos_dentroy tree) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: Diagrafi olon ton kombon tou dentrou */ Tree_dimiourgia(tree); int Tree_keno(typos_dentroy tree) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: epistrefei 1 an to dentro einai keno,diaforetika 0 */ return!tree[0].egkyro; void Tree_apaidi(typos_dentroy tree, int pateras, int *paidi, int *error) Δ.Μήλιος 23
{/* Pro: o pateras deixnei ena kombo se ena diadiko dentro anazitisis * Meta: epistrefei to aristero paidi pou deixnei o pateras */ int temp; if(pateras==-1) { return; if(tree[pateras].egkyro==0) { return; temp=2*(pateras+1)-1; if(temp<plithos) { *paidi=temp; if(tree[*paidi].egkyro==0) Δ.Μήλιος 24
void Tree_dpaidi(typos_dentroy tree, int pateras, int *paidi, int *error) {/* Pro: o pateras deixnei ena kombo se ena diadiko dentro anazitisis * Meta: epistrefei to deksi paidi pou deixnei o "pateras" */ int temp; if(pateras==-1) { return; if(tree[pateras].egkyro==0) { return; temp=2*(pateras+1); if(temp<plithos) { *paidi=temp; if(tree[*paidi].egkyro==0) void Tree_pateras(typos_dentroy tree, int paidi, int *pateras, int *error) {/* Pro: to paidi deixnei ena kombo se ena diadiko dentro anazitisis * Meta: epistrefei ton patera ston "pateras" tou kombou pou deixnei to "paidi" */ int temp; if(0<paidi) { if(tree[paidi].egkyro==0) { return; *pateras=floor((paidi+1)/2)-1; Δ.Μήλιος 25
void Tree_eisagogi(typos_dentroy tree, TStoixeioyTree stoixeio, int thesi, int *error) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: Eisagogi tou kombou sto dentro efoson autos den iparxei idi */ int error2=0; if(tree[thesi].egkyro==0) { TStree_setValue(&(tree[thesi].dedomena), stoixeio); tree[thesi].egkyro=1; { if(tstree_iso(stoixeio, tree[thesi].dedomena)) { return; if(tstree_mikrotero(stoixeio, tree[thesi].dedomena)) Tree_apaidi(tree, thesi, &thesi, error2); Tree_dpaidi(tree, thesi, &thesi,&error2); Tree_eisagogi(tree, stoixeio, thesi,error); Δ.Μήλιος 26
void Tree_diagrafi(typos_dentroy tree, TStoixeioyTree stoixeio, int thesi, int *error) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: Diagrafi tou kombou me periexomeno "stoixeio" */ int found, pateras, apaidi, dpaidi, next, ypodentro, error1, error2, i, j, stoixeia, check,out_err; found=apaidi=dpaidi=error1=error2=ypodentro=0; if(tree[thesi].egkyro) { Tree_apaidi(tree, thesi, &apaidi, &error1); Tree_dpaidi(tree, thesi, &dpaidi, &error2); if(tstree_iso(stoixeio, tree[thesi].dedomena)) { if((!tree[apaidi].egkyro error1) && (!tree[dpaidi].egkyro error2)) //an den iparxoun paidia { tree[thesi].egkyro=0; return; if((!tree[apaidi].egkyro) error1) //an iparxei dpaidi mono { error1=0; i=0; ypodentro=thesi; while(!error1) { stoixeia=pow(2, i); j=0; Δ.Μήλιος 27 Tree_apaidi(tree, ypodentro, &apaidi, &error1); while((j<stoixeia)&&(apaidi+j<plithos)&&(!error1)) { TStree_setValue(&(tree[ypodentro+j].dedomena), tree[apaidi+j].dedomena); mono tree[ypodentro+j].egkyro=tree[apaidi+j].egkyro; j++; if(apaidi+j>=plithos) i++; error1=1; ypodentro=apaidi; if((!tree[dpaidi].egkyro) error2) //an iparxei apaidi { error2=0; i=0; ypodentro=thesi;
while(!error2) { stoixeia=pow(2, i); j=0; Tree_dpaidi(tree, ypodentro, &dpaidi, &error2); while((j<stoixeia)&&(dpaidistoixeia+j+1<plithos)&&(!error2)) {TStree_setValue(&(tree[ypodentrostoixeia+j+1].dedomena), tree[dpaidi-stoixeia+j+1].dedomena); tree[ypodentro-stoixeia+j+1].egkyro=tree[dpaidi-stoixeia+j+1].egkyro; j++; if(dpaidi-stoixeia+j+1>=plithos) i++; error2=1; ypodentro=dpaidi; //an iparxoun kai ta 2 paidia { next=dpaidi; Tree_apaidi(tree, next, &apaidi, &error1); while(tree[apaidi].egkyro &&!error1) { next=apaidi; Tree_apaidi(tree, next, &apaidi, &error1); TStree_setValue(&(tree[thesi].dedomena), tree[next].dedomena); Tree_diagrafi(tree, tree[thesi].dedomena, dpaidi, error); /* TStree_iso*/ { if(tstree_mikrotero(stoixeio, tree[thesi].dedomena)) // if tree[thesi].egkyro Tree_diagrafi(tree, stoixeio, apaidi, error); Tree_diagrafi(tree, stoixeio, dpaidi, error); Δ.Μήλιος 28
void Tree_anazitisi(typos_dentroy tree, TStoixeioyTree stoixeio, int riza, int *thesi, int *found) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: epistrefei tin "thesi" tou kombou pou periexei to "stoixeio" */ int error; *found=error=0; *thesi=riza; if(!tree[riza].egkyro) return; if(tstree_iso(stoixeio, tree[riza].dedomena)) { *found=1; return; if(tstree_mikrotero(stoixeio, tree[riza].dedomena)) Tree_apaidi(tree, riza, &riza, &error); Tree_dpaidi(tree, riza, &riza, &error); Tree_anazitisi(tree, stoixeio, riza, thesi, found); void Tree_periexomeno(typos_dentroy tree, int thesi, TStoixeioyTree *stoixeio,int * error) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: Epistrefei sto "stoixeio" tin timi ton dedomenon pou iparxoun sto kombo * pou deixnei i "thesi"*/ *error=0; if(thesi==-1) { return; if(tree[thesi].egkyro==1) TStree_setValue(stoixeio, tree[thesi].dedomena); Δ.Μήλιος 29
void Tree_allagi(typos_dentroy tree, TStoixeioyTree old, TStoixeioyTree new, int *error) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: Enimeronei ton kombo pou exei tin timi old allazontas tin timi se new */ int thesi, found; *error=thesi=found=0; Tree_anazitisi(tree, old, 0, &thesi, &found); if(found) { Tree_diagrafi(tree, old, 0, error); Tree_eisagogi(tree, new, 0, error); 1.3.1.1.2.2 Αρχεία Δοκιμής Στα αρχεία δοκιμής περιλαμβάνεται το αρχείο main που χρησιμοποιείται ως αρχείο test για τις πράξεις του ΔΔΑ. Στο αρχείο main περιλαμβάνονται και οι συναρτήσεις: episkepsi, riza, prodiataksi, endodiataksi, metadiataksi των οποίων ο ρόλος έχει αναλυθεί πιο πάνω. Ακολουθεί ο κώδικας του αρχείου δοκιμής: #include <stdio.h> #include "BST_SeqArray-Recursive.h" #include "../../../../TS/TStoixeioyTree.h" void print_options(void); void episkepsi(typos_dentroy tree, int thesi); int riza(); void endodiataksi(typos_dentroy tree, int riza); void prodiataksi(typos_dentroy tree, int riza); void metadiataksi(typos_dentroy tree, int riza); int main(void) { int option, error, found, cur,created,out_err; typos_dentroy tree; TStoixeioyTree x, x1; created=0; Δ.Μήλιος 30
cur=-1; do{ printf("\n\no kersoras brisketai sth 8esh %d\n", cur); error=0; print_options(); scanf("%d", &option); switch(option) {case 1: Tree_dimiourgia(tree); created=1; printf("\nto dentro dimiourgithike!\n"); case 2: { printf("\nden uparxei dentro gia na eisaxthei stoixeio!\n"); printf("dwse ena stoixeio gia eisagwgh sto dentro: "); out_err=tstree_readvalue(stdin,&x); if(!out_err) { printf("\n error stin readvalue!\n"); Tree_eisagogi(tree, x, 0, &error); if(error) printf("\nerror! Paidi ektos oriwn pinaka 'h stoixeio yparxei hdh!\n"); printf("to stoixeio eishx8h!\n"); case 3: { printf("\nden uparxei dentro gia na diagrafei stoixeio!\n"); printf("dwse ena stoixeio gia diagrafh apo to dentro: "); out_err=tstree_readvalue(stdin,&x); if(!out_err) { printf("\n error stin readvalue!\n"); Δ.Μήλιος 31
!\n"); tou!\n"); case 4: Tree_diagrafi(tree, x, 0, &error); if(error) printf("\nerror! To stoixeio den yparxei sto dentro!\n"); printf("to stoixeio diagrafhke!\n"); { printf("\nden uparxei dentro gia na elegxthei an einai keno case 5: if(tree_keno(tree)) printf("\nto dentro einai keno!\n"); printf("\nto dentro DEN einai keno!\n"); { printf("\nden uparxei dentro gia na anazithithei stoixeio printf("dwse ena stoixeio gia anazhthsh sto dentro: "); out_err=tstree_readvalue(stdin,&x); if(!out_err) {printf("\n error stin readvalue!\n"); Tree_anazitisi(tree, x, 0, &cur, &found); if(found) case 6: printf("\nto stoixeio bre8hke!\n"); printf("\nto stoixeio DEN bre8hke!\n"); { printf("\nden uparxei dentro gia na epistrafei to periexomeno enos komboy tou!\n"); Tree_periexomeno(tree, cur, &x,&error); if(error) Δ.Μήλιος 32
printf("\nerror! O deiktis einai NULL!\n"); { printf("\nto periexomeno toy komboy einai "); case 7: out_err=tstree_writevalue(stdout,x); if(out_err <0) { printf("\n error stin writevalue!\n"); { printf("\nden uparxei dentro gia na allaxthei to periexomeno enos komboy tou!\n"); printf("dwse to stoixeio poy 8es na allaksei: "); out_err=tstree_readvalue(stdin,&x); if(!out_err) { printf("\n error stin readvalue!\n"); printf("dwse to stoixeio poy 8es na eisageis sth thesh tou "); out_err=tstree_writevalue(stdout,x); if(out_err <0) { printf("\n error stin writevalue!\n"); out_err=tstree_readvalue(stdin,&x1); if(!out_err) { printf("\n error stin readvalue!\n"); Tree_allagi(tree, x, x1, &error); if(error) 3anaprospa8hste!\n"); case 8: printf("\nerror! Sthn eisagwgh 'h diagrafh twn stoixeiwn.\ Elegkste ta stoixeia kai to dentro kai printf("\nh allagh egine!\n"); Δ.Μήλιος 33
{ printf("\nden uparxei dentro gia na metakinithei o dromeas sto aristero paidi tou trexonta!\n"); Tree_apaidi(tree, cur, &cur, &error); if(error) { printf("\nerror! Paidi ektos oriwn pinaka 'h kersoras se mh egkyrh thesh 'h den yparxei aristero paidi!\n"); cur=riza(); case 9: printf("\no kersoras allakse!\n"); { printf("\nden uparxei dentro gia na metakinithei o dromeas sto deksi paidi tou trexonta!\n"); Tree_dpaidi(tree, cur, &cur, &error); if(error) { printf("\nerror! Paidi ektos oriwn pinaka 'h kersoras se mh egkyrh thesh 'h den yparxei deksi paidi!\n"); cur=riza(); case 10: printf("\no kersoras allakse!\n"); { printf("\nden uparxei dentro gia na metakinithei o dromeas ston patera tou trexonta!\n"); thesh!\n"); Tree_pateras(tree, cur, &cur, &error); if(error) case 11: printf("\nerror! O kersoras brisketai sth riza 'h se mh egkyrh printf("\no kersoras allakse!\n"); Δ.Μήλιος 34
{ printf("\nden uparxei dentro gia na metakinithei o dromeas sti riza tou dentrou!\n"); cur=riza(); printf("o deiktis deixnei stin riza!\n"); case 12: { printf("\nden uparxei dentro gia na katastrafei!\n"); Tree_katastrofi(tree); case 13: created=0; printf("\nto dentro katastrafike!\n"); { printf("\nden uparxei dentro gia na ginei endodiataksi!\n"); {printf("\nendodiataksi!\n"); endodiataksi(tree,riza()); case 14: { printf("\nden uparxei dentro gia na ginei prodiataksi!\n"); printf("\nprodiataksi!\n"); prodiataksi(tree,riza()); case 15: { printf("\nden uparxei dentro gia na ginei metadiataksi!\n"); printf("\nmetadiataksi!\n"); metadiataksi(tree,riza()); Δ.Μήλιος 35
while(option); return 0; void print_options(void) { printf("\n1. Dhmioyrgia dentroy\n\ 2. Eisagwgh stoixeioy sto dentro\n\ 3. Diagrafh stoixeioy apo to dentro\n\ 4. Elegxos gia keno dentro\n\ 5. Anazhthsh stoixeioy sto dentro\n\ 6. Epistrofh periexomenoy enos komboy\n\ 7. Allagh toy periexomenoy enos komboy\n\ 8. Metakinhsh toy dromea sto aristero paidi\n\ 9. Metakinhsh toy dromea sto deksi paidi\n\ 10.Metakinhsh toy dromea ston patera\n\ 11.Metakinhsh toy dromea stin riza\n\ 12.Katastrofh dentroy\n\ 13.Endodiatetagmenh diadromh\n\ 14.Prodiatetagmenh diadromh\n\ 15.Metadiatetagmenh diadromh\n\n\ Dwste thn epilogh sas(1-15, 0 gia eksodo):"); void episkepsi(typos_dentroy tree, int thesi) { TStree_writeValue(stdout,tree[thesi].dedomena); int riza() { return 0; void endodiataksi(typos_dentroy tree, int riza) { int temp, error; temp=error=0; if((riza<0) (riza>(plithos-1))) return; if(tree[riza].egkyro==1) { Tree_apaidi(tree, riza, &temp, &error); endodiataksi(tree, temp); Δ.Μήλιος 36
episkepsi(tree, riza); Tree_dpaidi(tree, riza, &temp, &error); endodiataksi(tree, temp); void prodiataksi(typos_dentroy tree, int riza) { int temp, error; temp=error=0; if((riza<0) (riza>(plithos-1))) return; if(tree[riza].egkyro==1) { episkepsi(tree, riza); Tree_apaidi(tree, riza, &temp, &error); prodiataksi(tree, temp); Tree_dpaidi(tree, riza, &temp, &error); prodiataksi(tree, temp); void metadiataksi(typos_dentroy tree, int riza) { int temp, error; temp=error=0; if((riza<0) (riza>(plithos-1))) return; if(tree[riza].egkyro==1) { Tree_apaidi(tree, riza, &temp, &error); metadiataksi(tree, temp); Tree_dpaidi(tree, riza, &temp, &error); metadiataksi(tree, temp); episkepsi(tree, riza); ενώ τα αρχεία Διεπαφής-Υλοποίησης, εκτός πάντα του path για τον τύπο στοιχείου, ίδια με τα πρότυπα αρχεία. Δ.Μήλιος 37
1.3.1.2 Υλοποίηση ΑΤΔ δέντρου αναζήτησης με δείκτες Στην συγκεκριμένη υλοποίηση γίνεται χρήση Ολικής Απόκρυψης. Η υλοποίηση αυτή είναι σύμφωνη με την οπτική αναπαράσταση των δενδρικών δομών και είναι εύκολο να καταλάβει κάποιος την λογική της δομής που θα χρησιμοποιηθεί. 1.3.1.2.1 Υλοποίηση ΑΤΔ δέντρου αναζήτησης με δείκτες με επανάληψη 1.3.1.2.1.1 Αρχεία Διεπαφής-Υλοποίησης Στο αρχείο Διεπαφής έχουμε την δήλωση του απαραίτητου δείκτη προς την δομή, όπως είθισται σε μια υλοποίηση με Ολική Απόκρυψη, την δήλωση των συναρτήσεων, αλλά κυρίως εντοπίζεται το include του τύπου στοιχείου δέντρου το οποίο δεν περιλαμβάνει συγκεκριμένο μονοπάτι που να προσδιορίζει το αρχείο του τύπου στοιχείου δένδρου αλλά περιγράφει τον ρόλο του συγκεκριμένου include. Ακολουθεί ο κώδικας του αρχείου Διεπαφής: #ifndef BST_POINTER_ITERATIVE #define BST_POINTER_ITERATIVE #include "to antistoixo.h typou stoixeiou" /*edo analoga tin efarmogi i to test tou tipou stoixeiou mpainei to antoistixo.h tou tipou stoixeiou */ /*diloseis tipon*/ typedef struct typos_komboy * typos_deikti; /*diloseis synarthseon*/ /*dimiourgia/katastrofi dentrou*/ void Tree_dimiourgia(typos_deikti *tree); void Tree_katastrofi(typos_deikti *tree); /*Prakseis elegxou*/ int Tree_keno(typos_deikti tree); /*Prakseis prosvasis */ void Tree_apaidi(typos_deikti pateras, typos_deikti *paidi, int *error); void Tree_dpaidi(typos_deikti pateras, typos_deikti *paidi, int *error); void Tree_pateras(typos_deikti tree, typos_deikti *pateras, typos_deikti paidi, int *error); /*Prakseis diaxeirisis */ void Tree_eisagogi(typos_deikti *tree, TStoixeioyTree stoixeio, int *error); void Tree_diagrafi(typos_deikti *tree, TStoixeioyTree stoixeio, int *error); Δ.Μήλιος 38
/*Prakseis anazitisis*/ void Tree_anazitisi(typos_deikti tree, TStoixeioyTree stoixeio, typos_deikti *deiktis, int *found); void Tree_periexomeno(typos_deikti tree, TStoixeioyTree *periexomeno,int * error); void Tree_allagi(typos_deikti *tree, TStoixeioyTree old, TStoixeioyTree new, int *error); #endif /*#ifndef BST_POINTER_ITERATIVE */ #endif /*#ifndef BST_POINTER_ITERATIVE */ Στο αρχείο Υλοποίησης δηλώνεται η δομή του δένδρου που περιέχει μια μεταβλητή τύπου στοιχείου δένδρου για τα δεδομένα του κόμβου, και 2 δείκτες, ένα προς το δεξί παιδί του κάθε κόμβου και ένα προς το αριστερό. Προφανώς υπάρχει και το σώμα των συναρτήσεων που δηλώνονται στο αρχείο Διεπαφής. Ακολουθεί ο κώδικας του αρχείου Υλοποίησης: #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include "BST_pointer-Iterative.h" typedef struct typos_komboy { TStoixeioyTree dedomena; typos_deikti apaidi; typos_deikti dpaidi; typos_komboy; void Tree_dimiourgia(typos_deikti *tree) {/* Pro: kamia * Meta: Dimiourgia enos diadikou dentrou anazitisis */ *tree=null; Δ.Μήλιος 39
void Tree_katastrofi(typos_deikti *tree) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: Diagrafi olon ton kombon tou dentrou */ typos_deikti temp, pateras; int error, left; error=left=0; if(tree_keno(*tree)) return; temp=*tree; while(!error) { while((temp->apaidi!=null) (temp->dpaidi!=null)) { if(temp->apaidi==null) temp=temp->dpaidi; temp=temp->apaidi; Tree_pateras(*tree, &pateras, temp, &error); if(!error) { if(pateras->apaidi==temp) pateras->apaidi=null; pateras->dpaidi=null; free(temp); temp=pateras; *tree=null; int Tree_keno(typos_deikti tree) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: epistrefei 1 an to dentro einai keno,diaforetika 0*/ return (tree==null); Δ.Μήλιος 40
void Tree_apaidi(typos_deikti pateras, typos_deikti *paidi, int *error) {/* Pro: o pateras deixnei ena kombo se duadiko dentro anazitisis * Meta: epistrefei to aristero paidi pou deixnei o pateras */ *error=0; if(pateras!=null) { *paidi=pateras->apaidi; if(*paidi==null) void Tree_dpaidi(typos_deikti pateras, typos_deikti *paidi, int *error) { /* Pro: o pateras deixnei ena kombo se ena diadiko dentro anazitisis * Meta: epistrefei to deksi paidi pou deixnei o pateras */ *error=0; if(pateras!=null) { *paidi=pateras->dpaidi; if(*paidi==null) Δ.Μήλιος 41
void Tree_pateras(typos_deikti tree, typos_deikti *pateras, typos_deikti paidi, int *error) { /* Pro: to paidi deixnei ena kombo se ena diadiko dentro anazitisis * Meta: epistrefei ton patera ston "pateras" tou kombou pou deixnei to paidi*/ typos_deikti temp, dad; *error=0; if(tree_keno(tree) Tree_keno(paidi)) { *pateras=null; return; temp=dad=tree; while(temp!=null) { if(tstree_iso(paidi->dedomena, temp->dedomena)) { if(temp!=tree) *pateras=dad; { *pateras=null; return; if(tstree_mikrotero(paidi->dedomena, temp->dedomena)) { dad=temp; temp=temp->apaidi; { dad=temp; temp=temp->dpaidi; *pateras=null; Δ.Μήλιος 42
void Tree_eisagogi(typos_deikti *tree, TStoixeioyTree stoixeio, int *error) { /*Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: Eisagogi tou kombou sto dentro efoson autos den iparxei idi */ typos_deikti temp, pateras, paidi; paidi=*tree; pateras=null; temp=malloc(sizeof(typos_komboy)); if(temp==null) { return; while(paidi!=null) { pateras=paidi; if(tstree_mikrotero(stoixeio, paidi->dedomena)) paidi=paidi->apaidi; if(tstree_megalytero(stoixeio, paidi->dedomena)) paidi=paidi->dpaidi; { return; temp->apaidi=null; temp->dpaidi=null; TStree_setValue(&(temp->dedomena), stoixeio); if(pateras==null) *tree=temp; { if(tstree_mikrotero(stoixeio, pateras->dedomena)) pateras->apaidi=temp; pateras->dpaidi=temp; Δ.Μήλιος 43
void Tree_diagrafi(typos_deikti *tree, TStoixeioyTree stoixeio, int *error) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: Diagrafi tou kombou me periexomeno "stoixeio" */ typos_deikti x, pateras, x_next, ypodentro; int found, error1; *error=found=error1=0; Tree_anazitisi(*tree, stoixeio, &x, &found); if(!found) { return; Tree_pateras(*tree, &pateras, x, &error1); if((x->apaidi!=null)&&(x->dpaidi!=null))//iparxoun kai ta 2 paidia { x_next=x->dpaidi; pateras=x; while(x_next->apaidi!=null) { pateras=x_next; x_next=x_next->apaidi; TStree_setValue(&(x->dedomena), x_next->dedomena); x=x_next; ypodentro=x->dpaidi; if(ypodentro==null) ypodentro=x->apaidi; if(pateras==null) *tree=ypodentro; if(pateras->apaidi==x) pateras->apaidi=ypodentro; pateras->dpaidi=ypodentro; free(x); Δ.Μήλιος 44
void Tree_anazitisi(typos_deikti tree, TStoixeioyTree stoixeio, typos_deikti *deiktis, int *found) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: epistrefei ton deikti,ston "deiktis",tou kombou pou periexei to "stoixeio"*/ typos_deikti temp; *found=0; temp=tree; while(temp!=null) { if(tstree_iso(stoixeio, temp->dedomena)) { *deiktis=temp; *found=1; return; if(tstree_mikrotero(stoixeio, temp->dedomena)) temp=temp->apaidi; temp=temp->dpaidi; void Tree_periexomeno(typos_deikti tree, TStoixeioyTree *periexomeno,int * error) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: Epistrefei sto "stoixeio" tin timi ton dedomenon pou iparxoun ston kombo * pou deixnei to "tree" */ *error=0; if(!tree_keno(tree)) TStree_setValue(periexomeno, tree->dedomena); Δ.Μήλιος 45
void Tree_allagi(typos_deikti *tree, TStoixeioyTree old, TStoixeioyTree new, int *error) {/* Pro: Dimiourgia enos diadikou dentrou anazitisis * Meta: Enimenronei ton kombo pou exei tin timi old allazontas tin timi se new */ typos_deikti deiktis; int found; *error=found=0; deiktis=null; Tree_anazitisi(*tree, old, &deiktis, &found); if(found) { Tree_diagrafi(tree, old, error); if(!(*error)) Tree_eisagogi(tree, new, error); 1.3.1.2.1.2 Αρχεία Δοκιμής Στα αρχεία δοκιμής περιλαμβάνεται το αρχείο main που χρησιμοποιείται ως αρχείο test για τις πράξεις του ΔΔΑ. Στο αρχείο main περιλαμβάνονται και οι συναρτήσεις: episkepsi, riza, prodiataksi, endodiataksi, metadiataksi των οποίων ο ρόλος έχει αναλυθεί πιο πάνω. Επειδή συγκεκριμένα και εδώ αναλύουμε μια υλοποίηση με επανάληψη για να υλοποιηθούν οι 3 αυτές συναρτήσεις (prodiataksi, endodiataksi, metadiataksi) πρέπει να κάνουν χρήση του ΑΤΔ Στοίβα με Ολική Απόκρυψη που είδαμε στο 3 ο κεφάλαιο. Συνεπώς στα αρχεία Δοκιμής περιλαμβάνονται και τα αρχεία Διεπαφής-Υλοποίησης της στοίβας με Ολική Απόκρυψη (για τον κώδικα τους ανατρέξτε στο 3 ο κεφάλαιο στην ενότητα 3. 3. 2 Υλοποιήση με Ολική Απόκρυψη-3. 3. 2. 1 Αρχεία Διεπαφής- Υλοποίησης), τα αρχεία Διεπαφής-Υλοποίησης του τύπου στοιχείου δένδρου (για τον κώδικα τους ανατρέξτε στο 3 ο κεφάλαιο στην ενότητα 3. 3. 3) και τέλος τα αρχεία Διεπαφής-Υλοποίησης, εκτός πάντα του path για τον τύπο στοιχείου, ίδια με τα πρότυπα αρχεία. Ακολουθεί ο κώδικας του αρχείου δοκιμής: #include <stdio.h> #include "Stack-OA.h" #include "TStoixeioyStoivas.h" #include "BST_pointer-Iterative.h" #include "../../../../TS/TStoixeioyTree.h" Δ.Μήλιος 46
void print_options(void); void episkepsi(typos_deikti tree); typos_deikti riza(typos_deikti tree); void endodiataksi(typos_deikti tree); void prodiataksi(typos_deikti tree); void metadiataksi(typos_deikti tree); int main(void) { int option, error, found,out_err,created; typos_deikti tree, cur; TStoixeioyTree x, x1; created=0; cur=null; printf("\n\nh arxikh timh toy kersora einai NULL!\n", cur); do{ error=0; print_options(); scanf("%d", &option); switch(option) { case 1: Tree_dimiourgia(&tree); created=1; printf("\nto dentro dimiourgithike!\n"); case 2: { printf("\nden uparxei dentro gia na eisaxthei stoixeio!\n"); printf("dwse ena stoixeio gia eisagwgh sto dentro: "); out_err=tstree_readvalue(stdin,&x); if(!out_err) { printf("\n error stin readvalue!\n"); Tree_eisagogi(&tree, x, &error); if(error) printf("\nerror! Adynamia malloc 'h to stoixeio yparxei hdh!\n"); printf("\nto stoixeio eishx8h!\n"); Δ.Μήλιος 47
case 3: { printf("\nden uparxei dentro gia na diagrafei stoixeio!\n"); printf("dwse ena stoixeio gia diagrafh apo to dentro: "); out_err=tstree_readvalue(stdin,&x); if(!out_err) { printf("\n error stin readvalue!\n"); Tree_diagrafi(&tree, x, &error); if(error) printf("\nerror! To stoixeio den yparxei sto dentro!\n"); printf("\nto stoixeio diagrafhke!\n"); case 4: { printf("\nden uparxei dentro gia na elegxthei an einai keno!\n"); if(tree_keno(tree)) printf("\nto dentro einai keno!\n"); printf("\nto dentro DEN einai keno!\n"); case 5: { printf("\nden uparxei dentro gia na anazithithei stoixeio tou!\n"); printf("dwse ena stoixeio gia anazhthsh sto dentro: "); out_err=tstree_readvalue(stdin,&x); if(!out_err) { printf("\n error stin readvalue!\n"); Tree_anazitisi(tree, x, &cur, &found); if(found) Δ.Μήλιος 48
case 6: printf("\nto stoixeio bre8hke!\n"); printf("\nto stoixeio DEN bre8hke!\n"); { printf("\nden uparxei dentro gia na epistrafei to periexomeno enos komboy tou!\n"); Tree_periexomeno(cur, &x,&error); if(error) { printf("\nerror! O deiktis einai NULL!\n"); { printf("\nto periexomeno toy komboy einai "); out_err=tstree_writevalue(stdout,x); if(out_err <0) { printf("\n error stin writevalue!\n"); case 7: { printf("\nden uparxei dentro gia na allaxthei to periexomeno enos komboy tou!\n"); printf("dwse to stoixeio poy 8es na allaksei: "); out_err=tstree_readvalue(stdin,&x); if(!out_err) { printf("\n error stin readvalue!\n"); printf("dwse to stoixeio poy 8es na eisageis sth thesh tou ", x); out_err=tstree_writevalue(stdout,x); if(out_err <0) { printf("\n error stin writevalue!\n"); out_err=tstree_readvalue(stdin,&x1); if(!out_err) Δ.Μήλιος 49
{ printf("\n error stin readvalue!\n"); Tree_allagi(&tree, x, x1, &error); if(error) 3anaprospa8hste!\n"); printf("\nerror! Sthn eisagwgh 'h diagrafh twn stoixeiwn.\ Elegkste ta stoixeia kai to dentro kai { printf("\nh allagh egine!\n"); cur=null; case 8: { printf("\nden uparxei dentro gia na metakinithei o dromeas sto aristero paidi tou trexonta!\n"); Tree_apaidi(cur, &cur, &error); if(error) { printf("\nerror! O deiktis einai NULL!\n"); cur=riza(tree); case 9: printf("\no deiktis deixnei sto aristero paidi!\n"); { printf("\nden uparxei dentro gia na metakinithei o dromeas sto deksi paidi tou trexonta!\n"); Tree_dpaidi(cur, &cur, &error); if(error) { printf("\nerror! O deiktis einai NULL!\n"); cur=riza(tree); case 10: printf("\no deiktis deixnei sto deksi paidi!\n"); Δ.Μήλιος 50