Esercizio: scrivere una funzione che ritorna la somma delle foglie di un albero. Si noti che le foglie sono, come sempre, definite come i nodi che non hanno figli. Il prototipo della funzione è:
int SommaFoglie(TipoAlbero);
Soluzione: si procede come per gli alberi binari, ossia si considera che un albero, se non è vuoto, è composto da un nodo e da un certo numero di sottoalberi. Si considerano quindi i vari casi significativi:
L'algoritmo si ottiene mettendo le opportune istruzioni condizionali:
La somma nel sottoalbero a->figli[i] si fa con la chiamata ricorsiva SommaFoglie(a->figli[i]). Questo calcolo va fatto con i che va da 0 a a->numfigli-1.
Come faccio a sommare tutti questi valori? Si tratta di sommare un certo numero di valori, quindi posso usare il metodo dell'accumulatore. In questo caso, posso usare il metodo perchè devo sommare un insieme di valori SommaFoglie(a->figli[0]), SommaFoglie(a->figli[1]), SommaFoglie(a->figli[2]), ecc. che sono tutti noti all'interno della funzione (sono valori di ritorno di funzioni chiamate tutte all'interno dello stesso record di attivazione). Il metodo non è corretto sulle funzioni ricorsive se si cerca di sommare dei valori che si trovano in record di attivazioni diversi.
int SommaFoglie(TipoAlbero a) { int somma, i; if(a==NULL) return 0; if(a->numfigli==0) return a->info; somma=0; for(i=0; i<a->numfigli; i++) somma+=SommaFoglie(a->figli[i]); return somma; }
Si ricorda che la regola da seguire, nella scrittura delle funzioni ricorsive è la seguente:
se la chiamata ricorsiva viene fatta su un problema più semplice di quello di partenza, è corretta
Nel caso degli alberi, si fa di solito la chiamata ricorsiva sui sottoalberi. A questo punto, si può pensare come se al posto della chiamata ricorsiva SommaFoglie(a->figli[i]) ci sia una funzione di libreria, di cui la correttezza è stata già dimostrata. Possiamo quindi riscrivere la funzione mettendo, al posto della chiamata ricorsiva, la chiamta di una funzione di libreria (che in realtà non esiste) leaf_sum,
int SommaFoglie(TipoAlbero a) { int somma, i; if(a==NULL) return 0; if(a->numfigli==0) return a->info; somma=0; for(i=0; inumfigli; i++) somma+=leaf_sum(a->figli[i]); return somma; }
Assumendo che leaf_sum sia una funzione di libreria che risolve il problema, la funzione completa è corretta. Questo ci dice che la funzione di partenza era corretta.