Algoritmi e basi di dati – modulo Algoritmi e Strutture dati – a.a. 2012/2013
27 febbraio 2013
Cognome
Nome
1
2
3
Matricola
4
5
Esercizio 1
Sia data una struttura hash memorizzata su un array di 100 posizioni che memorizza un insieme di
al massimo 80 elementi. Indicare il contenuto delle prime 4 celle dell’array, inizialmente vuoto,
dopo le operazioni seguenti (indirizzamento con il metodo dello hash modulare, scansione lineare):
a) Inserimento dell’elemento 100
b) Inserimento dell’elemento 300
c) Inserimento dell’elemento 200
d) Cancellazione dell’elemento 300
e) Inserimento dell’elemento 400
Indirizzo Inizio
Dopo a)
Dopo b)
Dopo c)
Dopo d)
Dopo e)
0
-1
100
100
100
100
100
1
-1
-1
300
300
-2
400
2
-1
-1
-1
200
200
200
3
-1
-1
-1
-1
-1
-1
Esercizio 2
Dato il grafo orientato in figura, trovare i cammini minimi dal nodo A a tutti gli altri nodi. Per ogni
passo dell'algoritmo, indicare l'insieme Q, le distanze minime stimate e i nodi precedenti nel
cammino minimo stimato.
A
2
B
3
4
C
9
9
4
1
D
3
E
F
Q
A
B
C
D
E
F
dist
pred
dist
pred
dist
pred
dist
pred
dist
pred
dist
pred
ABCDEF
0
-
inf
-
inf
-
inf
-
inf
-
inf
-
BCDEF
0
-
2
A
4
A
3
A
inf
-
inf
-
CDEF
0
-
2
A
4
A
3
A
inf
-
11
B
CEF
0
-
2
A
4
A
3
A
12
D
11
B
EF
0
-
2
A
4
A
3
A
8
C
11
B
F
0
-
2
A
4
A
3
A
8
C
9
E
Esercizio 3
Calcolare la complessità del for in funzione di n>0.
for (int i=0; i <= g(g(n))+f(n); i++) cout << i;
con le funzioni f e g definite come segue. Indicare per esteso le relazioni di ricorrenza e, per ogni
comando ripetitivo, il numero di iterazioni e la complessità della singola iterazione.
int g(int x){
int f(int x){
if (x<=0) return 1;
if (x<=0) return 1;
int a = 0;
int a = g(x);
for (int i=0; i <= x; i++)
int b = a + 2*f(x/2);
a+=i;
for (int i=0; i <= x*x; i++)
for (int j=a; j >= 0; j--)
cout << i;
cout << a;
return b + 2*f(x/2);
return a*a + g(x-1); }
}
Funzione g
Primo for:
Complessità della singola iterazione: O(1)
Numero di iterazioni: O(n)
Complessità del for: O(n)
Secondo for:
Complessità della singola iterazione: O(1)
Numero di iterazioni: O(n^2)
Complessità del for: O(n^2)
Tg(0)= d
Tg(n)= cn^2 + Tg(n-1)
Tg(n) è O(n^3)
Rg(0)= d
Rg(n)= cn^4 + Rf(n-1)
Rg(n) è O(n^5)
Funzione f
for:
Complessità della singola iterazione: O(1)
Numero di iterazioni: O(n^2)
Complessità del for: O(n^2)
Tf(0)= d
Tf(n)= cn^3+ 2Tf(n/2)
Tf(n) è O(n^3)
Rf(0)= d
Rf(n)= cn^5+ 4Rf(n/2)
Rf(n) è O(n^5)
Calcolo for del blocco:
numero iterazioni: g(g(n)) + f(n)= g(n^5) + O(n^5)= O(n^25)
Complessità della singola iterazione: Tg(n) + Tg(n^5) + Tf(n) = O(n^3) + O(n^15) + O(n^3)
= O(n^15)
Complessità del for: O(n^40)
Esercizio 4
Scrivere una funzione booleana che, dati due alberi binari t1 e t2 ad etichette intere, controlli che
siano speculari.
bool speculari(Node* t1, Node* t2){
if (!t1 && !t2) return true;
if (!t1) return false;
if (!t2) return false;
if (t1->label != t2->label) return false;
return speculari(t1->left, t2->right)
&& speculari(t1->right, t2->left);
}
Esercizio 5
Scrivere una funzione che, dato un albero generico t ad etichette intere, conta i nodi dell'albero che
hanno più figli che fratelli successivi.
int conta(Node* t) {
if (!t) return 0;
return (fratelli(t->left) > fratelli(t->right))
+ conta(t->left) + conta(t->right);
}
int fratelli(Node* t) {
if (!t) return 0;
return 1 + fratelli(t->right);
}
O(n):
int conta2(Node* t, int& fratelli) {
if (!t) {fratelli = 0; return 0;}
int figli;
int ret = conta2(t->left, figli) + conta2(t->right, fratelli);
if (figli > fratelli) ret++;
fratelli++;
return ret;
}