Sei sulla pagina 1di 3

Algoritmi e Principi dell'Informatica

II Prova in itinere
18 maggio 2018

Esercizio 3
Si consideri il seguente frammento di codice:

int somma=0;
j=0;
for (i=0; i<N; i++){
j=0;
while (j < i^2){
somma=somma + funzione(N);
j++;
}
}

int funzione( int k ){


if ( k > 1 ){
for (int i=1; i<100; i++)
cout<<"*";
return 2 * funzione(k/2);
}
else return 0;
}

a) Si determini l'equazione di ricorrenza per il calcolo della complessità temporale di funzione


in funzione di k e si risolva l'equazione
b) Si determini la complessità del frammento di codice in funzione di N

SOLUZIONE

Analisi della complessità di funzione

Se k<=1 viene valutata la condizione ed eseguito il rame else: questo richiede un tempo di
esecuzione costante c che è in Θ(1)
Se k>1 si valuta la condizione, si esegue un ciclo per 100 volte (un numero costante di volte) e
si richiama la funzione stessa passando come parametro la metà (il valore restituito dalla
funzione viene moltiplicato per 2): questo richiede pertanto un tempo di esecuzione costante +
il tempo necessario per eseguire la funzione stessa su k/2

L'equazione di ricorrenza pertanto è

T(k) = c se k<=1
T(k) = d + T(k/2) se k>1

Si può risolvere per sostituzione oppure utilizzando le formule di ricorrenza comune, come
riportato nelle slide (quest'esempio viene presentato a lezione): si ottiene Θ(log k)
Analisi della complessità del frammento di codice:

- il ciclo esterno viene eseguito N volte


- il ciclo interno è dipendente dal ciclo esterno e viene eseguito i^2 volte

In particolare verrà eseguito


0 volte quando i=0
1=1^2 volta quando i=1
4=2^2 volte quando i=2
9=3^2 volte quando i=3
Ecc.

Verrà eseguito:

"Sommatoria per i che va da 1 a n-1 di i^2 volte"


Questa è una delle sommatorie con soluzione in forma chiusa comuni ed il risultato è pari a
n(2n+1)(n+1)/6 = Θ(n^3)

All'interno dei due cicli viene richiamata funzione sempre con parametro N, quindi con
complessità Θ(log n)

La complessità totale del frammento di codice pertanto è Θ(n^3 * log n)


Esercizio 4

Si consideri un albero binario contenente valori interi. Si scriva una funzione C++ che riceve in
ingresso un valore k, che verifica se è un albero binario pieno e tutte le foglie si trovano ad una
profondità maggiore o uguale a k. La funzione deve restituirà true se le condizioni sono
verificate, false altrimenti.

SOLUZIONE

#define TRUE 1
#define FALSE 0

int VerificaPienoFoglieProfonde(BinNode<Elem>* subroot, int k){


if (subroot == NULL)
return FALSE; //se per il nodo padre uno dei due figli è NULL qui si restituisce FALSE
else if (subroot-->isLeaf()) //qui si tratta il caso in cui entrambi figli sono NULL
if (k<=0)
return TRUE;
else
return FALSE;
return VerificaPienoFoglieProfonde(subroot->right(),k-1) &&
VerificaPienoFoglieProfonde(subroot->left(),k-1);
}

Si poteva anche
- effettuare esplicitamente il controllo per i nodi con un singolo figlio
- utilizzare una variabile da passare come parametro alla funzione per calcolare la profondità e
confrontare quella con k
- effettuare una visita in ampiezza

Attenzione alla differenza tra alberi completi e pieni…