Sei sulla pagina 1di 7

LINK FORMS

INFORMATICA TEORICA

https://forms.office.com/Pages/ResponsePage.aspx?id=K3EXCvNtXUKAjjCd8ope6xGhEotCVVtKrA8eYdjn
a3RUNlAyNUJMTjVCRTZFVjFVWDRKUDdOWDJJSS4u

ALGORITMI

https://forms.office.com/Pages/ResponsePage.aspx?id=K3EXCvNtXUKAjjCd8ope612l9yEARrZBjhLl1lBue
NxUMVRUNTJFVFRUUjdSTVRLTDZTMEU4WUY5Qi4u

RECUPERI

https://forms.office.com/Pages/ResponsePage.aspx?id=K3EXCvNtXUKAjjCd8ope612l9yEARrZBjhLl1lBue
NxUM0kzV01NTVdRUTNYOE1UUjlFSzMwV1UyRy4u

SOLUZIONI PARTE ALGORITMI – API – LUGLIO 2020

ESERCIZIO COMPLESSITA’

Si consideri la funzione fun1, ipotizzando che a, b, m e n siano interi positivi:

1 void fun2 (int a, int b, int m) {

2 for (int i=1; i<m; i++){

3 a+=b;

4 cout<<a;

5 }

6 }
7

8 void fun1 (int n, int a, int b, int m) {

9 if (n == 1)

10 fun2 (a, b, m);

11 else {

12 fun1 (n-1, a, b, m);

13 fun2 (a, b, m);

14 fun1 (n-1, b, a, m);

15 }

16 }

Ipotizzando che m=O(n), si determini la complessità temporale di fun1 scrivendo tutti i passaggi
per calcolarla.

SOLUZIONE (con spiegazioni)

2 for (int i:=1; i<m; i++){ viene eseguito m volte = O(n)

3 a+=b; Theta(1)

4 cout<<a; Theta(1)

fun2 è O(n)

9 if (n == 1) Theta(1)

10 fun2 (a, b); O(n)

Il ramo if è O(n)
11 else {

12 fun1 (n-1, a, b, m); T(n-1)

13 fun2 (a, b, m); O(n)

14 fun1 (n-1, b, a, m); T(n-1)

15 }

Il ramo else richiama due volte la funzione stessa su un problema di dimensione n-1

e richiama una volta fun2 che ha complessità O(n)

La complessità di fun1 è pertanto

T(n) = O(n) se n==1

T(n) = 2*T(n-1) + O(n) se n>1

Quest’equazione di ricorrenza rientra tra quelle comuni

Rientra nel caso: Σ 1≤i<h ai T(n-i) + cnβ

Posto a = Σ 1≤i<h ai la soluzione dell’equazione è

1) T(n) è O(nβ+1) se a=1

2) T(n) è O(annβ) se a ≥ 2

In questo caso a=2, β=1 quindi T(n) è O(annβ)  T(n)=O(n*2^n)


ESERCIZIO ORDINAMENTO

Dato il seguente array di interi

5 3 8 0 2 9 1 7 6 4

Si consideri l’algoritmo di quicksort: si mostri il partizionamento dell’array ipotizzando che il pivot sia 5.

Si mostri l'algoritmo passo passo partendo dall'array dato (fare copia e incolla) fino ad arrivare all'array
partizionato. Per ogni riga indicare quali numeri vengono scambiati

Ad esempio:

a b c d e f g (array iniziale)

a b f d e c g (scambio c con f)

SOLUZIONE (con spiegazioni)

Nota: si richiede solamente il primo partizionamento, non si richiede di ordinare l’intero array

Esistono due algoritmi per farlo.

Algoritmo con entrambi gli indici che partono a sinistra

5 3 8 9 0 2 1 7 6 4
Lascio il pivot nella posizione iniziale, entrambi gli indici i e j partono dalla prima posizione. j rappresenta
l’ultima posizione con valori minori del pivot già scambiati o al posto giusto e si sposterà verso destra
man mano che questa parte verrà costruita; i invece si sposterà verso destra sulla parte che contiene
valori maggiori del pivot e si fermerà sul primo valore minore del pivot, che non si trova nella posizione
corretta. Dopo qualche passaggio j sarà su 3 e i sarà sullo 0

5 3 8 9 0 2 1 7 6 4  scambiando 0 con 8 la parte di sinistra inizia ad essere ordinata

5 3 0 9 8 2 1 7 6 4  ora j si trova su 0 e i si trova su 8; i si sposta verso destra fino a trovare un


numero minore del pivot (il 2)  verranno quindi scambiati 9 e 2

5 3 0 2 8 9 1 7 6 4  ora j si trova su 2 e i si trova su 9; i si sposta verso destra fino a trovare un


numero minore del pivot (l’1)  verranno quindi scambiati 8 e 1

5 3 0 2 1 9 8 7 6 4  ora j si trova su 1 e i si trova su 8; i si sposta verso destra fino a trovare un


numero minore del pivot (il 4) – notate come stanno crescendo le parti con i valori minori del pivot e con
il valori maggiori del pivot, evidenziate in giallo e azzurro  verranno quindi scambiati 4 e 9

5 3 0 2 1 4 8 7 6 9  ora j si trova su 4 e l’indice i ha raggiunto la fine dell’array. Abbiamo


terminato, dobbiamo solamente sistemare la posizione del valore 5, che andrà messo al posto del 4
(scambio 5 e 4)

4 3 0 2 1 5 8 7 6 9

Algoritmo con indice di sinistra e indice di destra

5 3 8 9 0 2 1 7 6 4

Porto 5 in ultima posizione (effettuando uno scambio tra 5 e 4)

4 3 8 9 0 2 1 7 6 5

l’indice l sarà posizionato su 4, l’indice r su 6; l si sposta a destra fino a trovare un numero maggiore del
pivot, quindi arriva a 8; l’indice r si sposta verso sinistra fino a trovare un numero minore del pivot,
quindi arriva a 1

4 3 8 9 0 2 1 7 6 5 (scambio 1 e 8)

4 3 1 9 0 2 8 7 6 5

l si sposta ancora a destra fino a trovare un numero maggiore del pivot, quindi arriva a 9; l’indice r si
sposta verso sinistra fino a trovare un numero minore del pivot, quindi arriva a 2

4 3 1 9 0 2 8 7 6 5 (scambio 9 e 2)
4 3 1 2 0 9 8 7 6 5 Ora spostandosi a destra con l’indice l si arriva a 9 e con l’indice r si arriva 0 –> i
due indici si sono incrociati (per come funziona l’algoritmo avvengono due scambi che qui non vengono
riportati)

Ora la situazione mostra che nella prima parte abbiamo valori < del pivot, nella seconda parte a meno
del valore 5 abbiamo valori > del pivot

4 3 1 2 0 9 8 7 6 5

Per ottenere l’array partizionato sarà sufficiente scambiare 5 con 9 (primo elemento della partizione di
destra)

4 3 1 2 0 5 8 7 6 9

ESERCIZIO ALBERO

Si consideri un albero generico contenente valori interi. Si scriva una funzione C++ che riceve in
ingresso la radice dell'albero binario e verifichi se soddisfa le seguenti proprietà: a) i figli di ogni
nodo sono in ordine crescente; b) ciascun nodo ha un valore maggiore di tutti i figli. Se queste
condizioni sono soddisfatte per tutti i nodi la funzione restituirà 1, altrimenti restituirà 0.

L’albero vuoto soddisfa la definizione.

SOLUZIONE

int verificaProprietà(GTNode* subroot) {

if (subroot==NULL || subroot->isLeaf())

return 1; //per definizione soddisfa le proprietà

else { //non è foglia e quindi esiste almeno leftmost_child

//subroot è il nodo corrente (padre), ora accedo ai figli (con il puntatore temp)

for (GTNode* temp=subroot->leftmost_child(); temp != NULL; temp = temp->right_sibling()) {

if (temp->right_sibling()!=NULL)
if (temp->value() > temp->right_sibling()->value() || //verifico ordine crescente

temp->value() > subroot->value()) //e confronto con il padre

return 0; //se una delle proprietà non è soddisfatta restituisco 0

if (verificaProprietà(temp))==0 return 0; //verifico proprietà per il figlio

return 1; //se sono arrivato qui, le proprietà per il nodo corrente (e i suoi figli) sono

//soddisfatte e quindi restituisco 1

Potrebbero piacerti anche