You are on page 1of 22

Δομές

Δεδομένων
V–3
Δένδρα –
Ασκήσεις
Ελένη Γαλιώτου
ΔΕΝΔΡΑ
ΠΑΡΑΔΕΙΓΜΑΤΑ - ΑΣΚΗΣΕΙΣ
1. ΑΝΑΔΡΟΜΙΚΗ ΔΙΑΣΧΙΣΗ ΔΕΝΔΡΟΥ

Να γράψετε μία αναδρομική συνάρτηση που δέχεται ως όρισμα ένα σύνδεσμο


προς κάποιο δένδρο και καλεί τη συνάρτηση visit με όρισμα κάθε ένα από τους
κόμβους του δένδρου. Ο κώδικας υλοποιεί μία προδιατεταγμένη διάσχιση του
δένδρου.

Ποιά αλλαγή χρειάζεται στον κώδικα για να υλοποιήσει ενδοδιατεταγμένη


διάσχιση και μεταδιατεταγμένη διάσχιση αντίστοιχα;
typedef char Item;
void traverse(link h, void (*visit)(link))
{
typedef struct node *link; if (h == NULL) return;
struct node (*visit)(h);
{ traverse(h->l, visit);
Item item;
link l, r; traverse(h->r, visit);
}; }
2. ΠΡΟΔΙΑΤΕΤΑΓΜΕΝΗ ΔΙΑΣΧΙΣΗ (ΜΗ ΑΝΑΔΡΟΜΙΚΗ)
Η μη αναδρομική συνάρτηση που ακολουθεί βασίζεται σε στοίβα και είναι
λειτουργικά ισοδύναμη με την αντίστοιχη αναδρομική συνάρτηση του
παραδείγματος 1.
typedef char Item; void traverse(link h, void (*visit)(link))
{
typedef struct node *link; STACKinit(MAX);
struct node STACKpush(h);
{ while (!STACKempty())
Item item; {
link l, r; (*visit)(h = STACKpop());
}; if (h->r != NULL) STACKpush(h->r);
void STACKinit(int); if (h->l != NULL) STACKpush(h->l);
int STACKempty(void); }
void STACKpush(link); }
link STACKpop(void);
3. ΔΙΑΣΧΙΣΗ ΣΕΙΡΑΣ ΕΠΙΠΕΔΟΥ
Αλλάζοντας την υποκείμενη δομή δεδομένων της προδιατεταγμένης
διάσχισης (παράδειγμα 2) από στοίβα σε ουρά, μετασχηματίζουμε τη
διάσχιση σε διάσχιση σειράς επιπέδου
typedef char Item; void traverse(link h, void (*visit)(link))
typedef struct node *link; {
struct node QUEUEinit(MAX);
{ QUEUEput(h);
Item item; while (!QUEUEempty())

link l, r; {
(*visit) (h = QUEUEget());
};
if (h->l != NULL)
void QUEUEinit(int);
QUEUEput(h->l);
int QUEUEempty(void);
if (h->r != NULL)
void QUEUEput(link);
QUEUEput(h->r);
link QUEUEget(); }
}
4. ΜΕΤΑΔΙΑΤΕΤΑΓΜΕΝΗ ΔΙΑΣΧΙΣΗ (ΜΗ ΑΝΑΔΡΟΜΙΚΗ)

Να δώσετε μία μη-αναδρομική υλοποίηση της μεταδιατεταγμένης διάσχισης


typedef char Item; void traverse(link h, void (*visit)(link))
{
STACKinit(MAX);
typedef struct node *link;
struct node while (!STACKempty() || h != NULL)
{
{ if (h != NULL)
Item item; {
STACKpush(h);
link l, r;
h = h->l;
}; }
else
{
void STACKinit(int); (*visit) (h = STACKpop());
int STACKempty(void); h = h->r;
void STACKpush(link); }
}
link STACKpop(void); }
5. ΥΠΟΛΟΓΙΣΜΟΣ ΠΑΡΑΜΕΤΡΩΝ ΔΕΝΔΡΟΥ
Να υπολογίσετε τις βασικές δομικές ιδιότητες ενός δένδρου με χρήση απλών
αναδρομικών διαδικασιών
typedef char Item; int height(link h)
typedef struct node *link; {
struct node int u, v;
{
Item item; if (h == NULL)
link l, r; return -1;
}; u = height(h->l);
v = height(h->r);
int count(link h) if (u > v)
{ return u + 1;
else
if (h == NULL) return 0;
return v + 1;
return count(h->l) + count(h->r) + 1;
}
}
6. ΓΡΗΓΟΡΗ ΣΥΝΑΡΤΗΣΗ ΕΚΤΥΠΩΣΗΣ ΔΕΝΔΡΟΥ

Να γράψετε μία αναδρομική συνάρτηση που παρακολουθεί το ύψος ενός


δένδρου και χρησιμοποιεί αυτή την πληροφορία για τη ρύθμιση των περιθωρίων
κατά την εκτύπωση μίας αναπαράστασης του δένδρου.
Θεωρούμε ότι τα στοιχεία των κόμβων είναι χαρακτήρες του λατινικού
αλφαβήτου
E

E D
B
/ \
A
D H *
/\ /\ *

B F C
*
/\ / \ *
A C G *
/\/\ /\ H
F
*
G
*
*
*
7. ΚΑΤΑΣΚΕΥΗ ΔΕΝΔΡΟΥ ΣΥΝΤΑΚΤΙΚΗΣ ΑΝΑΛΥΣΗΣ
Να γράψετε ένα πρόγραμμα το οποίο δημιουργεί ένα δένδρο συντακτικής
ανάλυσης από μία προθεματική παράσταση. Για λόγους απλούστευσης
θεωρούμε ότι οι όροι είναι μεμονωμένοι χαρακτήρες.
Κάθε κλήση της αναδρομικής συνάρτησης δημιουργεί ένα νέο κόμβο του
οποίου το γλωσσικό σημείο είναι ο επόμενος χαρακτήρας της εισόδου.
Αν το γλωσσικό σημείο είναι όρος, επιστρέφουμε τον νέο κόμβο.
Αν είναι τελεστής, ορίζουμε τον αριστερό και τον δεξιό δείκτη έτσι ώστε να
δείχνουν στο δένδρο που κατασκευάζεται (αναδρομικώς) για τα δύο ορίσματα.
*
+ f
a *
* +
b c d e

*+a**bc+def
char *a; link parse ()
typedef struct Tnode *link; { char t = a[i++];
struct Tnode { char token; link l, r }; link x = NEW ( t, NULL, NULL);
link NEW (char token, link l, r ) if ( ( t == ‘+’ ) || ( t ==‘*’ ) )
{ link x = malloc ( sizeof *x ); {
x -> token = token; x -> l = parse ();
x -> l = l; x-> r = parse ();
x -> r = r; }
return x; return x;
} }
8. ΜΕΤΡΗΣΗ ΦΥΛΛΩΝ ΔΕΝΔΡΩΝ

Να γράψετε ένα πρόγραμμα που μετράει τα φύλλα ενός δυαδικού


δένδρου.
typedef char Item;
int count_leaves(link x)
typedef struct node *link; {
struct node if (x == NULL)
{ return 0;
Item item; if (x->r == NULL && x->l == NULL)
link l, r; return 1;
}; return (count_leaves(x->l) + count_leaves(x->r));
}
9. ΠΛΗΘΟΣ ΚΟΜΒΩΝ ΔΥΑΔΙΚΟΥ ΔΕΝΔΡΟΥ

Να γράψετε ένα πρόγραμμα που μετράει το πλήθος των κόμβων ενός


δυαδικού δένδρου οι οποίοι έχουν ένα εξωτερικό και ένα εσωτερικό παιδί
typedef char Item; int count(link x)
typedef struct node *link; { link u = x->l, v = x->r;
struct node if (u == NULL && v == NULL) return 0;
{
if (u != NULL && v == NULL) return count(u);
Item item;
link l, r; if (u == NULL && v != NULL) return count(v);
}; if (has_children(u) && !has_children(v))
return 1 + count(u);
int has_children(link x)
{ if (has_children(v) && !has_children(u))
if ((x->r != NULL) || (x->l != NULL)) return 1 + count(v);
return 1; return count(u) + count(v);
return 0;
}
}
ΑΣΚΗΣΗ BONUS
Να γραφεί ένα πρόγραμμα, το οποίο θα υλοποιεί ένα γενεαλογικό δένδρο. Κάθε
κόμβος θα περιέχει στοιχεία σχετικά με το ονοματεπώνυμο, το φύλο και την ημ/νία
γέννησης.
Το πρόγραμμα θα έχει τη δυνατότητα εισαγωγής νέων κόμβων στο δένδρο και θα
μπορεί να βρίσκει τους συγγενείς (πατέρα, μητέρα, παππού, γιαγιά, αδέλφια,
παιδιά, εγγόνια, θείους, εξαδέλφια, ανίψια) ενός προσώπου.

You might also like