2.
Analisi degli Algoritmi
1
Algoritmi e strutture dati Definizioni
Struttura dati: organizzazione sistematica dei dati e del
loro accesso
Algoritmo: procedura suddivisa in passi che, eseguiti in
sequenza, consentono di eseguire un compito in tempo finito
Esempio: Max. di un vettore di n elementi
Algorithm arrayMax(A, n)
currentMax = A[0];
for (i=0; i < n; i++)
if (A[i] > currentMax)
currentMax = A[i];
return currentMax;
2
Nel mondo reale.......
Gli algoritmi sono al cuore di innumerevoli applicazioni
informatiche
Esempi
Routing in Internet
DBMS
Analisi e classificazione di documenti/Motori di ricerca
Ottimizzazione di progetti
Etc. Etc. Etc.
3
Esempio: Routing in Internet
Protocollo di Routing
5
Obiettivo: determinare
“buon” cammino sorg.-dest.
Astrazione usando grafi:
I nodi rappresentano
router
Gli archi descrivono i
link fisici
Costi sugli archi (link) :
ritardo, livello di
congestione
2
A
B
2
1
D
3
C
3
1
5
F
1
E
2
Cammino “buono”:
Di solito significa
cammino a costo minimo
Possibili def. alternative
4
Esempio: Accesso a basi di dati
Interrogazione
Obiettivo: rispondere
rapidamente.
Interrogazione
...
Data base
Data Record
5
Qualità di algoritmi e strutture dati
Efficienza
Tempo di esecuzione
Spazio (quantità di memoria)
I due aspetti sono interdipendenti
6
Come misurare l’efficienza?
10 ms
Programma A
Dati
Problema
Programma B
1 ms
Perché B gira più velocemente ?
Possiamo affermare che B sia “migliore” di A?
8
Misura dell’efficienza obiettivi
Indipendenza dall’implementazione
Generale (valida per ogni input, di qualsiasi
dimensione)
Misura indipendente dalla piattaforma Hw/Sw
9
Modello di costo RAM
Random Access Machine
Macchina che esegue le istruzioni in sequenza.
Insieme di operazioni primitive a costo unitario:
Assegnazione
A = 10; (costo 1)
Op. aritmetiche
A = B*C + D – 7; (costo 4)
Test
Lettura/Scrittura
A == B (costo 1)
System.out.println(A); (Costo 1)
10
Modello di costo/2
Costo di operazioni complesse:
Ciclo: somma costo test di fine ciclo e costo corpo del
ciclo
if…then…else: costo test più costo blocco istruzioni
che segue then o else (a seconda del caso)
Attivazione di un metodo: somma dei costi di tutte le
istruzioni presenti nel metodo
Costo: somma di tutti i costi
11
Esempio
Nel primo caso (vett. di 3
elementi) si ha costo 1
(ass.)+1 (ass. nel for) + 6
(test e incr. nel for) + 1
(test finale for) + 3 (test
if) + 1 (istruz. return) = 13
Nel secondo caso si ha 1
(ass.) + 1 (ass. nel for) + 10
(test e incr. nel for) + 1
(test finale for) + 5 (test
if) + 1 (istr. ass. nell’if) + 1
(istruz. return) = 20
AlgorithmarrayMax(A, n)
currentMax=A[0];
for (i=0; i<n; i++)
if (A[i]>currentMax)
currentMax=A[i];
return currentMax;
1
8
7
6
1
3
4
4
n=3
n=5
12
Perché il modello è accettabile?
MUL B,C
ADD A,B
A=A+B*C;
B
A
C
Ogni istruzione
corrisponde a una
sequenza finita di
istruzioni macchina
Ogni variabile occupa
una quantità finita di
memoria e quindi i
tempi di accesso a due
variabili sono legati da
una costante
N finito (es. 32 o 64 )
13
Vantaggi e svantaggi
Vantaggi: prescinde dalla
piattaforma Hw/Sw e dal
linguaggio di programmazione
Svantaggi: l’indicazione che si
ottiene è qualitativa
14
Quale input considerare?
La misura deve dipendere dalla dimensione dell’input
(n nel nostro esempio) ma non dal particolare input
considerato
Possibile alternative:
Analisi del caso peggiore: si considera il costo di
esecuzione nel caso peggiore
Analisi del caso medio: si considera il costo medio
dell’algoritmo rispetto ad una distribuzione
dell’input (richiede la conoscenza della
distribuzione)
In ogni caso occorre definire la dimensione dell’input
15
Dimensione dell’input
In generale: No. bit necessari a rappresentare l’input
Esempio (calcolo del Max. in un array di n interi)
n interi finiti (< MAXINT)
log(MAXINT) bit per rappresentare ogni valore.
Poiché MAXINT è una costante in pratica, il
numero di bit necessari a rappresentare un intero
è costante (es. 32)
Quindi: dimensione input è proporzionale a n
A volte le cose possono non essere così ovvie (si
pensi al problema di indovinare un numero proposto
nell’ultima slide)
16
Analisi nel caso peggiore
(esempio)
Nel caso peggiore l’array e’
ordinato in senso crescente
In questa ipotesi l’istruzione
currentMax=A[i];
è eseguita n-1 volte.
Il costo complessivo
dell’algoritmo è allora
1(ass)+1(ass for)+2n(test ed
increm for)+2(n-1)(test e
ass. if)+1(test finale for)
+1(return)=4n+3
AlgorithmarrayMax(A, n)
currentMax=A[0];
for (i=0; i<n; i++)
if (A[i]>currentMax)
currentMax=A[i];
return currentMax;
1
4
6
3
8
17
Analisi asintotica
Se si considerano tutte le costanti l’analisi può
divenire eccessivamente complessa
Interessa conoscere il costo al variare della
dimensione dell’input, a meno di costanti
Motivo: il costo è comunque calcolato a meno di
costanti, per le ipotesi fatte circa il modello
Un’analisi di questo tipo è detta asintotica
L’analisi asintotica è influenzata dall’operazione
dominante di un algoritmo
18
Istruzione dominante
Un’ operazione o istruzione si dice dominante se il
numero d(n) di volte che essa è eseguita nel caso
peggiore di input di dimensione n soddisfa:
f(n)<=a d(n) + b,
dove f(n) è la complessità dell’algoritmo nel caso
peggiore ed a e b sono costanti opportune
Es.: istruzione if (A[i]>currentMax) in
AlgorithmarrayMax(A, n)
19
Analisi di Insertion Sort
Algorithm insertionSort(A, n)
for (i=0; i<n; i++) {
tmp=A[i];
for (j=i; j>0 && tmp<A[j-1];
j--)
A[j]=A[j-1];
A[j] = tmp;
}
return A;
Inserisce l’elemento A[i]
nella posizione corretta
nel vettore ordinato
A[0,…,i-1]
Ex:
54321
i=0
i=1
i=2
i=3
i=4
54321
45321
34521
23451
12345
0 confronti
1 confronto
2 confronti
3 confronti
4 confronti
Ex:f (n) 1
2i 3n(n
4 51) /2f(n)=
O(n 2 )n
n1
i 0
20
Esempi
class esercizio {
public void Ex1(int n) {
int a, i;
for (i=0; i<n;i++)
a=i;
}
public void Ex2(int n) {
int a, i;
for (i=0; i<n*n;i++)
a=i;
}
public void Ex3(int n) {
int a, i, j;
for (i=0; i<n;i++)
for (j=0; j<=i;j++)
a=i;
}
}
Valutare la complessità
dei tre metodi
Complessità di Ex3:
1+2+....+n=O(n2)
21
Metodo Divide et Impera
Il problema è risolto ricorsivamente attraverso la
sua scomposizione in problemi di taglia inferiore
Divide: Problema suddiviso in un numero di
sottoproblemi di taglia inferiore
Impera: Sottoproblemi risolti ricorsivamente o
direttamente se di dimensione piccola a
sufficienza
Combina: Le soluzioni dei sottoproblemi sono
combinate per ottenere la soluzione al problema
originale
23
Merge Sort A[0...n]
A[0...n/2-1]
A[n/2...n-1]
Suddividi A in due sottovettori di dim. n/2
A[0...n/2-1]
A[n/2...n-1]
MergeSort A[0...n/2-1]
Si suppone n pari
per semplicità
MergeSort A[n/2...n-1]
Merge
A ordinato
24
Merge Sort/2
void mergesort(int[] A, int first, int last)
{
if (first < last) {
int mid = (first + last) / 2;
mergesort(A, first, mid);
mergesort(A, mid+1, last);
merge(A, first, last);
}
}
25
Merge Sort A[0...n] /3
Divide: divide gli n elementi da ordinare in due
sottosequenze da n/2 elementi. Costo: O(n)
Impera: ordina ricorsivamente usando il merge
sort le due sottosequenze. Costo: 2f(n/2)
Combina: fonde le due sottosequenze ordinate.
Costo: O(n)
La ricorsione termina quando si hanno solo due
elementi da ordinare. Costo:O(1)
Costo dell’algoritmo Merge Sort:
(1), n 2
f ( n)
2 f (n / 2) ( n), n 2
26
L’array
[1 8 6 4 10 5 3 2 22]
ordinato
con mergesort
27
Merge
void merge(int[] data, int first, int last) {
int mid = (first + last) / 2;
int i1 = 0, i2 = first, i3 = mid + 1;
while (i2 <= mid && i3 <= last)
if (data[i2] <data[i3])
temp[i1++] = data[i2++];
else temp[i1++] = data[i3++];
while (i2 <= mid)
temp[i1++] = data[i2++];
while (i3 <= last)
temp[i1++] = data[i3++];
for (i1 = 0, i2 = first;
i2 <= last; data[i2++] = temp[i1++]);
}
28
Equazioni di ricorrenza
Tempo di esecuzione di algoritmi ricorsivi
descritti con equazioni di ricorrenza. Ex:
MergeSort:
c1, n 1
f (n)
2 f (n / 2) c2n, n 2
Semplificazioni:
Argomenti non interi.
(1), n 2
f ( n)
Condizioni al
n
piccolo
( n / 2) f ( n /per
2)
(n), n 2
fcontorno:
(1)
29
Soluzione di equazioni di ricorrenza
Metodo per sostituzione. Si tenta una soluzione
g(n) e si verifica se soddisfa l’equazione di
ricorsione.
Dimostrazione per induzione.
Base dell’induzione: f(1)≤g(1)
Ipotesi induttiva: f(n/2) ≤g(n/2)
Passo induttivo: f(n) ≤g(n)
Per Merge Sort:
g (n) cn log n a
30
Soluzione equazioni di ricorrenza
per Merge Sort
Base:
f (1) c1 g (1) a
Ipotesi induttiva:
Passo induttivo:
f ( n / 2) g ( n / 2)
f (n) 2 g (n / 2) c2 n
2c(n / 2) log( n / 2) c2 n 2a
cn log( n / 2) c2 n 2a
cn log n cn c2 n 2a
cn log n a
c1 c2 c
31
Esercizi/1
1.
Mostrare che la soluzione di
f(n)=f(n/2)+f(n/2)+1 è O(n)
2. Mostrare che la soluzione di
f(n)=2f(n/2+10)+n è O(nlog n)
32
f(n)=f(n/2)+f(n/2)+1
Ipotesi: f(n)<=g(n)=cn
f(n/2)+f(n/2)+1<=cn/2 + cn/2 +1 = cn +1 NO!
Ipotesi: f(n)<=g(n)=cn-b
f(n/2)+f(n/2)+1<=cn/2-b + cn/2-b +1
= cn -2b+1 b>=1
33
f(n)=2f(n/2+10)+n
Rinominiamo n+20= m. Quindi:
f(m)=2f(m/2)+m-20
Ipotesi: f(m)<=g(m)=cmlogm
f(m)<=2c (m/2) (log m-1)+m-20<=cm log m
se c>=1
Quindi: f(n)<=g(n)=(n+20)log(n+20)
34
Esercizi/2
Mostrare che la soluzione di
f(n)=f(n/2)+1 è O(log n)
35
Esercizi/3
Si consideri il problema della ricerca in un
vettore di interi: dato il vettore A[1..n] ed
un intero k, si vuole stabilire se k sia tra
gli elementi di A o meno
Considerato il classico algoritmo basato
sulla ricerca binaria, si mostri che esso
ha complessità O(log n)
36
Esercizi/4
Si consideri il problema di “indovinare” un numero
intero nel numero minimo di tentativi: ad ogni
tentativo, l’algoritmo propone un valore ad un
oracolo, che conosce il numero da indovinare.
L’oracolo risponde dicendo se il numero proposto
sia maggiore, minore o uguale a quello da
indovinare (nell’ ultimo caso il gioco termina).
Si proponga un algoritmo efficiente e se ne
esprima la complessità temporale in funzione
del generico numero N da indovinare
37