Sei sulla pagina 1di 98

Capitolo 1 Introduzione

Alcuni problemi sono irrisolvibili

Alcuni vengono risolti solo in modo approssimato

Soluzioni ottime: non ce ne sono di pi efficienti

Semplicit, modularit, manuntenibilit, espandibilit, sicurezza, robustezza

Invariante: condizione sempre vera in un certo punto del programma

Di ciclo: allinizio del ciclo (subito dopo il for)

Di classe: alla fine dellesecuzione di un metodo

Dimosterazione correttezza
o

Caso base: vera allinizio

Passo induttivo: se la condizione vera allinizio di uniterazione, lo


anche alla successiva (ad esempio: min conterr il minimo degli
elementi tra 0 e i-1)

Conclusione: alla fine min conterr il minimo tra 0 e n-1

Risorse da poter valutare:


o

Tempo

Spazio (memoria)

Banda (algoritmi distribuiti)

ANALISI DI ALGORITMI
Dimensione dellinput
Criterio di costo logaritmico: la taglia dell'input il numero di bit necessari per
rappresentarlo .Esempio: moltiplicazione di numeri binari lunghi n bit
Criterio di costo uniforme: la taglia dell'input il numero di elementi che lo
costituiscono. Esempio: ricerca minimo in un array di n elementi
In molti casi: possiamo assumere che gli elementi siano rappresentati da un
numero costante di bit. Le due misure coincidono a meno di una costante
moltiplicativa

Modello di calcolo: rappresentazione astratta di un


calcolatore
Astrazione: deve semplificare i dettagli, altrimenti inutile
Realismo: deve riflettere la situazione reale
Potenza: deve permettere di trarre conclusioni formali sul costo

Binary search

Funziona solo su vettori ordinati .


O(log n)

Complessit:

Karatsuba

Serve per moltiplicare due binari con divide et impera


Complessit: O(n1.58)

Selection sort

Ordina un vettore mettendo il minimo allinizio ogni volta


O(n2)

Complessit:

Merge sort

Ordinare un vettore con divide et impera


O(nlog(n))

Complessit:

Analisi ammortizzata
Ci sono tre metodi per fare lanalisi ammortizzata:
Metodo dellaggregazione:

Si calcola la complessit O(f(n)) per eseguire operazioni in sequenza nel


caso pessimo

Il costo ammortizzato di una singola operazione O(f(n)/n)

Metodo degli accantonamenti (consigliato):

Alle operazioni vengono assegnati costi ammortizzati che possono essere


maggiori /minori del loro costo effettivo

Provare che la somma dei costi ammortizzati un limite superiore al costo


effettivo

Metodo del potenziale (ignorato)

Counting sort

Basato non sui confronti, dipende dal range (k) dei numeri
Complessit: O(n+k)

Capitolo 3 Strutture

Specifica, implementazione

Tipi:

Lineari (presenza di una sequenza) / non lineari

Statiche / dinamiche

Omogenee / disomogenee

Sequenze
o

Dinamica e lineare

Conta lordine

Ammette duplicati

Accesso diretto a primo/ultimo

Accesso sequenziale a tutti gli altri elementi

A pagina 4 degli appunti guella, linterfaccia incompleta. La versione


completa a pagina 5 (con implementazione)

Dati chiave (unici)

Dati satellite

Set

Dizionari

Implementazioni
o

Dizionario: hashtable, albero

Albero: albero con puntatori, vettore dei padri

Sequenza: linked lista, array

STRUTTURE ELEMENTARI
Lista circolare, bidirezionale, con sentinella

possibile realizzare le liste con i vettori, bisogna gestire per il problema della
dimensione dinamica, meglio gestirla come fa java nellarray list, incrementa ogni
volta del doppio e dimezza quando loccupazione pari ad un quarto.

Stack

Funziona come i piatti in pizzeria, LIFO

Queue

FIFO

Capitolo 5 Alberi

Profondit/livello: distanza dalla radice (0 per la radice)

Livello: nodi della stessa profondit

Altezza: massima profondit

Visita
o

In profondit, a seconda di quando si processa il nodo rispetto ai figli:


Pre-order
In-order (a.k.a. invisita, simmetrico)
Post-order

In ampiezza (con la coda dei nodi da visitare)

Implementazioni
o

Vettore dei figli (*parent, node *childNodes[])


Spreca spazio per i nodi con pochi figli

Linked list dei figli (*parent, *firstChild, *nextSibling)

Vettore dei padri


struct {int parentIndex, Item value}[SIZE];

Alberi binary
Tree right(), Tree left()

Ordinamento basato sui confronti:


o

Sequenza di confronti rappresentabile come albero binario

Foglie: soluzioni del problema, nodi interni: confronti

Numero di possibili solizioni: n!

Altezza minima dellalbero: log n! n/2 log n/2

Per cui ogni algoritmo di ordinamento (basato sui confronti) (n logn)

ALBERI BINARI DI RICERCA


Alberi binari in cui il figlio sinistro pi piccolo del padre, il figlio destro pi grande
del padre

Alberi binari di ricerca

Ricerca: implementazione

Cerca un valore nellalbero


O(logn)

Complessit:

Ricerca del minimo e del massimo

Complessit:
O(logn)

Successore-predecessore

Successore: di un nodo il pi piccolo nodo maggiore di quel nodo

Inserimento

Nel caso pessimo dobbiamo scorrere tutto laltezza dellalbero


Complessit: O(logn)

Cancellazione

Bisogna se in caso modificare lalbero perch rimanga un ABR

Bilanciamento degli alberi


Spesso le operazioni (ricerca, cancellazione ecc) sugli ABR dipendono dallaltezza
dellalbero. Conviene quindi cercare di tenere lalbero il pi possibile bilanciato: che
non vi sia troppa disequit di profondit fra sottoalbero destro e sottoalbero sinistro.
Per fare questo dobbiamo fare ogni tanto delle rotazioni.

Alberi Red-Black Treee


Sono implementati per prevedere la bilanciatura dellalbero. Ogni nodo pu essere
rosso o nero, le foglie non contengono valori, sono nodi nil ( in trealt ne esiste solo
uno, tutti puntano a quello, per risparmiare memoria). La radice nera, tutte le
foglie sono nere, i figli di un nodo rosso sono ambedue neri.
In pratica root e foglie sono neri, non posso avere due rossi consecutivi. Il path di
ogni foglia contiene lo stesso numero di nodi neri.
Altezza nera: il numero di nodi neri lungo ogni percorso da un nodo v (escluso) ad
una foglia (inclusa). Si indica con b(v)
Altezza nera di un albero: laltezza nera della radice

RB-Tree rotazione a sinistra

RB-Tree inserimento nodo

Come negli ABR, poi si sistema il tutto


O(log n)

Complessit:

RB-Tree cancellazione

Funziona come negli ABR, solo che poi dobbiamo decidere se aggiustare o no, si
deve aggiustare solo quando il nodo cancellato nero:
Se il nodo cancellato rosso:

laltezza nera rimane invariata

non sono stati creati nodi rossi consecutivi

la radice resta nera

Se il nodo cancellato nero:

la radice pu essere un nodo rosso

se il padre e uno dei figli del nodo erano rossi ci troviamo con due rossi di fila

cambia laltezza nera

Complessit: visitiamo O(log n) nodi ognuno in tempo O(1), quindi O(log n)

Capitolo 7 Hashing

Dizionario: insieme dinamico con coppie chiave, valore (chiave unica)

Se il numero di possibili chiavi molto maggiore di quelle che verranno


effettivamente memorizzate, occorre unhashtable, altrimenti si pu usare
lindirizzamento diretto

H(k) una funzione che tritura la chiave k (sempre allo stesso modo per) e
restituisce un valore dal range molto pi limitato di k. Ci possono essere
quindi delle collisioni.

Tutti i valori con lo stesso hash sono memorizzati nello stesso slot di un array

Occorre minimizzare il numero di collisioni, e sapere gestire quelle che si


verificano

Sarebbe necessario conoscere la distribuzione di probabilit di k, ma nella


realt non si usa questo metodo.

Funzioni di hash
o

Estrazione: si estraggono degli specifici bit dal valore

XOR: si xorano varie estrazioni di specifici bit

Divisione: k mod m, dove m dispari, meglio se primo

Moltiplicazione: H(k) = floor(m * (kC floor(kC))), dove C una


costante tra 0 e 1, e m un numero qualunque (potenze di 2 consigliate)
(questo metodo non poi cos buono)

Avalanche effect: un singolo bit della chiave modificato deve cambiare


almeno met dellhash

Collisioni

Liste di trabocco: linked list sugli slot con pi di un elemento.


Inserimento in testa, lookup e delete richiedono la scansione della lista:
(1+lunghezzaMediaLista/2)

Indirizzamento aperto: se uno slot gi occupato, se ne cerca uno


alternativo
Non si vuole esaminare (ispezionare) uno slot pi di una volta
Ispezione lineare: H(k, i) = (H(k) + h*i) mod m

Problema: primary clustering

Nascono lunghe sottosequenze occupate che tendono a


diventare sempre pi lunghe

Ispezione quadratica: H(k, i) = (H(k) + h*i 2) mod m

Problema: la sequenza risultante non una permutazione

Problema: secondary clustering: due chiavi con stessa


ispezione iniziale hanno sequenze identiche

Ispezione pseudocasuale: H(k, i) = (H(k) + r i) mod m

ri li-esimo elemento restituito da un generatore di num


casuali da 0 a m-1

Risulta una permutazione, ma rimane il secondary


clustering

Doppio hashing: H(k, i) = (H(k) + i*H(k)) mod m

H(k) deve essere relativamente primo con m


o

m = 2p, H(k) deve restituire numeri dispari

m primo, H(k) deve restituire numeri minori di m

Cancellazione: non si pu mettere null, altrimenti le scansioni


successive si fermerebbero. Occorre uno speciale valore deleted

Complessit
o

n chiavi, m slot

n<m, ovvero fattore di carico < 1

I(): numero atteso di ispezioni in caso di insuccesso

S(): numero atteso di ispezioni in caso di successo

Quando cresce troppo, si raddoppia la dimensione della tabella


(tipicamente 0.5)

Costo ammortizzato costante

Problemi hashtable:
o

Scarsa locality reference (cache miss)

Non possibile ottenere le chiavi in ordine

INSIEMI E DIZIONARI
Riepilogo complessit

Insieme: collezione di oggetti


Dizionario: insieme di associazioni chiave-valore

Insiemi realizzati con vettori booleani

Vantaggi: notevolmente semplice, efficiente verificare se un elemento appartiene


allinsieme
Svantaggi: occupazione di memoria
dellinsieme, operazioni inefficienti O(N)

O(N),

indipendente

dalla

dimensione

Insiemi realizzati con liste non ordinate


Vantaggi:
occupazione
di
memoria
proporzionale alla dimensione del vettore
Svantaggi: operazioni di ricerca, inserimento e
cancellazione O(n); unione, intersezione e
differenza O(nm)

Insiemi realizzati con liste ordinate


Vantaggi:
occupazione
di
memoria
proporzionale alla dimensione del vettore,
operazioni di unione, intersezione e differenza
O(n)
Svantaggi: operazione di ricerca, inserimento
e cancellazione: O(n)

Insiemi realizzati con strutture dati complesse


Con alberi di ricerca bilanciati:

Ricerca, inserimento, cancellazione: O(logn)

Viene mantenuto lordinamento

Elencare tutti gli elementi: O(n)

Con tabelle hash:

Ricerca, inserimento, cancellazione: O(1)

Viene perso lordinamento

Elencare tutti gli elementi: O(m) dove m la dimensione della tabella hash

Capitolo 9 Grafi

Visite
o

Ampiezza (numero di Erdos)

Profondit (ordinamento topologico, component (fortemente)


connesse)

Cammini minimi
o

Da singola sorgente

Fra tutte le coppie

Tipi
o

Orientato / non orientato (con le freccie singole o bidirezionale)

(u, v) incidente da u a v (u --> v)

v adiacente a u se u --> v (ci si pu arrivare direttamente da)

Definizioni
o

n = |V|, m=|E|

Grado (quanti archi), grado entrante (quanti entrano), grado uscente


(quanti escono)

Cammino (orientato), Catena (non orientato). Semplice se non ci sono


nodi doppi

Ciclo (orientato), Circuito (non orientato). Semplice se non ci sono nodi


doppi

Aciclico, Orientato aciclico == DAG

Completo: ciascuno direttamente collegato a ciascunaltro

Albero libero==orientato, connesso, aciclico

Albero radicato: se qualche vertice detto radice

Albero di copertura

Erdos: Erdos ha Erdos 0, chi ha scritto un articolo con lui 1, chi ha


scritto un articolo con uno di erdos 1 2 e cos via

Vertici aperti: vertici i cui archi uscenti non sono ancora stati percorsi

Vertici chiusi: vertici di cui archi uscenti sono stati tutti percorsi

Componenti connesse: si sa

Componenti fortemente connesse: per i grafi orientati, significa che si


pu andare avanti e indietro

Un sottografo un sottoinsieme dei vertici e un sottoinsieme dei lati

Un sottografo massimale se non si pu allargare mantenendolo


connesso

Implementazioni
o

Matrice di adiacenza (cosa collegato a cosa)


Spazio: O(n2)
Verifica adiacenza: O(1)
Elenco di tutti gli archi: O(n2)

Liste di adiacenza
Spazio: O(n+m)
Verifica adiacenza: O(n)
Elenco di tutti gli archi: O(n+m)

Depth First Search


o

Quando si scopre un nuovo nodo che prima non era marcato, questo
viene marcato e inserito nellalbero ricoprente (T)

Gli archi restanti possono essere:


Allindietro: puntano ad un antenato (o padre)
In avanti: puntano ad un discendente (o figlio)
Di attraversamento, negli altri casi

Un grafo ciclico?
o

I DAG non hanno archi allindietro, per cui quando se ne trova uno si
restituisce false.

Ordinamento topologico: In che ordine fare le cose per eseguire tutti i task, ad
esempio con make (richiede un DAG)
o

Soluzione diretta: trovare un nodo senza archi incidenti, stamparlo e


rimuovere. Ripetere per tutti gli altri

Basata su DFS

Strongly Connected Components (scc)


o

Algoritmo di Kosaraju, 1978 (calcola il grafo trasposto)

HEAP MFSET
Code con priorit
Le operazioni base viste fin ora (cancellazione, inserimento ecc) possono non
bastare, certe volte dobbiamo inventarne di nuove. Le code di priorit sono una
struttura dati fatta apposta per essere efficiente a fare determinate operazioni. Gli
oggetti sono estratti dalla cosa in base alla loro priorit.

Albero binario perfetto


Tutte le foglie hanno la stessa altezza, tutti, tranne le foglie hanno due figli. Altezza
quindi log n.

Albero binario completo


Tutte le foglie hanno profondit H o H-1. Tutti i nodi a livello H sono accatastati a
sinistra. Tutti i nodi interni hanno grado due, eccetto al pi uno.

Heap
un particolare tipo di coda di priorit nella quale i dati sono mantenuti in modo
parzialmente ordinato.
Max heap: albero binario completo in cui la radice sempre il maggiore. (anche
nei sottoalberi, il padre sempre il maggiore)
Min heap: albero binario completo in cui la radice sempre minore (anche nei
sottoalberi)
Gli heap non impongono nessun ordinamento fra i figli di un nodo (ordinamento
parziale), limportante che i padre sia maggiore o minore rispettivamente per il
max e per il min heap.

Ogni nodo maggiore o uguale di se stesso

Se n >=m e m>=n allora n=m

Se n>=m e m>=r allora n>=r

Lordinamento parziale utile per modellare gerarchie complesse o per mantenere


informazioni parziali. pi semplice costruire uno heap ordinato parzialmente che
qualcosa ordinato totalmente.

Array heap

A[1] contiene la radice

p(i) = [i/2] (limite inferiore). Padre

l(i) = 2i. Figlio sinistro

r(i) = 2i+1. Figlio destro

Procedure per gestire uno heap


Max heap restore

Serve per mantenere la propriet dei max heap dopo un inserimento Complessit:
O(logn)
Ogni sottoalbero deve essere un max heap, quindi si cerca di fare scendere fino al
posto giusto il valore
Heap build

Serve per costruire un max heap da zero (dato un vettore)


Complessit: O(nlogn)
Heapsort

Ordina sul posto un array

Complessit: O(nlogn)

Coda con priorit


Una struttura dati che serve a mantenere un insieme S di elementi x, ciascuno con
un valore associato di priorit

Riduzione priorit

MFSET
Servono a rappresentare degli insiemi disgiunti, le operazioni fondamentali sono
unire pi insiemi, identificare linsieme a cui appartiene un oggetto. una collezione
di insiemi dinamici disgiunti (un insieme di insiemi). Ogni insieme rappresentato
da un rappresentante univoco. Le ricerche del rappresentate sullo stesso insieme
devono restituire sempre lo stesso oggetto. Solo dopo un unione questo oggetto pu
cambiare. Si pu scegliere lelemento pi piccolo/grande di un insieme

Applicazione: trovare le componenti connesse di un


grafo

Alla fine avremo linsieme delle comonenti connesse.


O(n+m)

Complessit:

Implementazione basata su liste

realizzazione basata su liste:

realizzazione basata su alberi: find O(n)

find O(1)

merge O(n)

merge O(1)

conviene anche inserire leuristica del peso (se liste) / rango (se alberi) e la
compressione dei percorsi. Euristica sul peso: ho due liste, per unirle devo scegliere
uno dei due rappresentanti ed applicarlo allaltra lista, logicamente attacco la pi
corta alla pi lunga, quindi mi salvo anche la dimensione.
Nel caso delle liste: ogni elemento contiene un puntatore al successivo, un
puntatore al rappresentante ed un oggetto

Pu essere visto come un albero di altezza 1


Loperazione find richiede O(1), si restituisce il rappresentante di X
Il merge(x,y) richiede pi tempo, si appende la lista che contiene Y alla lista che
contiene X, e poi vengono modificati tutti i puntatori, caso pessimo per n operazioni
O(n2), costo ammortizzato: O(n).

Implementazione basata su alberi


Ogni nodo ha un oggetto ed il puntatore al padre, la radice punta a se stessa ed il
rappresentante
Find O(n) nel caso pessimo, bisogna risalire fino a trovare la radice
Merge(x,y) O(1) si appendono gli alberi
Qui conviene applicare la compressione dei cammini:

Quando si cerca qualcosa portiamo tutto in su. Cos le successive ricerche


costeranno O(1):

Capitolo 11 Cammini minimi grafi

Tipi di problemi (non centra col resto del capitolo)


o

Decisionali: bool IsItTrueThatInputHasASpecificProperty()

Ricerca: IEnumerable<Solution> GetPossibleSolutions()

Ottimizzazione: Solution GetBestSolution()

Approssimazione: Solution GetGoodEnoughSolution()

La definizione matematica di un problema pu suggerirci un metodo di


risoluzione

Teorema di Bellman:
o

Con i cammini minimi, ogni arco (u, v) dellalbero ricoprente deve


avere:
Distanza da v = Distanza da u + peso dellarco u,v

Per ogni arco del grafo (intero stavolta, non solo dellalbero ricoprente)
La distanza calcolata da noi deve essere minore o uguale a
quella che si otterrebbe usando larco (u, v)

Algoritmo di Dijkstra (1959)


o

Coda di priorit mediante vettore / lista non ordinati

O(n2)

Pesi positivi

Algoritmo di Johnson (1977)


o

Coda di priorit mediante heap binario

O(m log n)

Pesi positivi

Algoritmo di Fredman-Tarjan (1987)


o

Coda di priorit mediante heap di fibonacci

O(m + n log n)

Pesi positivi

Algoritmo di Bellman-Ford-Moore (1958)


o

Coda

O(mn)

Funziona anche con pesi negativi

Al contrario degli algoritmi precedenti, dove ogni nodo veniva estratto


esattamente una volta, qui viene estratto al massimo n-1 volte

Algoritmo di Pape DEsopo (1974)


o

DeQueue

Generalmente, superpolinomiale

In pratica, veloci per grafi di reti stradali

DIVIDE ET IMPERA
Divide: dividi il problema in sotto problemi pi piccoli ed indipendenti
Impera: risolvi i sotto problemi ricorsivamente
Combina: unisci le soluzioni dei sottoproblemi

Ordina un vettore sul posto, divide comlicato, nessun combina


O(nlogn)

Parentesizzare (decidere
matrice fare prima)
Strassen

O(n2.81)

quale

Complessit:

motiplicazione

di

Winograd

O(n2,38)

Capitolo 13 Programmazione dinamica

Divide-et-impera
o

Ricorsiva

Top-down

Vantaggioso quando i sottoproblemi sono indipendenti

Programmazione dinamica
o

Iterativa

Bottom-up

Semplice spiegazione della differenza tra programmazione dinamica


(iterativa), e memoization:
o

Memoization: si chiama ricorsivamente, alla fine della funzione ci si


salva il risultato in un array (cache), e allinizio si controlla se il risultato
gi stato calcolato. In tal caso, lo si restituisce subito.

Se larray di cache ha dimensione N, significa che ci sono N possibili


input per la funzione, quindi il corpo pesante della funzione verr
eseguito al massimo N volte.

Se ci si rende conto che tutti gli N slot della cache verranno riempiti,
tanto vale calcolarli tutti, iterativamente, partendo dal caso base e
arrivando a quello che ci interessa. A questo punto si pu togliere le
chiamate ricorsive e sostituirle con un fiducioso
cache[argomentoConCuiAvreiChiamatoLaFunzioneRicorsivamente],
visto che lo avremo sicuramente gi calcolato (a questo punto si
sceglie un nuovo nome per la variabile cache)

Attenzione per: usando la versione iterativa si rischia di calcolare


elementi che poi non ci serviranno, quindi tanto vale usarela ricorsione
con memoization, che anche molto pi naturale ed espressiva

Se il numero di possibili chiavi troppo alto, si usa unhashtable

Sottostruttura ottima
o

una definizione ricorsiva della soluzione ottima, cio le soluzioni dei


sottoproblemi

In che sequenza conviene moltiplicare delle matrici?

Lordine non pu essere cambiato, ma i raggruppamenti s.

Scegliamo dove spezzare la lista di matrici per effettuare il


raggruppamento, e proseguiamo ricorsivamente sulle sottoparti

Teorema di parentetizzazione ottima: ogni soluzione ottima contiene al


tuo interno le parentizzazioni ottime dei sottoproblemi

O(n3)

Zaino [...]

Longest Common Subsequence


o

Subsequence: cio che si ottiene rimuovendo un certo numero di


elementi (anche sparsi) da una sequenza

Common subsequence: una subsequence ottenibile da due sequenze


diverse

Longest Common Subsequence: la pi lunga di queste

Che mal di testa

LCS viene usato nel diff per confrontare file, vedendo quali righe sono
state aggiunte e quali tolte (le modifiche vengono viste come
aggiunta+cancellazione)

String matching approssimato


o

Unoccorrenza K-approssimata unistanza di una certa sottostringa


allinterno di una stringa, che per ammette fino a k differenze
(sostituzione, aggiunta, cancellazione)

Distanza di Levenshtein
Numero di add/del/edit per trasformare una stringa in un altra

Insieme indipendente di intervalli pesati


o

TODO TODO

Capitolo 14 Greedy

Cerchiamo una possibile scelta ingorda

Dimostriamo che la scelta ingorda porta alla soluzione ottima

Scriviamo un algoritmo ricorsivo o iterativo che effettua sempre la scelta


ingorda

*sottostruttura ottima: qualcuno me la rispieghi

Teorema Greedy choice


Sia S[i,j] un sottoproblema non vuoto, e m l'attivit di S[i,j] con il minor tempo di fine;
allora:

m compresa in qualche soluzione ottima di S[i,j]

Il sottoproblema S[i,m] vuoto

Conseguenze:

Non pi necessario analizzare tutti i possibili valori di k


o

Faccio una scelta ingorda, ma sicura: seleziono l'attivit m con il minor


tempo di fine

Non pi necessario analizzare due sottoproblemi:


o

Elimino tutte le attivit che non sono compatibili con la scelta ingorda

Mi resta solo un sottoproblema da risolvere: S[m,j]

Insiemi indipendenti versione iterativa (greedy)

Complessit: O(n) se ordinata, O(nlogn) se disordinata

Per un buon greedy:


Trasformare il problema di ottimizzazione in un problema di scelte successive

Dimostrare che tale scelta rispetta il principio della scelta ingorda

Dimostrare che la soluzione ottima del problema residuo dopo la scelta


ingorda pu essere unito a tale scelta

Tipici problemi greedy (soluzione sulle slide a parole, poso pseudocodice)


Problema del resto

Algoritmo di scheduling Shortest Job First (algoritmo di Moore)

Zaino:

Complessit: O(nlogn) per lordinamento, O(n) per la scelta dei valori

Problema della compressione:


Problema della compressione (codici di Huffman, nessun codice prefisso di altro
codice):

Teorema: L'output dell'algoritmo Huffman per un dato file un codice a prefisso


ottimo
Schema della dimostrazione:

Sottostruttura ottima
o

Dato un problema sull'alfabeto , possibile costruire un sottoproblema


con un alfabeto pi piccolo

Propriet della scelta greedy


o

Scegliere i due elementi con la frequenza pi bassa conduce sempre ad


una soluzione ottimale

Sia
un alfabeto, f un array di frequenze
x, y i due caratteri che hanno frequenza pi bassa
Allora
Esiste un codice prefisso ottimo per in cui x,y hanno la stessa profondit
massima e i loro codici differiscono solo per l'ultimo bit
Dimostrazione
Al solito, basata sulla trasformazione di una soluzione ottima
Supponiamo che esistano due caratteri a,b con profondit massima e questi
siano diversi da x,y
Scelta greedy:
Assumiamo (senza perdere in generalit): f[x] f[y] f[a] f[b]

Poich le frequenze di x e y sono minime: f[x] f[a] f[y] f[b]

Scambiamo x con a: otteniamo T'

Scambiamo y con b: otteniamo T"

Dimostriamo che:

C(f,T '') C(f, T ') C(f,T)

Ma poich T ottimo, sappiamo anche che:

C(f,T) C(f,T '')

Quindi T'' anch'esso ottimo

*Sottostruttura ottima: qualcuno me la rispieghi

Albero di copertura di peso minimo


Due algoritmi greedy: Kruskal e Prim

Per caratterizzare gli archi sicuri dobbiamo introdurre alcune definizioni:


Un taglio (S,V-S) di un grafo non orientato G=(V,E) una partizione di V in due
sottoinsiemi disgiunti
Un arco [u,v] attraversa il taglio se u S e v V-S
Un taglio rispetta un insieme di archi A se nessun arco di A attraversa il taglio
Un arco che attraversa un taglio leggero nel taglio se il suo peso minimo fra
i pesi degli archi che attraversano un taglio

La regola per riconoscere gli archi sicuri data dal seguente teorema:
Sia G=(V,E) un grafo non orientato e connesso
Sia w una funzione peso a valori reali definita su E
Sia A E contenuto in un qualche albero di copertura minimo per G
Sia (S,V-S) un qualunque taglio che rispetta A
Sia [u,v] un arco leggero che attraversa il taglio.
Allora
larco [u,v] sicuro per A
Corollario:
Sia G=(V,E) un grafo non orientato e connesso
Sia w una funzione peso a valori reali definita su E
Sia A E contenuto in un qualche albero di copertura minimo per G
Sia C una componente connessa (un albero) nella foresta GA=(V,A)
Sia [u,v] un arco leggero che connette C a qualche altra componente in GA
Allora
larco [u,v] sicuro per A

Capitolo 15 Ricerca locale

ShellSort
Inversioni di una sequenza: numero di coppie nellordine sbagliato

Ordinamento: la permutazione che minimizza il numero di inversion

Vantaggi della InsertionSort (pochi passi quando quasi ordinata)

Elimina gli svantaggi della InsertionSort (quello di spostare solo elementi


adiacenti tra loro)

Invece di considerare elementi a distanza 1, li considera prima a distanza


1093, poi 364, 121, 40, 13, 4 e 1 (esempio)

Quando h = 1, in pratica una insertion sort, questo garantisce la correttezza

Per n non troppo grandi, migliore di altri algoritmi asintoticamente migliori

Ordinamento sul posto

La complessit piena di casi particolari

Problemi di flusso

Rete di flusso: (V,E,s,p,c)


o

Grafo orientato G=(V,E)

Vertice sorgente (s) e pozzo (p)

Funzione di capacit c: VxV N

Flusso: funzione VxV Z


o

f(u, v) = -f(v, u)

f(u, v) c(u, v)

Sommatoria di tutti i flussi uscenti da un certo nodo = 0 (tranne per


sorgente e pozzo)
Questo per via dei flussi allincontrario

Valore di flusso:
o

Sommatoria di tutti i flussi tra tutti i nodi (in pratica, quanto passa visto
che gli opposti si annullano)

Si vuole trovare il massimo f possibile

Capacit residua di un flusso: funzione che ci dice per ogni coppia di nodi,
quanto avanzerebbe per quellarco

Rete residua: (V, Er, s, p, r) come loriginale, solo che la capacit sostituita
dalla capacit residua e gli archi sono tutte le coppie per cui rimane una
capacit residua

Flusso nullo: flusso che restituisce 0 per ogni u, v

Cammino aumentante per f: cammino da sorgente a pozzo in R

Capacit del cammino: la pi piccola tra quelle degli archi del cammino

Flusso aumentante: (??)

Metodo delle reti residue


o

Il flusso corrente viene inizializzato a flusso nullo

Si ripetono i seguenti passaggi finch g f0


Calcola la rete residua, sostituendo la capacit originale con
quella residua
Si cerca un flusso aumentante g per R
f += g

Taglio: suddivisione in due dei nodi in modo che sorgente e pozzo rimangano
separati

Capacit del taglio: la somma, per ogni coppia di nodi tra parte 1 e parte 2,
delle capacit

Taglio minimo: taglio con capacit minima

Il flusso che attraversa un taglio la somma, per ogni coppia di nodi tra parte
1 e parte 2, dei flussi

Il valore di un flusso che attraversa un qualsiasi taglio uguale a quello degli


altri

Teorema flusso massimo / taglio minimo: dimostrazioni equivalenti:

f un flusso massimo

Non esistono cammini aumentanti per f

Esiste un taglio (S,P) tale che|f| = c(S, P)

Varianti
o

Ford-Fulkerson (qualunque algoritmo di visita) O(|f*| (m+n) )

Edmonds-Karp (visite in ampiezza) O(nm2)

Algoritmo dei tre indiani O(n3)

Capitolo 16 Backtrack

Tipi di problem
o

IEnumerable<Solution> GetPossibleSolutions()

Solution GetFirstSolution()

int CountPossibleSolutions()

Algoritmo di Grahm (Inviluppo convesso disegnare un poligono convesso


attorno a dei punti, pi piccolo possibile) O(n log n)
o

Il punto con ordinata minima fa parte dellinviluppo convesso

Fai qualcosa e disfalo se non corretto

Pruning: lasciar perdere le soluzioni parziali che non porteranno a niente

(N regine, solite cose del filz)

Per le regine, la tecnica migliore invece una minimum-conflicts heuristic: si


muove il pezzo con il maggior numero di conflitti nella casella della stessa
colonna con minor numero di conflitti. Non per garantita la terminazione
sempre corretta

Giro di cavallo: andare ni giro col cavallo su una scacchiera fino a ricoprire
tutte le celle esattamente una volta
o

S[][] contiene il numero di passo in cui entro in una cella (0=non


ancora)

Sudoku, Giri di cavallo: appunti guella

Capitolo 17 algoritmi probabilistici


Il calcolo delle probabilit applicato non ai dati di input, ma ai dati di output
Due possibilit:
Algoritmi corretti, il cui tempo di funzionamento probabilistico
Algoritmo la cui correttezza probabilistica

Espressione polinomiale nulla


Data unespressione polinomiale in n variabile, dire se nulla o no. Non ci sono
monomi. Gli algoritmi basati su semplificazioni sono molto complessi.

Si genera una n-pla di valori v1, ..., vn


Si calcola x= p(v1 , ... , vn)
o Se x 0, p non identicamente nullo
o Se x = 0, p potrebbe essere identicamente nullo
Se vi = random(1, 2d), dove d il grado massimo del polinomio, allora la
probabilit di errore non supera 1/2.
Si ripete k volte, riducendo la probabilit di errore a (1/2) k

Statistica
Algoritmi statistici sui vettori: estraggono da un vettore numerico alcune
caratteristiche statistiche rilevanti (media, varianza, moda, mediano).
Selezione: dato un array di valori distinti ed un valore K compreso nel range del
vettore, trovare lelemento che maggiore di esattamente k-1 elementi.
Ricerca del minimo, massimo:
T(n) = n-1 = (n) confronti
Possiamo dimostrare che questo algoritmo ottimale? Idea:
scelta del minimo come un torneo
Tutti gli elementi (tranne il vincitore) deve perdere almeno un partita
Quindi il problema (n)
Trovare il secondo minimo dellarray

L'albero del torneo permette di trovare il secondo minimo in O(n + log n) confronti nel
caso pessimo:
n passi necessari per la ricerca del minimo
Siano M e S il minimo e il secondo minimo
Sicuramente c' stato un incontro fra M e S, dove M ha vinto
Se cos non fosse, esisterebbe un valore X<S che ha battuto S assurdo dalla
definizione di S
Quindi, basta cercare nei log n valori battuti direttamente da M per trovare il
secondo minimo. Totale: O(n + log n)
Lalbero del torneo pu essere simulato da uno heap:

Non va bene se k>= n/2. Questo va meglio:

*Seguono cenni a cose complicate.

Capitolo 18 Teoria dellNP-Completezza

Dominio limitato, quello delle tessere. Non c un algoritmo migliore della forza
bruta (si pensa che nemmeno ci sia)

Colorazione (carta geografica)

Commesso viaggiatore

Programmazione lineare 0/1: data una matrice A di elementi interi di


dimensione mxn ed un vettore b di m elementi, esiste un vettore x di n elementi
0/1 tale che Axb?

Soddisfabilit: quello dellequazione booleana e dire se si pi rendere vera

Sono tutti problemi tanto PRO.

Certificato polinomiale
Un algoritmo che data una presunta soluzione del problema verifica in tempo
polinomiale che tale soluzione sia effettivamente una soluzione che da risposta SI.

Algoritmo non deterministico


Algoritmo che, posto di fronte alla necessit di prendere una decisione, ha la virtu`
magica di scegliere sempre la strada giusta!
In termini equivalenti, come se lalgoritmo, di fronte a pi alternative, le seguisse
tutte contemporaneamente, generando pi copie di se stesso.
Ciascuna copia procede la computazione, indipendentemente dalle altre, seguendo
una e una sola delle alternative possibili.

Istruzioni elementari O(1)


Choiche(c): sceglie arbitrariamente un elemento dellinsieme finito C

Failure: che blocca la computazione in uno stato di fallimento

Success: che blocca la computazione in uno stato di successo

Non determinismo

Non determinismo, schema generale

Non determinismo tramite enumerazione

Classe P
Classe di tutti i problemi decisionali risolvibili in tempo polinomiale con algoritmi
deterministici
Classe NP
La classe di tutti i problemi decisionali risolvibili in tempo polinomiale con algoritmi
non deterministici

P contenuta in NP

Non si sa se NP contenuta in P

Riducibilit polinomiale
Siano A e B due problemi decisionali. Si dice che A si riduce in tempo polinomiale a B,
e si scrive A B, se esiste una funzione f di trasformazione:
f: (dati dingresso per A) (dati dingresso per B)
Tale che:
f computabile in tempo polinomiale con un algoritmo deterministico;

x un dato dingresso per cui A d risposta S se e solo se f(x) un dato


dingresso per cui B d risposta S

*seguono cenni e spiegazioni poco comprensibili

Capitolo 19 Tecniche risolutive per problemi intrattabili

Bisogna rinunciare a qualcosa


o

Generalit (algoritmi pseudo-polinomiali): per alcuni input, il problema


potrebbe essere intrattabile

Ottimalit (algoritmi approssimazione): si cercano soluzioni non troppo


distanti da quella ottima

Efficienza (algoritmi branch&bound): si pota quando non si intravedono


soluzioni buone

Formalit: (algoritmi euristici): soluzioni che sembrano buone, anche


senza dimostrazione matematica

Somma di sottoinsieme: esiste un sottoinsieme che ha una certa somma?


o

Se la somma desiderata O(nc), la complessit polinomiale

Se la somma desiderata esponenziale, la complessit esponenziale

Algoritmo Rate-Monotonic (Liu, Layland): assegnare tempo di cpu a dei


processi periodi

(continua)

Misc

Ricorrenze lineari con partizione bilanciata


Tn=aTn/b+cn
a1
b2
0
=logalogb

:Onmax,
=:O(nmax, logn)

Master theorem

Tn=aTn/b+fn
a1
b1
=logba

0 :fn=On-Tn=n
fn=n
Tn=f(n)logn
0 :fn=n+
c<1 :afnbcfn Tn=f(n)

(da un certo n in poi)

c>0, 0
a=ai

Ricorrenze lineari di ordine costante

a=1On+1
a2O(nan)

ANALISI DI ALGORITMI
Dimensione dellinput
Criterio di costo logaritmico: la taglia dell'input il numero di bit necessari per
rappresentarlo .Esempio: moltiplicazione di numeri binari lunghi n bit
Criterio di costo uniforme: la taglia dell'input il numero di elementi che lo
costituiscono. Esempio: ricerca minimo in un array di n elementi
In molti casi: possiamo assumere che gli elementi siano rappresentati da un
numero costante di bit. Le due misure coincidono a meno di una costante
moltiplicativa

Modello di calcolo: rappresentazione astratta di un


calcolatore
Astrazione: deve semplificare i dettagli, altrimenti inutile
Realismo: deve riflettere la situazione reale
Potenza: deve permettere di trarre conclusioni formali sul costo

Binary search

Funziona solo su vettori ordinati .


O(log n)

Complessit:

Karatsuba

Serve per moltiplicare due binari con divide et impera


Complessit: O(n1.58)

Selection sort

Ordina un vettore mettendo il minimo allinizio ogni volta


O(n2)

Complessit:

Merge sort

Ordinare un vettore con divide et impera


O(nlog(n))

Complessit:

Analisi ammortizzata
Ci sono tre metodi per fare lanalisi ammortizzata:
Metodo dellaggregazione:

Si calcola la complessit O(f(n)) per eseguire operazioni in sequenza nel


caso pessimo

Il costo ammortizzato di una singola operazione O(f(n)/n)

Metodo degli accantonamenti (consigliato):

Alle operazioni vengono assegnati costi ammortizzati che possono essere


maggiori /minori del loro costo effettivo

Provare che la somma dei costi ammortizzati un limite superiore al costo


effettivo

Metodo del potenziale (ignorato)

Counting sort

Basato non sui confronti, dipende dal range (k) dei numeri
Complessit: O(n+k)

STRUTTURE ELEMENTARI
Lista circolare, bidirezionale, con sentinella

possibile realizzare le liste con i vettori, bisogna gestire per il problema della
dimensione dinamica, meglio gestirla come fa java nellarray list, incrementa ogni
volta del doppio e dimezza quando loccupazione pari ad un quarto.

Stack

Funziona come i piatti in pizzeria, LIFO

Queue

FIFO

ALBERI BINARI DI RICERCA


Alberi binari in cui il figlio sinistro pi piccolo del padre, il figlio destro pi grande
del padre

Alberi binari di ricerca

Ricerca: implementazione

Cerca un valore nellalbero


O(logn)

Complessit:

Ricerca del minimo e del massimo

Complessit:
O(logn)

Successore-predecessore

Successore: di un nodo il pi piccolo nodo maggiore di quel nodo

Inserimento

Nel caso pessimo dobbiamo scorrere tutto laltezza dellalbero


Complessit: O(logn)

Cancellazione

Bisogna se in caso modificare lalbero perch rimanga un ABR

Bilanciamento degli alberi


Spesso le operazioni (ricerca, cancellazione ecc) sugli ABR dipendono dallaltezza
dellalbero. Conviene quindi cercare di tenere lalbero il pi possibile bilanciato: che
non vi sia troppa disequit di profondit fra sottoalbero destro e sottoalbero sinistro.
Per fare questo dobbiamo fare ogni tanto delle rotazioni.

Alberi Red-Black Treee


Sono implementati per prevedere la bilanciatura dellalbero. Ogni nodo pu essere
rosso o nero, le foglie non contengono valori, sono nodi nil ( in trealt ne esiste solo
uno, tutti puntano a quello, per risparmiare memoria). La radice nera, tutte le
foglie sono nere, i figli di un nodo rosso sono ambedue neri.
In pratica root e foglie sono neri, non posso avere due rossi consecutivi. Il path di
ogni foglia contiene lo stesso numero di nodi neri.
Altezza nera: il numero di nodi neri lungo ogni percorso da un nodo v (escluso) ad
una foglia (inclusa). Si indica con b(v)
Altezza nera di un albero: laltezza nera della radice

RB-Tree rotazione a sinistra

RB-Tree inserimento nodo

Come negli ABR, poi si sistema il tutto


O(log n)

Complessit:

RB-Tree cancellazione

Funziona come negli ABR, solo che poi dobbiamo decidere se aggiustare o no, si
deve aggiustare solo quando il nodo cancellato nero:
Se il nodo cancellato rosso:

laltezza nera rimane invariata

non sono stati creati nodi rossi consecutivi

la radice resta nera

Se il nodo cancellato nero:

la radice pu essere un nodo rosso

se il padre e uno dei figli del nodo erano rossi ci troviamo con due rossi di fila

cambia laltezza nera

Complessit: visitiamo O(log n) nodi ognuno in tempo O(1), quindi O(log n)

INSIEMI E DIZIONARI
Riepilogo complessit

Insieme: collezione di oggetti


Dizionario: insieme di associazioni chiave-valore

Insiemi realizzati con vettori booleani

Vantaggi: notevolmente semplice, efficiente verificare se un elemento appartiene


allinsieme
Svantaggi: occupazione di memoria
dellinsieme, operazioni inefficienti O(N)

O(N),

indipendente

dalla

dimensione

Insiemi realizzati con liste non ordinate


Vantaggi:
occupazione
di
memoria
proporzionale alla dimensione del vettore
Svantaggi: operazioni di ricerca, inserimento e
cancellazione O(n); unione, intersezione e
differenza O(nm)

Insiemi realizzati con liste ordinate


Vantaggi:
occupazione
di
memoria
proporzionale alla dimensione del vettore,
operazioni di unione, intersezione e differenza
O(n)
Svantaggi: operazione di ricerca, inserimento
e cancellazione: O(n)

Insiemi realizzati con strutture dati complesse


Con alberi di ricerca bilanciati:

Ricerca, inserimento, cancellazione: O(logn)

Viene mantenuto lordinamento

Elencare tutti gli elementi: O(n)

Con tabelle hash:

Ricerca, inserimento, cancellazione: O(1)

Viene perso lordinamento

Elencare tutti gli elementi: O(m) dove m la dimensione della tabella hash

HEAP MFSET
Code con priorit
Le operazioni base viste fin ora (cancellazione, inserimento ecc) possono non
bastare, certe volte dobbiamo inventarne di nuove. Le code di priorit sono una
struttura dati fatta apposta per essere efficiente a fare determinate operazioni. Gli
oggetti sono estratti dalla cosa in base alla loro priorit.

Albero binario perfetto


Tutte le foglie hanno la stessa altezza, tutti, tranne le foglie hanno due figli. Altezza
quindi log n.

Albero binario completo


Tutte le foglie hanno profondit H o H-1. Tutti i nodi a livello H sono accatastati a
sinistra. Tutti i nodi interni hanno grado due, eccetto al pi uno.

Heap
un particolare tipo di coda di priorit nella quale i dati sono mantenuti in modo
parzialmente ordinato.
Max heap: albero binario completo in cui la radice sempre il maggiore. (anche
nei sottoalberi, il padre sempre il maggiore)
Min heap: albero binario completo in cui la radice sempre minore (anche nei
sottoalberi)
Gli heap non impongono nessun ordinamento fra i figli di un nodo (ordinamento
parziale), limportante che i padre sia maggiore o minore rispettivamente per il
max e per il min heap.

Ogni nodo maggiore o uguale di se stesso

Se n >=m e m>=n allora n=m

Se n>=m e m>=r allora n>=r

Lordinamento parziale utile per modellare gerarchie complesse o per mantenere


informazioni parziali. pi semplice costruire uno heap ordinato parzialmente che
qualcosa ordinato totalmente.

Array heap

A[1] contiene la radice

p(i) = [i/2] (limite inferiore). Padre

l(i) = 2i. Figlio sinistro

r(i) = 2i+1. Figlio destro

Procedure per gestire uno heap


Max heap restore

Serve per mantenere la propriet dei max heap dopo un inserimento Complessit:
O(logn)
Ogni sottoalbero deve essere un max heap, quindi si cerca di fare scendere fino al
posto giusto il valore
Heap build

Serve per costruire un max heap da zero (dato un vettore)


Complessit: O(nlogn)
Heapsort

Ordina sul posto un array

Complessit: O(nlogn)

Coda con priorit


Una struttura dati che serve a mantenere un insieme S di elementi x, ciascuno con
un valore associato di priorit

Riduzione priorit

MFSET
Servono a rappresentare degli insiemi disgiunti, le operazioni fondamentali sono
unire pi insiemi, identificare linsieme a cui appartiene un oggetto. una collezione
di insiemi dinamici disgiunti (un insieme di insiemi). Ogni insieme rappresentato
da un rappresentante univoco. Le ricerche del rappresentate sullo stesso insieme
devono restituire sempre lo stesso oggetto. Solo dopo un unione questo oggetto pu
cambiare. Si pu scegliere lelemento pi piccolo/grande di un insieme

Applicazione: trovare le componenti connesse di un


grafo

Alla fine avremo linsieme delle comonenti connesse.


O(n+m)

Complessit:

Implementazione basata su liste

realizzazione basata su liste:

realizzazione basata su alberi: find O(n)

find O(1)

merge O(n)

merge O(1)

conviene anche inserire leuristica del peso (se liste) / rango (se alberi) e la
compressione dei percorsi. Euristica sul peso: ho due liste, per unirle devo scegliere
uno dei due rappresentanti ed applicarlo allaltra lista, logicamente attacco la pi
corta alla pi lunga, quindi mi salvo anche la dimensione.
Nel caso delle liste: ogni elemento contiene un puntatore al successivo, un
puntatore al rappresentante ed un oggetto

Pu essere visto come un albero di altezza 1


Loperazione find richiede O(1), si restituisce il rappresentante di X
Il merge(x,y) richiede pi tempo, si appende la lista che contiene Y alla lista che
contiene X, e poi vengono modificati tutti i puntatori, caso pessimo per n operazioni
O(n2), costo ammortizzato: O(n).

Implementazione basata su alberi


Ogni nodo ha un oggetto ed il puntatore al padre, la radice punta a se stessa ed il
rappresentante
Find O(n) nel caso pessimo, bisogna risalire fino a trovare la radice
Merge(x,y) O(1) si appendono gli alberi
Qui conviene applicare la compressione dei cammini:

Quando si cerca qualcosa portiamo tutto in su. Cos le successive ricerche


costeranno O(1):

DIVIDE ET IMPERA
Divide: dividi il problema in sotto problemi pi piccoli ed indipendenti
Impera: risolvi i sotto problemi ricorsivamente
Combina: unisci le soluzioni dei sottoproblemi

Ordina un vettore sul posto, divide comlicato, nessun combina


O(nlogn)

Parentesizzare (decidere
matrice fare prima)
Strassen

O(n2.81)

Winograd

O(n2,38)

quale

Complessit:

motiplicazione

di

TEOREMI DI ALGORITMI
----------------------------- Ricorrenze lineari con partizioni
bilanciate:
Tn= aTnb+cnn>1dn=1
Condizioni: a, b interi. a1, b2. c,d, reali. c,d>0 0
=logba
Se >
Se =
Se <
Esempio quando alfa > beta
Tn=2Tn4+1 =12,=0
Tn=On=O(n )
Esempio quando alfa = beta
Tn=2Tn4+n =12,=12
Tn=Onlogn=O(nlogn )
Esempio quando alfa < beta
Tn=2Tn4+n =12,=1
Tn=On=On

Tn=On
Tn=Onlog n
Tn=On

--------------------------------------------------------------- Master
theorem:
Tn= aTnb+f(n)n>1dn=1
=logba
Se fn=On- >0
Tn=n
Se fn=n
Tn=nlog n
Se fn=n+>0, c<1, m0 | afnbcfn nm
Tn=Of(n)
Esempio fn=On-:
Tn=9Tn3+n =log39=2 dobbiamo cercare un delta che faccia risultare -=esponente di n.
Esiste e vale 1. Quindi Tn=n2
fn=n
Tn=9Tn3+n2 =2 Quindi Tn=n2log n
fn=n+
Tn=9Tn3+n3 =2 dobbiamo cercare un delta che faccia risultare alfa + delta uguale
allesponente di n, esiste e vale 1 quindi Tn=On3

------------------------------------- Ricorrenze lineari di


ordine costante:

Tn= i=1haiTn-i+cnn>1dn=1
=logba
Se a=1
Se a>1
Esempio:
Tn=7Tn-2+3Tn-4+n2
a2=7 a4=3 ai=0 se i2,4. a=7+3=10. a>1Tn=O(10nn2)

Tn=On+1
Tn=O(ann)