Laboratorio di
Algoritmi e Strutture Dati
II Esercitazione Guidata
Teresa M.A. Basile
– [email protected] –
Dipartimento di Informatica
Università degli Studi di Bari “Aldo Moro”
1
_TRACCIA_
Cosa consegnare
Consegnare in un archivio compresso la risoluzione della traccia in C++
(sorgenti di tutte le ADT utilizzate ed eseguibile) e una descrizione sintetica, in
un file di testo, della strategia utilizzata che risponda ai seguenti punti:
●
●
●
●
●
Input: elencare i dati di input. Per ognuno fornire il nome, il tipo, primitivo o
derivato, ed una brevedescrizione;
Output: elencare i dati di output. Per ognuno fornire il nome, il contenuto, il tipo –
primitivo o derivato – ed una breve descrizione;
Ipotesi ed assunzioni: riportare l’elenco di ipotesi ed assunzioni. Ad es., per i dati
di input specificare eventuali ordinamenti ipotizzati sui dati, esistenza di duplicati, i
limiti sui valori, il limite sul volume, la fine dei dati, il supporto di memorizzazione, le
modalità (a menu, su richiesta, da altri programmi etc.); per i dati di output, l’ordine
e il limite sul volume, il supporto di memorizzazione, l’eventuale periodicità etc.;
Strutture dati: elencare le strutture dati scelte per la risoluzione del problema,
motivandone brevemente la scelta;
Strategia solutiva: Riportare in linguaggio naturale la descrizione della strategia
solutiva del programma principale e di tutte le eventuali procedure.
2
_TRACCIA_ (1)
Fornire in un file util bin tree.cpp la realizzazione in C++ delle seguenti
funzioni che operano su alberi binari di elementi di tipo intero:
●
●
●
int odd(bintree<int> &T, int k)
calcola e restituisce il numero di nodi di livello k il cui valore e' dispari;
int even_leafs(bintree<int> &T)
calcola e restituisce il numero di foglie il cui valore e' pari;
int leafs_with_even_parent(bintree<int> &T)
calcola e restituisce il numero di foglie che hanno come genitore un nodo il
cui valore e' pari.
Prevedere un main che acquisisca automaticamente un albero binario
e mostri a video il test delle funzioni implementate.
3
int odd(BinTree<T,R> &T, int k)
Descrizione :
calcola e restituisce il numero di nodi di livello k il cui valore e dispari;
Input :
- BinTree<T,R> &T: generica struttura albero;
- int k: numero intero identificante il livello da analizzare
Output :
- intero: intero rappresentante il numero di nodi con valore dispari ad
un determinato livello
Ipotesi e assunzioni:
- le strutture devono necessariamente valori interi; non sono richiesti
ulteriori vincoli
- il valore restituito sarà maggiore o uguale a 0;
Strategia risolutiva:
- Scansione per livelli dell'albero;
- attraverso un calcolo sui nodi è possibile conoscere il livello scandito;
- raggiunto il livello richiesto si effettua il controllo dei valori contenuti
4
nei nodi e, in caso di valore dispari, si incrementa un contatore apposito
int even_leafs(BinTree<T,R> &T)
Descrizione :
calcola e restituisce il numero di foglie il cui valore e pari;
Input :
BinTree<T,R> &T: generica struttura albero;
Output :
intero: intero rappresentante il numero di foglie con valore pari
Ipotesi e assunzioni:
- le strutture devono necessariamente valori interi; non sono richiesti
ulteriori vincoli
- il valore restituito sarà maggiore o uguale a 0;
Strategia risolutiva:
- Scansione per livelli dell'albero;
- quando si incrocia un nodo senza figli, si effettua un controllo sul
valore contenuto;
- se pari, si incrementa un apposito contatore
5
proposta
void binVisita(Nodo n, BinAlbero &T){
if (!T.binAlberoVuoto()){
// 1 esame anticipato del nodo n
if (!T.sinistroVuoto(n))
binVisita(T.figlioSinistro(n), T)
// 2 esame simmetrico del nodo n
if (!T.destroVuoto(n))
binVisita(T.figlioDestro(n), T)
// 3 esame differito del nodo n
}
}
esame del nodo:
se foglia(nodo) (sinistroVuoto(nodo) && destroVuoto(nodo))
allora
se (leggiNodo(nodo,T)%2==0) foglie_pari++
6
int leafs_with_even_parent(BinTree<T,R> &T)
Descrizione :
calcola e restituisce il numero di foglie che hanno come genitore un
nodo il cui valore è pari
Input :
- BinTree<T,R> &T: generica struttura albero;
Output :
- intero: intero rappresentante il numero di foglie con valore pari
Ipotesi e assunzioni:
- le strutture devono necessariamente valori interi; non sono richiesti
ulteriori vincoli
- il valore restituito sarà maggiore o uguale a 0;
Strategia risolutiva:
- Scansione per livelli dell'albero;
- quando si incrocia un nodo senza figli si effettua un controllo sul
valore contenuto nel padre;
- se pari, si incrementa un apposito contatore
7
proposta
void binVisita(Nodo n, BinAlbero &T){
if (!T.binAlberoVuoto()){
// 1 esame anticipato del nodo n
if (!T.sinistroVuoto(n))
binVisita(T.figlioSinistro(n), T)
// 2 esame simmetrico del nodo n
if (!T.destroVuoto(n))
binVisita(T.figlioDestro(n), T)
// 3 esame differito del nodo n
}
}
esame del nodo:
se foglia(nodo) (se sinistroVuoto(nodo) && destroVuoto(nodo))
allora
se (leggiNodo(binpadre(nodo))%2==0) foglie_con_padre_pari++
8
_TRACCIA_ (2)
Dopo aver acquisito un albero n-ario di elementi di tipo double (o int)
fornire la realizzazione in C++ delle seguenti funzioni:
1) double somma(AlberoN<T> Tree)
restituisce la somma di tutti gli elementi dell'albero n-ario T
calcolata in modo RICORSIVO;
2) double sommaLivello(AlberoN<T> Tree, int k)
restituisce la somma di tutti gli elementi di livello k dell'albero nario calcolata in modo RICORSIVO;
3) pari(AlberoN<T> Tree)
restituisce tutti i nodi dell'albero T radici di sottoalberi aventi nodi
la cui somma e' pari;
4) dispari(AlberoN<T> Tree)
restituisce tutti i nodi dell'albero T che sono radici di sottoalberi
aventi nodi (inclusa la radice) la cui somma e' dispari;
5) double media_livello(AlberoN<T> Tree, int k)
restituisce la media dei valori di tutti i nodi dell'albero T di livello k;
9
_TRACCIA_ (2)
Prevedere nel main una funzione di popolamento automatico
dell'albero n-ario T evitando di acquisirlo di volta in volta da
tastiera e visualizzarne il contenuto prima di eseguire in ordine
le seguenti operazioni:
1)
2)
3)
4)
5)
visualizza
visualizza
visualizza
visualizza
visualizza
il
il
il
il
il
valore
valore
valore
valore
valore
restituito
restituito
restituito
restituito
restituito
da
da
da
da
da
somma(T)
sommaLivello(T,k)
pari(T)
dispari(T)
media_livello(T,k)
10
double somma(AlberoN<T> Tree)
Descrizione :
calcola e restituisce la somma di tutti gli elementi dell'albero n-ario
Tree
Input :
- AlberoN<T> Tree: generica struttura albero;
Output :
- reale: rappresentante la somma di tutti gli elementi dell'albero nario Tree
Ipotesi e assunzioni:
- le strutture possono contenere valori di tipo interi o reali, non sono
richiesti ulteriori vincoli;
- il calcolo deve avvenire in modo ricorsivo;
- il valore restituito sarà maggiore o uguale a 0;
Strategia risolutiva:....
- Scansione per livelli dell'albero; // Visita albero
- Per ogni nodo dell'albero viene richiamata ricorsivamente una
funzione di somma che lavora su un sottoalbero la cui radice è
rappresentata dal nodo che stiamo analizzando;
- questo fino ad arrivare ad un nodo foglia.
11
double somma(AlberoN<T> Tree)
double somma(AlberoN<_double_> T){
AlberoN<_double_>::nodo n = T.Radice();
return(somma(T,n));
}
double somma(AlberoN<_double_> T, AlberoN<_double_>::nodo n){
_double_ s = T.leggiNodo(n);
if (!T.Foglia(n)){
AlberoN<_double_>::nodo k = T.primoFiglio(n);
while(!T.ultimoFratello(k)){
s += somma(T,k);
k = T.succFratello(k);
}
s += somma(T,k);
}
return(s);
}
12
double sommaLivello(AlberoN<T> Tree, int k)
Descrizione :
calcola e restituisce la somma di tutti gli elementi di livello k dell'albero
n-ario Tree;
Input :
- AlberoN<T> Tree: generica struttura albero;
- int k: numero intero identificante il livello da analizzare
Output :
- reale: rappresentante la somma di tutti gli elementi dell'albero n-ario
Tree ad un determinato livello
Ipotesi e assunzioni:
- le strutture possono contenere valori di tipo interi o reali, non sono
richiesti ulteriori vincoli;
- il calcolo deve avvenire in modo ricorsivo;
- il valore restituito sarà maggiore o uguale a 0;
Strategia risolutiva:
- Scansione per livelli dell'albero;
- attraverso un calcolo sui nodi è possibile conoscere il livello scandito;
- raggiunto il livello richiesto si effettua il calcolo della somma dei valori
contenuti nei nodi
13
double sommaLivello(AlberoN<T> Tree, int k)
double sommaLivello(AlberoN<_double_> T, int k){
AlberoN<_double_>::nodo n = T.radice();
return(sommaLivello(T,n,1,k));
}
double sommaLivello(AlberoN<_double_> T, AlberoN<_double_>::nodo n, int currLev, int h){
_double_ s = 0;
if (!T.foglia(n)){
if (currLev == h)
return T.legginodo(n);
else {
AlberoN<_double_>::nodo n1 = T.primoFiglio(n);
while(!T.ultimoFratello(n1)){
s+= sommaLivello(T,n1,currLev++,k);
n1 = T.succFratello(n1);
}
s += sommaLivello(T,n1,currLev++,k);
}
} else
if (currLev == h)
s = T.legginodo(n);
return(s);
}
14
double media_livello(AlberoN<T> Tree, int k)
Descrizione :
calcola e restituisce la media di tutti gli elementi di livello k dell'albero
n-ario Tree;
Input :
- AlberoN<T> Tree: generica struttura albero;
- int k: numero intero identificante il livello da analizzare
Output :
- reale: rappresentante la media di tutti gli elementi dell'albero n-ario
Tree ad un determinato livello
Ipotesi e assunzioni:
- le strutture possono contenere valori di tipo interi o reali, non sono
richiesti ulteriori vincoli;
- il valore restituito sarà maggiore o uguale a 0;
Strategia risolutiva:
- Scansione per livelli dell'albero;
- attraverso un calcolo sui nodi è possibile conoscere il livello scandito;
- raggiunto il livello richiesto si effettua il calcolo della somma dei valori
contenuti nei nodi e si incrementa un apposito contatore che identifica
il numero di nodi per il determinato livello da analizzare
15
double media_livello(AlberoN<T> Tree, int k)
Considerazioni: come sommalivello ma incrementando un contatore
per il numero di nodi sommati
16
pari(AlberoN<T> Tree)
Descrizione :
restituisce tutti i nodi dell'albero Tree che sono radici di sottoalberi
aventi nodi la cui somma e' pari
Input :
- AlberoN<T> Tree: generica struttura albero;
Output :
- struttura che memorizza i nodi con la particolare caratteristica
richiesta, ovvero che siano radici di sottoalberi aventi nodi la cui
somma è pari
Ipotesi e assunzioni:
- le strutture albero possono contenere valori di tipo interi o reali,
non sono richiesti ulteriori vincoli;
- la struttura di appoggio per memorizzare i nodi di output è una
lista ..... (peculiarità della lista che hanno indotto a questa scelta)
Strategia risolutiva:....
- Scansione per livelli dell'albero; // Visita albero bfs
- Per ogni nodo dell'albero (uso di somma(Albero,Nodo)) viene
richiamata ricorsivamente una funzione di somma che lavora su un
sottoalbero la cui radice è rappresentata dal nodo che stiamo
analizzando, questo fino ad arrivare ad un nodo foglia;
- Se il valore così calcolato è pari, si memorizza il nodo in esame
nella opportuna struttura dati scelta per contenere il risultato
17
dispari(AlberoN<T> Tree)
Descrizione :
restituisce tutti i nodi dell'albero Tree che sono radici di sottoalberi aventi
nodi (inclusa la radice) la cui somma e' pari
Input :
- AlberoN<T> Tree: generica struttura albero;
Output :
- struttura che memorizza i nodi con la particolare caratteristica richiesta,
ovvero che siano radici di sottoalberi aventi nodi (incluso il nodo radice
stesso) la cui somma è dispari
Ipotesi e assunzioni:
- le strutture albero possono contenere valori di tipo interi o reali, non sono
richiesti ulteriori vincoli;
- la struttura di appoggio per memorizzare i nodi di output è una lista .....
(peculiarità della lista che hanno indotto a questa scelta)
Strategia risolutiva:....
- Scansione per livelli dell'albero; // Visita albero bfs
- Per ogni nodo dell'albero (uso di somma(Albero,Nodo)) viene richiamata
ricorsivamente una funzione di somma che lavora su un sottoalbero la cui
radice è rappresentata dal nodo che stiamo analizzando, questo fino ad
arrivare ad un nodo foglia;
- Se il valore così calcolato sommato al valore contenuto nel nodo in esame,
è dispari, si memorizza il nodo in esame nella opportuna struttura dati
scelta per contenere il risultato
18