Sei sulla pagina 1di 70

Algoritmi e complessità

La complessità
Complessità in tempo e spazio
Complessità asintotica
Algoritmi e complessità
Ricerca e ordinamento
La macchina di Turing e le classi di
complessità

Fondamenti di Informatica I  a.a. 2008-09 1


La complessità

Fondamenti di Informatica I  a.a. 2008-09 2


La complessità

L’analisi di complessità definisce le risorse teoricamente


consumate da un algoritmo
complessità temporale:
temporale tempo necessario all’esecuzione
dell’algoritmo
complessità spaziale:
spaziale memoria necessaria all’esecuzione
dell’algoritmo
Poiché ad ogni algoritmo corrispondono più
implementazioni (più programmi), lo studio della
complessità non definisce esattamente il tempo e la
memoria usata: si concentra sulle proprietà che sono
indipendenti dell’implementazione fornendo un’idea di
quanto sia efficiente un algoritmo

Fondamenti di Informatica I  a.a. 2008-09 3


Che cosa si misura?  1
Complessità temporale
Si contano le istruzioni eseguite dall’algoritmo
Poiché le istruzioni potrebbero essere di natura diversa, si
individuano quelle che incidono principalmente sul tempo
di esecuzione
Le operazioni in virgola mobile:
mobile le più lente da eseguire per una
CPU; sono predominanti se il loro numero è paragonabile al numero
delle altre istruzioni
Le istruzioni di controllo (gli if)
if e le istruzioni più frequenti (sono
predominanti se sono in numero molto superiore alle altre
istruzioni)
Le istruzioni di accesso alla memoria secondaria e alle periferiche:
periferiche
sono decine di migliaia di volte più lente delle istruzioni svolte nella
memoria principale;
principale se un’applicazione ne richiede molte, queste
potrebbero essere predominanti (ad es., nei database, l’analisi di
complessità è concentrata sugli accessi al disco)

Fondamenti di Informatica I  a.a. 2008-09 4


Che cosa si misura?  2

Complessità spaziale
Si misurano le “posizioni” di memoria occupate dai dati
necessari allo svolgimento dell’algoritmo
La complessità spaziale sarà misurata relativamente alla
memoria principale se i dati dell’algoritmo possono essere
allocati in memoria principale, in base all’occupazione di
memoria secondaria quando le strutture dati dell’algoritmo
sono troppo grandi per poter risiedere nella memoria
centrale

Fondamenti di Informatica I  a.a. 2008-09 5


Complessità asintotica
Lo studio della complessità si concentra su i casi in cui
il problema è grande:
non importa se un programma di contabilità impiega 1 o
100 millisecondi a calcolare il bilancio
cambia molto se il programma della segreteria impiega 1
o 10 secondi a trovare i dati di uno studente nell’archivio
Complessità asintotica
Definisce le risorse usate da un algoritmo al crescere della
dimensione del problema affrontato
Ad esempio: come cambia il tempo di accesso ai dati
quando cresce il numero degli studenti nell’archivio della
segreteria

Fondamenti di Informatica I  a.a. 2008-09 6


Complessità temporale asintotica  1
Formalmente, si usa il concetto matematico di ordine di
grandezza
sia n la dimensione del problema, cioè la dimensione dell’input
dell’algoritmo
sia T(n) il tempo impiegato per l’esecuzione dell’algoritmo
quando l’ingresso ha dimensione n
sia f(n) una qualsiasi funzione di n, ad esempio 3, n, n2, n5, 2n
Si dice che la complessità asintotica dell’algoritmo è dell’ordine
di f(n) e si scrive O (f(n)) se esiste una costante  tale che
T(n) f(n)
Osservazione importante:
importante in base alla definizione data,
algoritmi che differiscono solo per una costante moltiplicativa
hanno lo stesso ordine di complessità
Esempio:
Esempio due algoritmi che richiedono 4n e 7n operazioni
sono entrambi O (n)
Fondamenti di Informatica I  a.a. 2008-09 7
Complessità temporale asintotica  2

Informalmente…
L’ordine O (f(n)) fornisce una misura della complessità
temporale di ogni programma che implementa l’algoritmo

Esempio:
Esempio Calcolare la somma degli elementi di un array
n: numero di elementi dell’array
complessità: O (n)

Fondamenti di Informatica I  a.a. 2008-09 8


Complessità media e relativa al caso peggiore

Un algoritmo può richiedere un numero di operazioni


diverse per ingressi di dimensione uguale:
complessità media:
media complessità valutata su tutti i possibili
ingressi
complessità nel caso peggiore:
peggiore complessità dell’algoritmo
per l’ingresso che richiede più operazioni

Di solito, quando si parla di complessità, ci si riferisce


alla complessità nel caso peggiore

Fondamenti di Informatica I  a.a. 2008-09 9


Complessità asintotica: array e liste

Array
n: numero degli elementi dell’array
Ricerca/inserimento/cancellazione di un elemento
Complessità O (n)
Liste semplici
n: numero delle posizioni nella lista
Ricerca/cancellazione di un elemento
Complessità O (n)
Inserimento di un elemento all’inizio della lista (in testa)
Complessità O (1)

Fondamenti di Informatica I  a.a. 2008-09 10


Complessità asintotica: alberi binari

Alberi binari di ricerca


n: numero dei nodi dell’albero
Inserire, eliminare o ricercare un elemento in un albero
binario bilanciato
Complessità: O (log2n)
6

3 8

1 4 7 9

Fondamenti di Informatica I  a.a. 2008-09 11


Complessità asintotica: tabelle hash

Problema
Memorizzare in maniera opportuna un insieme di dati 
tipicamente sotto forma di record  in modo da poter
reperire un qualsiasi elemento dell’insieme con un
numero “piccolo” di tentativi
Cosa significa “piccolo” ?
Indipendente (o quasi) dalla dimensione della tabella su cui
si effettua la ricerca, quindi con una complessità in tempo
pari ad O (1)

Fondamenti di Informatica I  a.a. 2008-09 12


Funzioni hash  1

h: K → {0, 1, 2, …, m–1}
K: insieme dei valori distinti che possono essere assunti
dalle chiavi dei record
m: dimensione del vettore in cui si intende memorizzare
la tabella
Ipotesi:
Ipotesi K sottoinsieme dei numeri naturali
 Possibile funzione di accesso:
h(k)  k MOD m, kK
Valore della funzione sempre compreso fra 0 e m–1

Fondamenti di Informatica I  a.a. 2008-09 13


Funzioni hash  2

Se K non è un sottoinsieme dei numeri naturali


Esempio:
Esempio insieme di stringhe alfanumeriche
La funzione hash si applica a numeri
 Per utilizzarla in corrispondenza di una chiave non numerica
occorre associare alla chiave un valore numerico
Necessità di definire funzioni hash generali
Associazione di un valore numerico ad una chiave di
qualunque tipo
Applicazione della funzione hash a tale valore
Esempio:
Esempio si utilizza la somma dei codici ASCII dei caratteri
che costituiscono la stringa
Fondamenti di Informatica I  a.a. 2008-09 14
Collisioni  1

Associazione, da parte di una trasformazione, della


stessa posizione a chiavi distinte
Sinonimi
Esempio:
Esempio [10,12,20,23,27,30,31,39,42,44,45,49,53,57,60]
h(chiave)  (chiave MOD 15)
Posizione 0 ← 30, 45, 60
Posizione 8 ← 23, 53
Posizione 12 ← 12, 27, 42, 57
Ciascuna posizione dell’array può contenere al più un
elemento; occorre…
Ridurre al massimo le collisioni
Gestirle quando si verificano
Fondamenti di Informatica I  a.a. 2008-09 15
Collisioni  2

Funzioni di hashing perfetto (che evitano i duplicati) sono


rare, anche per tabelle grandi
Esempio paradosso del compleanno
Esempio:
Dato un gruppo di 23 persone, ci sono più del 50% di
probabilità che due di esse siano nate nello stesso giorno
dell’anno
 In altre parole, se scegliamo una funzione aleatoria (a valori
casuali) che trasforma 23 chiavi in un indirizzo di una tabella di
365 elementi, la probabilità che due chiavi NON collidano è solo
0.4927 (meno della metà)
Individuare una funzione di accesso che porti ad un numero
ridotto di collisioni è un problema complesso

Fondamenti di Informatica I  a.a. 2008-09 16


Collisioni  3
Tuttavia… numero di collisioni ridotto drasticamente se
accettiamo uno spreco del 25% di memoria extra 0 57

Esempio:
Esempio array di 19 elementi (indicizzati da 0 a 18) 12 20, 39
Posizione 0 ← 57 3 60

Posizione 8 ← 27 4 23, 42
5
Posizione 1 ← 20, 39 6 44
Posizione 10 ← 10 7 45

Posizione 3 ← 60 h(chiave)  (chiave MOD 19) 8 27


9
Posizione 11 ← 30, 49 10 10
Posizione 4 ← 23, 42 11 30, 49

Posizione 12 ← 12, 31 12 12, 31


13
Posizione 6 ← 44 14
Posizione 15 ← 53 15 53

Posizione 7 ← 45 16
17

Collisioni non eliminate del tutto 18

Fondamenti di Informatica I  a.a. 2008-09 17


Gestione delle collisioni  1
Uso di liste concatenate destinate alla memorizzazione
degli elementi che, in inserimento, hanno portato ad
una collisione
Ricerca di un elemento di chiave k
Si calcola h(k)
Se si verifica una collisione allora si accede alla lista
associata alla posizione h(k) e la si scandisce

Fondamenti di Informatica I  a.a. 2008-09 18


Gestione delle collisioni  2

Il costo dell’operazione di ricerca  realizzata in modo


lineare relativamente alle liste di elementi in collisione 
si mantiene pressoché indipendente da n (numero degli
elementi contenuti nella tabella)

Inserimento/cancellazione costano O (1)

Metodo non adatto a reperire sottoinsiemi di dati con


chiave che soddisfi una data relazione

Fondamenti di Informatica I  a.a. 2008-09 19


Complessità asintotica fattoriale

Sia dato un programma che prende in ingresso i


partecipanti ad una competizione e genera (ad esempio
per stamparle) tutte le possibili classifiche finali
n: numero di partecipanti
Complessità: O (n!)

Si osservi che n! è un numero molto grande anche per


n relativamente piccoli
20!  2.432.902.008.176.640.0002.41018

Fondamenti di Informatica I  a.a. 2008-09 20


Complessità asintotica polinomiale
Sia dato un programma che ha come ingresso due
array a, b e cerca tutte le coppie (i,j) tali che a[i]b[j]
n: dimensione di a
m: dimensione di b
Complessità: O (nm)
void search(int a[], int b[], int alength, int blength)
{…
for(i0;ialength;i){
for(j0;jblength;j){
if(a[i]b[j])
printf(“Trovata corrispondenza: a[%d]b[%d]%d”, i, j, a[i]);
}
}
}

Fondamenti di Informatica I  a.a. 2008-09 21


Algoritmi facili e difficili

In base alla loro complessità temporale asintotica, gli


algoritmi sono tipicamente divisi in classi
Algoritmi a complessità costante O (1) o lineare O (n)
Molto veloci, “scalabili”
Algoritmi a complessità polinomiale O (na) per un qualche
valore a
Usabili se l’esponente a è piccolo
 Algoritmi a complessità esponenziale O (an) per un qualche
valore a (1)
Usabili solo per n molto piccoli

Fondamenti di Informatica I  a.a. 2008-09 22


Algoritmi a complessità esponenziale

Fondamentale:
Fondamentale perché gli algoritmi a complessità
esponenziale sono considerati quasi inusabili?
Perché richiedono talmente tante operazioni che
probabilmente anche i calcolatori futuri non saranno in
grado di eseguire in tempi ragionevoli le loro possibili
implementazioni (programmi) per dati in ingresso ad alta
dimensionalità

Fondamenti di Informatica I  a.a. 2008-09 23


Esempio

Si consideri il programma che genera tutte le classifiche


finali di una competizione con n partecipanti,
complessità O (n!) (è esponenziale, perché n! n n )
Con 20 concorrenti le classifiche sono 20! 2.41018
Un computer che generi 1 miliardo di classifiche al secondo,
circa 31016 l’anno, impiegherebbe circa 79 anni per
generare tutte le classifiche richieste
Tendenzialmente, i computer diverranno sempre più veloci e
fra dieci anni forse saranno abbastanza veloci da realizzare in
un mese quello per cui adesso occorrono 79 anni ma…
…comunque, fra dieci anni per risolvere il problema con 21
partecipanti occorreranno ancora 21 mesi e per 25
partecipanti circa 531300 anni!!

Fondamenti di Informatica I  a.a. 2008-09 24


Algoritmi e complessità

Fondamenti di Informatica I  a.a. 2008-09 25


La ricerca dicotomica  1

Per “cercare” un elemento in un vettore ordinato esiste


un metodo detto ricerca binaria o dicotomica
Si confronta il valore val da ricercare con l’elemento
centrale del vettore A[length/2]
Se val è minore dell’elemento mediano, si ripete la ricerca
sulla metà sinistra del vettore, altrimenti si ricerca nella
metà destra

Fondamenti di Informatica I  a.a. 2008-09 26


La ricerca dicotomica  2
Esempio:
Esempio ricerca del numero 23
Si confronta 23 con 13

0 2 4 5 8 9 13 16 20 23 27 30 34 35
Ci si concentra sulla metà destra (da ind. 8 a ind. 14): si confronta 23 con 27

0 2 4 5 8 9 13 16 20 23 27 30 34 35

Ci si concentra sulla metà sinistra (da ind. 8 a ind. 10): si confronta 23 con 20

0 2 4 5 8 9 13 16 20 23 27 30 34 35

Ci si concentra sulla metà destra (da ind. 9 a ind. 9): trovato!!


0 2 4 5 8 9 13 16 20 23 27 30 34 35

Fondamenti di Informatica I  a.a. 2008-09 27


Implementazione della ricerca dicotomica

int search(int val, int A[], int from, int to)


{
int center(fromto)/2;
if (from  to) return 1;
if (fromto) {
if (A[from]val) {return from;}
return 1;} // si esegue solo se A[from]!val
//si esegue solo se (fromto)
if (valA[center]){ return search(val,A,from,center1);}
if (valA[center]){ return search(val,A,center1,to);}
return center;
}

Fondamenti di Informatica I  a.a. 2008-09 28


Complessità della ricerca dicotomica

La ricerca dicotomica divide il vettore in due ad ogni


passo:
n
dopo p passi la dimensione del vettore è p
2
n
nel caso peggiore, la ricerca si ferma quando p è 1, cioè
quando plog2n 2

Quindi la ricerca dicotomica è O (log2n)

Fondamenti di Informatica I  a.a. 2008-09 29


Mergesort  1

Il Mergesort è un algoritmo basato sul paradigma del


divide et impera
Una strategia divide et impera consiste nel suddividere
un problema in sottoproblemi, nel risolvere i
sottoproblemi, e nel ricomporli per ottenere la soluzione
del problema originale

Il Mergesort è composto da due fasi:


una fase di divisione del vettore da ordinare in sottovettori
una fase di ricomposizione dei risultati (merge)

Fondamenti di Informatica I  a.a. 2008-09 30


Mergesort  2
Idea
Dato un vettore da ordinare, lo si divide in due sottovettori di
ugual dimensione, si ordinano i sottovettori e poi si “fondono”
insieme
6 1 2 8 3 4 7 5

Divisione
6 1 2 8 3 4 7 5

Ordinamento Ordinamento

1 2 6 8 3 4 5 7
Fusione

1 2 3 4 5 6 7 8

Fondamenti di Informatica I  a.a. 2008-09 31


Mergesort: la divisione ricorsiva
Come si ordinano i due sottovettori ?
Applicando ricorsivamente la divisione fino a quando il vettore
contiene un solo elemento: in tal caso l’ordinamento è banale
6 1 2 8 3 4 7 5

Divisione
6 1 2 8 3 4 7 5

6 1 2 8 3 4 7 5

6 1 2 8 3 4 7 5

Fondamenti di Informatica I  a.a. 2008-09 32


Mergesort: la fusione ricorsiva  1

I sottovettori ordinati verranno poi ricorsivamente fusi

1 2 3 4 5 6 7 8

Fusione
1 2 6 8 3 4 5 7

1 6 2 8 3 4 5 7

6 1 2 8 3 4 7 5

Fondamenti di Informatica I  a.a. 2008-09 33


Mergesort: la fusione ricorsiva  2
La fusione viene realizzata utilizzando due indici che scorrono i
due sottovettori da fondere:
1. Ad ogni passo si confrontano i due elementi indicati dagli indici i e j,
A[i], A[j]
2. Si copia l’elemento minore in un vettore d’appoggio e si incrementa
l’indice corrispondente
3. Si torna al passo 1. fino a quando i due vettori non sono stati
completamente visitati

1 2 6 8

i 1 2 3 4 5 6 7 8
3 4 5 7
k
j
Fondamenti di Informatica I  a.a. 2008-09 34
Complessità del Mergesort

Il Mergesort ha complessità O (nlog2n) sia nel caso


medio che nel caso pessimo
Mergesort è un algoritmo ottimo!
ottimo
La sua complessità asintotica è la migliore possibile
Comunque…
…esistono algoritmi che per alcuni ingressi fanno meglio di
nlog2n (ad es., Bubblesort su vettori ordinati)
…esistono altri algoritmi con complessità nlog2n nel caso
pessimo  Heapsort

Fondamenti di Informatica I  a.a. 2008-09 35


Quicksort  1

Quicksort come Mergesort, è un algoritmo divide et


Quicksort,
impera
Idea
Si divide il vettore A in due sottovettori, che contengono
rispettivamente tutti gli elementi maggiori e minori di
(per esempio) A[0], cioè il primo elemento del vettore 
detto perno
Si ripete ricorsivamente la divisione…

Fondamenti di Informatica I  a.a. 2008-09 36


Quicksort  2
4 2 1 6 3 8 7 5

Si ripartisce il vettore rispetto ad A[1]  4

3 2 1 4 6 8 7 5

3 2 1 6 8 7 5

Si divide rispetto a 3 Si divide rispetto a 6

1 2 3 5 6 7 8

1 2 5 7 8

Fondamenti di Informatica I  a.a. 2008-09 37


Quicksort: l’operazione perno  1
Si scorrono i, j confrontando con 4
Come si divide il vettore? 4 2 8 6 3 1 7 5
Si usano due indici i, j che
scorrono il vettore da sinistra e j
i
da destra, rispettivamente
Si scambiano gli elementi
L’indice i scorre fino a quando
4 2 8 6 3 1 7 5
A[i]A[1]
L’indice j scorre fino a quando
i j
A[j]A[1]
Si scorrono i, j confrontando con 4
Si effettua lo scambio fra A[i]
4 2 1 6 3 8 7 5
e A[j] e quindi si procede
come sopra
i j
Fondamenti di Informatica I  a.a. 2008-09 38
Quicksort: l’operazione perno  2

Alla fine si scambia il perno con l’elemento in posizione j


Si scambiano gli elementi
4 2 1 6 3 8 7 5

i j
Si scambia A[j] con il perno
4 2 1 3 6 8 7 5

3 2 1 4 6 8 7 5

Fondamenti di Informatica I  a.a. 2008-09 39


Implementazione

void perno(int A[], int from, int to)


{
int ifrom1, jto;
while(ij){
while(A[i]A[from]) i;
while(A[j]A[from]) j;
if(ij) scambia(A,i,j);
}
scambia(A,from,j);
}

Fondamenti di Informatica I  a.a. 2008-09 40


Complessità del Quicksort

Il Quicksort ha complessità media O (nlog n)

Il caso pessimo si verifica quando il perno finisce in


fondo o in testa al vettore
In tal caso, Quicksort ha complessità pari ad O (n2)

Fondamenti di Informatica I  a.a. 2008-09 41


Mergesort vs Quicksort

Mergesort ha il vantaggio di avere complessità sempre


O (nlog n)
Quicksort ha il vantaggio di non richiedere un vettore di
appoggio: ordina il vettore “in loco” (minore
complessità spaziale)

In media, Quicksort si comporta “bene” e, per questo


motivo, in pratica spesso è preferito a Mergesort

Fondamenti di Informatica I  a.a. 2008-09 42


Heap  1
Ospita gli elementi dell’insieme A di cardinalità n, su cui
è definita una relazione d’ordine totale “”
Lo heap (mucchio) è un albero binario
Proprietà 1
L’albero è quasi perfettamente bilanciato
È completo fino al livello k1, cioè contiene il numero massimo di
nodi, 2k1, mentre al livello k contiene un numero di nodi (foglie)
compreso tra 1 e 2k
I nodi a livello massimo sono tutti addossati a sinistra
 Proprietà 2
Ogni nodo contiene un elemento  dell’elemento contenuto
nel padre
Fondamenti di Informatica I  a.a. 2008-09 43
Heap  2

Noto il valore di n, la forma 63


dell’albero è fissata dalla
Proprietà 1
38 23
L’allocazione degli elementi nei
nodi può variare, nel rispetto
12 28
della Proprietà 2 17 22

L’elemento massimo dell’insieme


10 5 18
è allocato nella radice
Nello heap, i sottoalberi di 1 2 3 4 5 6 7 8 9 10

ciascun nodo sono ancora heap 63 38 23 12 28 17 22 10 5 18

Lo heap può essere allocato in


un array
Fondamenti di Informatica I  a.a. 2008-09 44
Heap  3

Con l’allocazione lineare…


A[1] è l’elemento contenuto nella radice dello heap
Per ogni A[i], gli elementi corrispondenti ai figli sinistro e
destro, se esistono, sono memorizzati in A[2i] e A[2i1]
Se 2in e/o 2i1n il figlio sinistro e/o destro di A[i] non
esiste nell’albero
A[2i]A[i] e A[2i1]A[i], quando tali elementi sono definiti

Fondamenti di Informatica I  a.a. 2008-09 45


Heapsort  1

Lo heap trova la sua applicazione più elegante nel


metodo di ordinamento noto come Heapsort
Si estrae l’elemento massimo dallo heap (quello nella
radice, o in prima posizione nella rappresentazione lineare)
Si ricostruisce lo heap
…fino a quando non ci sono più elementi nello heap
(ovvero gli elementi del vettore sono ordinati)

Fondamenti di Informatica I  a.a. 2008-09 46


Heapsort  2
Come si ricostruisce lo heap, dopo l’estrazione della
radice?
63 18

38 23 38 23

12 28 17 22 12 28 17 22

10 5 18 10 5

1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10
63 38 23 12 28 17 22 10 5 18 18 38 23 12 28 17 22 10 5 63

Continua… 47
Fondamenti di Informatica I  a.a. 2008-09
Heapsort  3
Si considera il massimo fra i due figli della radice e, se
max{A[2],A[3]}A[1], si effettua lo scambio
18 38

Si scambia A[1] con A[2]


38 23 18 23

12 28 17 22 12 28 17 22

10 5 10 5

1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10
18 38 23 12 28 17 22 10 5 63 38 18 23 12 28 17 22 10 5 63

Continua… 48
Fondamenti di Informatica I  a.a. 2008-09
Heapsort  4
Si considera il massimo fra i due figli di A[2] e, se
max{A[4],A[5]}A[2], si effettua lo scambio
38 38

Si scambia A[2] con A[5]


18 23 28 23

12 28 17 22 12 18 17 22

10 5 10 5

1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10
38 18 23 12 28 17 22 10 5 63 38 28 23 12 18 17 22 10 5 63

Continua… 49
Fondamenti di Informatica I  a.a. 2008-09
Heapsort  5
Si estrae A[1] che è l’elemento più grande… e si ricomincia
il procedimento di ricostruzione
38 5

28 23 28 23

12 18 17 22 12 18 17 22

10 5 10

1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10
38 28 23 12 18 17 22 10 5 63 5 28 23 12 18 17 22 10 38 63

Fondamenti di Informatica I  a.a. 2008-09 50


Heapsort  6

Poiché ogni estrazione e ricostituzione dello heap


richiede tempo O (log2n'), se n′ è il numero di elementi
attualmente contenuti nello heap…
Heapsort ha complessità O (nlog2n)

L’algoritmo di ordinamento può essere realizzato


facilmente sulla “rappresentazione sequenziale” dello
heap

Fondamenti di Informatica I  a.a. 2008-09 51


Heapsort  7
void heapsort(int a[], int left, int right)
{
int k, temp, sizerightleft1, *paleft1;

/* si costruisce lo heap */
for (ksize2; k1; k)
heap(p, k, size);
/* si scambia l’elemento più grande con quello finale
* e si ricostruisce lo heap
*/
while (size1)
{
temp  p[1];
p[1]  p[size];
p[size]  temp;
heap(p, 1, size);
}
exit(0);
}
Fondamenti di Informatica I  a.a. 2008-09 52
Heapsort  8
/* Costruzione topdown di uno heap */
#define LESS(A,B)((A)(B))

void heap(int a[], int k, int size)


{
int j, temp;
while (2ksize)
{
j  2k;
if (jsize && LESS(a[j],a[j1]))
j;
if (!LESS(a[k],a[j]))
break;
temp  a[k];
a[k]  a[j];
a[j]  temp;
k  j;
}
}
Fondamenti di Informatica I  a.a. 2008-09 53
Ancora sulla complessità

Fondamenti di Informatica I  a.a. 2008-09 54


Problemi e algoritmi
Anche per i problemi si parla di complessità
Tipicamente non si riesce a definire univocamente la
complessità di un problema, perché...
...lo stesso problema può essere risolto con algoritmi
diversi che hanno diversa complessità
…anche se si riesce a stabilire qual è il miglior algoritmo
per la risoluzione di un dato problema, tale stima ha
comunque un valore non assoluto, ma limitato nel tempo,
in quanto non è dato prevedere se in futuro potrà esistere
un metodo risolutivo migliore
Per questi motivi, si parla solo di limite inferiore e
superiore alla complessità di un problema
Fondamenti di Informatica I  a.a. 2008-09 55
Complessità di un problema
In alcuni casi è possibile dimostrare che nessun
algoritmo che risolve un dato problema può/potrà
impiegare meno risorse di un certo limite inferiore
Esempi banali
Nessun algoritmo che genera tutte le classifiche possibili
per n concorrenti può farlo in meno di n! operazioni (il
limite inferiore alla complessità è O (n!))
Nessun algoritmo può effettuare la somma fra vettori
ndimensionali in meno di n operazioni (il limite inferiore
alla complessità è O (n))
Esempio non banale
Nessun algoritmo può ordinare un vettore di n elementi in
meno di nlog2n operazioni, nel caso peggiore

Fondamenti di Informatica I  a.a. 2008-09 56


Algoritmi ottimi
Un algoritmo si dice ottimo,
ottimo quando ha complessità pari
al limite inferiore
Esempi
Mergesort e Heapsort sono ottimi
Si consideri il problema di sommare gli elementi di un vettore:
un algoritmo che scorre tutti gli elementi e li somma uno ad uno
richiede O (n) operazioni: tale algoritmo è ottimo perché la sua
complessità corrisponde con quella minima
Si consideri il problema di inserire un elemento in un albero
binario bilanciato che contiene n elementi:
Abbiamo visto una soluzione algoritmica che impone O (log2n)
operazioni  log2n è un limite superiore per tale problema
Si può dimostrare che tale complessità corrisponde con il limite
inferiore e che l’algoritmo proposto è ottimo
Fondamenti di Informatica I  a.a. 2008-09 57
Algoritmi e computer
Dubbi:
La complessità è indipendente dal computer su cui “gira” il
programma?
Ad esempio, se si inventasse un calcolatore in grado di generare
contemporaneamente tutte le classifiche di n concorrenti, allora
quel problema non avrebbe più complessità n!
Oppure… potrebbe esistere in futuro un computer in grado di
ordinare un vettore di qualsiasi lunghezza per mezzo di una sola
istruzione
Nessuno conosce la risposta ma, fino ad ora, nessuno è
riuscito a progettare un computer con queste capacità
Tutti i calcolatori conosciuti sono equivalenti, in termini
di capacità di calcolo, ad un computer semplicissimo: la
macchina di Turing

Fondamenti di Informatica I  a.a. 2008-09 58


La macchina di Turing

Alan Turing (19121954) è considerato uno dei padri


dell’informatica
Nel 1936 propose l’idea di una macchina immaginaria
che fosse capace di eseguire ogni tipo di calcolo su
numeri e simboli
Esistono varie versioni della macchina di Turing, quella
più simile ai nostri calcolatori è quella cosiddetta a
registri

Fondamenti di Informatica I  a.a. 2008-09 59


La macchina di Turing a registri
È costituita da un insieme di registri di lavoro R 1, R2, R3,… e
di registri di ingresso I1, I2, I3,…
Ogni registro è una cella di memoria che contiene un intero non
negativo
I programmi sono costituiti da tre semplici tipi di istruzioni:
incremento: Ri  IF I1 GOTO ciclo
Il registro i viene incrementato di 1 ciclo: I2
decremento: Ri  I1
Il registro i viene decrementato di 1; se
il registro ha già valore 0, l’istruzione IF I1 GOTO ciclo
non ha effetto fine:
Programma che somma i
salto condizionato: IF Ri GOTO L1
contenuti di I1 e I2 in I2
Se il registro i contiene un valore
maggiore di 0, si va all’istruzione L1 60
Fondamenti di Informatica I  a.a. 2008-09
La tesi di ChurchTuring

La tesi di ChurchTuring afferma che:


Ogni problema intuitivamente calcolabile (risolubile) da
un qualsiasi elaboratore è calcolabile da una macchina
di Turing, purché dotata di memoria (e tempo di
elaborazione) sufficiente

Nessuno è mai riuscito a confutare la tesi di


ChurchTuring

La maggior parte dei ricercatori ritiene che sia vera

Fondamenti di Informatica I  a.a. 2008-09 61


Il problema della terminazione
Supponiamo che esista un programma halt in grado di
risolvere i problema della terminazione
halt(P,I) restituisce:
true se P con ingresso I termina
false se P con ingresso I non termina
Consideriamo il programma Q void Q(Program P){
Cosa succede se si applica Q a Q ? while (halt(P,P)) {}
}
Q(Q) termina o no ?
Se Q(Q) termina allora halt(Q,Q) dovrebbe essere vero… ma
allora Q(Q) non dovrebbe terminare
Se Q(Q) non termina allora halt(Q,Q) dovrebbe essere falso
… ma allora Q(Q) dovrebbe terminare
Quindi il programma halt non esiste!!
Fondamenti di Informatica I  a.a. 2008-09 62
Problemi impossibili

Esistono problemi molto difficili… problemi non


calcolabili con una macchina di Turing e  se la tesi di
ChurchTuring è vera  con nessun calcolatore!!
Esempi
Problema della terminazione
Dato un programma e un suo ingresso, dire se il
programma terminerà (o entrerà in un ciclo indefinito)
Problema di Post
Dato un programma e due stati (uno stato è
definito da un certo valore delle variabili), dire se a partire
dal primo stato si potrà raggiungere il secondo

Fondamenti di Informatica I  a.a. 2008-09 63


La macchina non deterministica  1
R4
Nella macchina non deterministica, i
FORK{ R1,
programmi includono anche altre
istruzioni R1 }
scelta casuale: FORK FORK{ R2,
prende in ingresso un insieme di R2 }
istruzioni e ne esegue una a caso IF R1 GOTO cont
istruzione di accettazione: ACCEPT IF R4 GOTO no
quando viene eseguita, il
cont: IF R2 GOTO ok
programma termina correttamente
IF R4 GOTO no
Un problema è risolubile se esiste
un programma e una scelta casuale ok: ACCEPT
per cui il programma termina con no:
Programma che assegna a
ACCEPT e fornisce la risposta caso valori in {0, 1} a R1 e R2
desiderata e termina solo se R1R21

Fondamenti di Informatica I  a.a. 2008-09 64


La macchina non deterministica  2
La macchina non deterministica “non calcola più di quella
deterministica”
Si può dimostrare che tutto ciò che è calcolabile sulla macchina
di Turing non deterministica è calcolabile anche sulla macchina
deterministica
Si pensa però che la macchina non deterministica sia più
efficiente di quella deterministica
Il non determinismo può essere pensato come una forma di
parallelismo:
FORK è un istruzione che genera più programmi paralleli
Il parallelismo permette di risolvere i problemi velocemente:
ad esempio, si può cercare un elemento in un vettore
guardando contemporaneamente a tutte le posizioni del
vettore
Fondamenti di Informatica I  a.a. 2008-09 65
Problemi P e NP
I problemi decisionali richiedono solo una risposta
binaria (sì/no), correlata in genere all’esistenza di una
soluzione (es., problema della terminazione)
Nella teoria della complessità, i problemi decisionali si
dividono in due classi
P  problemi risolubili in tempo polinomiale sulla
macchina di Turing deterministica
NP  problemi risolubili in tempo polinomiale sulla
macchina di Turing non deterministica
Includono sia i problemi “facili”, sia anche la quasi totalità
dei problemi che si incontrano nelle situazioni pratiche
Ovviamente vale PNP, ma non è noto se P≠NP
Fondamenti di Informatica I  a.a. 2008-09 66
Problemi NPcompleti  1

Problema decisionale della soddisfattibilità: Data una


forma normale congiuntiva F(x1,x2,…,xn) stabilire se
esiste un assegnamento di valori delle variabili
booleane x1, x2,…, xn che soddisfi F
Qualunque problema della classe NP si riduce, in tempo
polinomiale, al problema della soddisfattibilità PS
PS è il “più difficile” fra i problemi di NP

Fondamenti di Informatica I  a.a. 2008-09 67


Problemi NPcompleti  2

Un problema P è detto NPcompleto se PNP e PS si


riduce a P
I problemi NPcompleti sono tutti equivalenti fra loro:
Sarebbe sufficiente trovare un algoritmo polinomiale per
uno solo di essi ed avremmo trovato un algoritmo
polinomiale per risolvere tutti i problemi
Inoltre, tutti i problemi in NP sarebbero risolubili in tempo
polinomiale sulla macchina di Turing deterministica, cioè
avremmo dimostrato che NPP!

Fondamenti di Informatica I  a.a. 2008-09 68


Problemi NPcompleti: esempi
Problema decisionale del commesso viaggiatore
Dato un insieme di n città con le relative distanze,
trovare, se esiste, un cammino di lunghezza k che,
partendo da una città, le visiti tutte tornando in quella
di partenza
Un problema NParduo (non decisionale)
Programmazione lineare intera
Data una matrice A e due vettori b, c, calcolare un
vettore di interi x che soddisfi Axb e minimizzi f(x)cx
Problemi di programmazione lineare
definire l’orario dei treni e degli autobus
definire l’orario delle lezioni

Fondamenti di Informatica I  a.a. 2008-09 69
Conclusioni: PNP e tesi di Church

Attualmente si pensa che NPP


…ma nessuno è ancora riuscito a dimostrarlo
Si pensa anche che la tesi di Church sia vera:
ovviamente questo non si può dimostrare ma è,
eventualmente, solo confutabile
Talvolta, problemi con complessità proibitiva sono utili:
Ad esempio, gli algoritmi crittografici sono basati sul fatto
che “decrittare” una chiave è molto complesso e
richiederebbe un tempo troppo lungo
Se la tesi di Church non fosse vera o se PNP, tali metodi
non sarebbero più efficaci
Fondamenti di Informatica I  a.a. 2008-09 70

Potrebbero piacerti anche