131
Appunti di Algoritmi e Strutture Dati Alberto Carraro

Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

  • Upload
    others

  • View
    5

  • Download
    1

Embed Size (px)

Citation preview

Page 1: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Appunti di Algoritmi e Strutture Dati

Alberto Carraro

Page 2: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

2

Page 3: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Contents

1 Introduzione informale agli algoritmi 71.1 I numeri di Fibonacci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

1.1.1 Algoritmo numerico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.1.2 Algoritmo ricorsivo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.1.3 Algoritmo iterativo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91.1.4 Algoritmo basato su potenze ricorsive . . . . . . . . . . . . . . . . . . . . . . . . . 10

2 Modelli di calcolo e metodologie di analisi 132.1 Criteri di costo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132.2 La notazione asintotica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132.3 Delimitazioni inferiori e superiori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142.4 Metodi di analisi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142.5 Analisi di algoritmi ricorsivi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

2.5.1 Metodo di iterazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142.5.2 Metodo di sostituzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152.5.3 Il teorema fondamentale delle ricorrenze . . . . . . . . . . . . . . . . . . . . . . . . 162.5.4 Analisi dell’albero della ricorsione . . . . . . . . . . . . . . . . . . . . . . . . . . . 182.5.5 Cambiamenti di variabile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

2.6 Analisi ammortizzata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192.6.1 Metodo dell’aggregazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202.6.2 Metodo degli accantonamenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202.6.3 Metodo del potenziale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2.7 Esercizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

3 Correttezza degli algoritmi 293.1 Algoritmi iterativi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293.2 Algoritmi ricorsivi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

4 Pile e code 314.1 Pile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314.2 Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314.3 Esercizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

5 Liste 335.1 Esercizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

6 Alberi 376.1 Introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376.2 Rappresentazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

6.2.1 Rappresentazioni indicizzate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386.2.2 Rappresentazioni collegate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

6.3 Visite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386.3.1 Visita in profondita . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396.3.2 Visita in ampiezza . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

6.4 Alberi binari di ricerca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396.5 Esercizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

3

Page 4: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

6.6 Alberi AVL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

6.6.1 Ribilanciamento tramite rotazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

6.6.2 Alberi di Fibonacci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

7 Heap e code di priorita 45

7.1 Heap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

7.1.1 Costruzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

7.1.2 Realizzazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

7.2 Code di priorita . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

8 Algoritmi di ordinamento 49

8.1 Selection sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

8.2 Insertion sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

8.3 Bubble sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

8.4 Heap sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

8.5 Merge sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

8.6 Quicksort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

8.7 Counting sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

8.8 Radix sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

8.9 Limitazione inferiore per algoritmi basati sul confronto . . . . . . . . . . . . . . . . . . . . 53

9 Tabelle hash 55

9.1 Definizione di funzioni hash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

9.2 Risoluzione delle collisioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

9.2.1 Liste di collisione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

9.2.2 Indirizzamento aperto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

10 Tecniche algoritmiche 59

10.1 Divide et impera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

10.2 Programmazione dinamica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

10.3 Paradigma greedy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

11 Grafi 63

11.1 Definizioni preliminari . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

11.2 Rappresentazione di grafi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

11.2.1 Lista di archi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

11.2.2 Liste di adiacenza . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

11.2.3 Matrice di adiacenza . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

11.2.4 Confronto tra le rappresentazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

11.3 Visite di grafi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

12 Minimo albero ricoprente 69

12.1 Teorema fondamentale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

12.2 Algoritmo di Kruskal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

12.3 Algoritmo di Prim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

13 Cammini minimi con sorgente singola 75

13.1 Cammini minimi e rilassamento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

13.2 Algoritmo di Dijkstra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

13.3 Algoritmo di Bellman-Ford . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

14 Cammini minimi fra tutte le coppie 85

14.1 Cammini minimi e moltiplicazione di matrici . . . . . . . . . . . . . . . . . . . . . . . . . 85

14.2 Algoritmo di Floyd-Warshall . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

4

Page 5: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

15 Reti di flusso 9115.1 Introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9115.2 Problema del flusso massimo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9315.3 Flusso massimo - taglio minimo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9515.4 Algoritmo di Ford-Fulkerson . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

15.4.1 Ottimizzazione di Edmond-Karp . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9915.5 Abbinamento massimo nei grafi bipartiti . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10215.6 Caso di studio: segmentazione di immagini . . . . . . . . . . . . . . . . . . . . . . . . . . 105

16 String matching 10716.1 Introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10716.2 Algoritmo ingenuo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10816.3 String matching con automa a stati finiti . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

16.3.1 Automi a stati finiti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10916.3.2 L’algoritmo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11016.3.3 Costruzione dell’automa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111

16.4 Algoritmo di Knuth - Morris - Pratt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

17 Geometria computazionale 11717.1 Intersezione tra segmenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118

17.1.1 Ricerca di un’intersezione tra diversi segmenti . . . . . . . . . . . . . . . . . . . . . 11917.2 Inviluppo convesso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121

17.2.1 Algoritmo “brute force” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12217.2.2 Algoritmo di Jarvis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12217.2.3 Algoritmo di Graham . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12317.2.4 Algoritmo Quick Hull . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

18 Teoria della NP-completezza 12518.1 Complessita di problemi decisionali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

18.1.1 Classi di complessita . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12518.2 La classe NP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

18.2.1 Non determinismo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12618.2.2 La gerarchia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127

18.3 Riducibilita polinomiale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12718.4 Problemi NP-completi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12718.5 La classe coNP e la relazione tra P e NP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128

19 Appendice 12919.1 Serie aritmetica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12919.2 Serie geometrica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12919.3 Calcolo di somme per integrazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13019.4 Goniometria e trigonometria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

5

Page 6: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

6

Page 7: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Chapter 1

Introduzione informale agli algoritmi

Definizione 1.1. Un algoritmo e un insieme di istruzioni, definite passo per passo, in modo tale da poteressere eseguite meccanicamente, e tali da produrre un determinato risultato.

1.1 I numeri di Fibonacci

Si vuole scrivere un algoritmo per il calcolo dell’n-esimo numero di Fibonacci, che puo essere calcolatoutilizzando la seguente formula:

Fn =

1 se n = 1, 2

Fn−1 + Fn−2 se n ≥ 3(1.1)

Saranno presentati diversi algoritmi, evidenziandone pregi e difetti.

1.1.1 Algoritmo numerico

Un primo algoritmo si basa sull’utilizzo di una funzione matematica che calcoli direttamente i numeri diFibonacci; proviamo a vedere se e possibile individuarne una esponenziale della forma an con a 6= 0 chesoddisfi la relazione di ricorrenza 1.1:

an = an−1 + an−2

an−2 · (a2 − a− 1) = 0

Poiche, per ipotesi, a 6= 0, cerchiamo i valori di a che soddisfano l’equazione:

a2 − a− 1 = 0 (1.2)

L’equazione 1.2 ammette due radici reali:

φ =1 +√

5

2≈ +1.618

φ =1−√

5

2≈ −0.618

Le funzioni φn e φn soddisfano entrambe la relazione (1.1), ma nessuna di esse calcola correttamentei numeri di Fibonacci come vorremmo: ad esempio, φ2 6= F2; questo perche non sono stati considerati ipassi base della definizione ricorsiva.

Per risolvere il problema, e sufficiente osservare che una qualunque combinazione lineare di funzioniche soddisfano la relazione di Fibonacci soddisfa anch’essa tale relazione; cerchiamo opportune costantic1 e c2 che diano la funzione cercata:

c1 · φ+ c2 · φ = 1

c1 · φ2 + c2 · φ2 = 1

Risolvendo il sistema si ottiene:

7

Page 8: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

c1 = +1√5

c2 = − 1√5

Segue che il primo algoritmo per il calcolo dei numeri di Fibonacci e il seguente:

Algoritmo Fibonacci numerico

1 int fibonacciNumerico(int n)

2 return 1√5· (φn − φn);

3

Il limite di tale algoritmo e dato dal fatto che si e costretti ad operare con numeri reali, rappresentatinei calcolatori con precisione limitata, e quindi si possono fornire risposte errate dovute ad errori diarrotondamento.

1.1.2 Algoritmo ricorsivo

Data la natura ricorsiva della relazione di Fibonacci, si puo pensare di realizzare un algoritmo ricorsivo,come il seguente:

Algoritmo Fibonacci ricorsivo

1 int fibonacciRicorsivo(int n)

2 if (n <= 2)

3 return 1;

4 else

5 return fibonacciRicorsivo(n-1) + fibonacciRicorsivo(n-2);

6

Per analizzare le prestazioni di un algoritmo, si possono considerare il numero di linee di codiceeseguite (complessita temporale) e la quantita di memoria occupata (complessita spaziale): consideriamola prima.

In generale, ogni algoritmo ricorsivo puo essere analizzato mediante una relazione di ricorrenza: iltempo speso da una routine e pari al tempo speso all’interno della routine piu quello speso dalle chiamatericorsive; ad esempio, la relazione per l’algoritmo sopra descritto, per n > 2, e la seguente:

T (n) = 2 + T (n− 1) + T (n− 2)

Possiamo rappresentare le chiamate ricorsive con una struttura ad albero, detta albero di ricorsione:si usa un nodo, la radice dell’albero, per la prima chiamata e generiamo un figlio per ogni chiamataricorsiva.

F2 = 1

F1 = 1F2 = 1 F2 = 1

F1 = 1

F3 = 2

F3 = 2F4 = 3

F5 = 5

Figure 1.1: Albero di ricorsione di fibonacciRicorsivo per il calcolo di F5

Per calcolare il numero di linee di codice eseguite da una generica chiamata fibonacciRicorsivo(n)usiamo i seguenti lemmi.

Lemma 1.1. Sia Tn l’albero delle chiamate ricorsive della funzione fibonacciRicorsivo(n): il numerodi foglie in Tn e pari al numero di Fibonacci Fn.

Proof. Procediamo per induzione su n.

8

Page 9: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Caso base: e banalmente verificato; per n = 1, T1 contiene un solo nodo, e dunque una sola foglia(F1 = 1) e, per n = 2, T2 contiene anch’esso un solo nodo, e quindi una sola foglia (F2 = 1).

Ipotesi induttiva: sia n > 2 e supponiamo che il lemma sia verificato per ogni k tale per cui 2 ≤ k ≤n− 1.

Passo induttivo: usando l’ipotesi, dimostriamo che il lemma vale per n. L’albero della ricorsione Tn hacome sottoalbero sinistro Tn−1 e come sottoalbero destro Tn−2: per ipotesi essi hanno, rispettiva-mente, Fn−1 e Fn−2 foglie, dunque Tn ha Fn−1 + Fn−2 = Fn foglie, come si voleva dimostrare.

Lemma 1.2. Sia T un albero binario in cui ogni nodo interno ha esattamente due figli: allora il numerodi nodi interni di T e pari al numero di foglie diminuito di uno.

Proof. Procediamo per induzione su n.

Caso base: se n = 1, T ha una sola foglia e nessun nodo interno, quindi la condizione e verificata.

Ipotesi induttiva: supponiamo per ipotesi che la condizione valga per tutti gli alberi con meno di nnodi.

Passo induttivo: proviamo che la condizione valga anche per T , ossia che i = f − 1, dove i e il numerodi nodi interni di T e f il numero di foglie di T ; sia T un albero ottenuto da T rimuovendo unaqualunque coppia di foglie aventi lo stesso padre: T avra i − 1 nodi interni e f − 2 + 1 = f − 1foglie. Per ipotesi, poiche T ha meno nodi di T , vale la relazione i − 1 = (f − 1) − 1: sommandouno ad ambo i membri, si ottiene i = f − 1, ossia l’uguaglianza che si voleva dimostrare.

Alla luce di quanto appena dimostrato, la chiamata generica fibonacciRicorsivo(n) comportal’esecuzione di Fn righe di codice per via delle foglie (una per ciascuna foglia) e 2 · (Fn − 1) righeper via dei nodi interni (due per ciascuno), per un totale di 3 ·Fn− 2 righe di codice, una soluzione assaiinefficiente.

1.1.3 Algoritmo iterativo

La lentezza di fibonacciRicorsivo e dovuta al fatto che continua a ricalcolare ripetutamente la soluzionedello stesso sottoproblema (vedi, ad esempio, F3 nell’albero di ricorsione in figura 1.1); per fare di meglio,si potrebbe risolvere il sottoproblema una volta sola, memorizzarne la soluzione ed usarla nel seguitoinvece di ricalcolarla: questa e l’idea che sta alla base della tecnica chiamata programmazione dinamica.

Algoritmo Fibonacci iterativo

1 int fibonacciIterativo(int n)

2 int Fib[n];

3 Fib [0] = Fib [1] = 1;

4 for (int i = 2; i < n; i++)

5 Fib[i] = Fib[i-1] + Fib[i-2];

6 return Fib[n]

7

Per quanto riguarda l’analisi temporale, occorre operare in maniera diversa: per ogni linea di codice,calcoliamo quante volte essa e eseguita, esaminando a quali cicli appartiene e quante volte essi sonoeseguiti. Nel nostro caso si ha:

T (n) =

4 se n = 1, 2

2n se n > 2

Si tratta di una soluzione decisamente piu efficiente dell’algoritmo ricorsivo proposto.

9

Page 10: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Un piccolo miglioramento

L’algoritmo fibonacciIterativo richiede una quantita di spazio di memoria linearmente proporzionalealla dimensione dell’input n, anche se ogni iterazione utilizza solo i due valori precedenti a Fn, Fn−1

e Fn−2; rimpiazzando l’array con due variabili, come proposto nel seguente algoritmo, otteniamo unnotevole risparmio di memoria.

Algoritmo Fibonacci iterativo modificato

1 int fibonacciIterativoModificato(int n)

2 int a = 1, b = 1;

3 for (int i=2; i<n; i++)

4 c = a + b;

5 a = b;

6 b = c;

7

8 return b;

9

1.1.4 Algoritmo basato su potenze ricorsive

L’algoritmo che sara presentato in questa sezione si basa sul seguente lemma.

Lemma 1.3. Sia A =

(1 11 0

). Allora An−1 =

(1 11 0

)n−1

=

(Fn Fn−1

Fn−1 Fn−2

).

Proof. Procediamo per induzione su n.

Caso base: sia F0 = 0 fissato per convenzione. Per n = 2 il caso base e banalmente verificato:(1 11 0

)1

=

(F2 F1

F1 F0

)Ipotesi induttiva: supponiamo valido il lemma per n− 1, ossia:(

1 11 0

)n−2

=

(Fn−1 Fn−2

Fn−2 Fn−3

)Passo induttivo: dimostriamo la validita del lemma per n:

An−1 =

(1 11 0

)n−1

=

(Fn−1 Fn−2

Fn−2 Fn−3

)·(

1 11 0

)=

(Fn−1 + Fn−2 Fn−1

Fn−2 + Fn−3 Fn−2

)=

(Fn Fn−1

Fn−1 Fn−2

)Usando il lemma appena dimostrato ed utilizzando il metodo dei quadrati ripetuti per il calcolo della

potenza n-esima della matrice, si ottiene il seguente algoritmo:

Algoritmo Fibonacci con matrici

1 int fibonacciMatrice(int n)

2 M =

(1 11 0

)3 potenzaDiMatrice(M, n - 1)

4 return M[0][0]

5

6 void potenzaDiMatrice(int [][] M, int n)

7 if (n > 1)

8 potenzaDiMatrice(M, n / 2)

9 M = M * M

10

11 if (n dispari)

12 M = M *

(1 11 0

)13

10

Page 11: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

L’algoritmo presenta la seguente relazione di ricorrenza:

T (n) =

O(1) se n ≤ 1

T (n/2) +O(1) se n > 1

la cui soluzione e:

T (n) = O(log n)

11

Page 12: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

12

Page 13: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Chapter 2

Modelli di calcolo e metodologie dianalisi

2.1 Criteri di costo

Il criterio di misurazione del tempo di esecuzione di un algoritmo che si basa sull’assunzione che le diverseoperazione richiedano tutte lo stesso tempo, indipendentemente dalla dimensione degli operandi coinvolti,e noto come misura di costo uniforme; si tratta di un criterio utile in prima approssimazione, ma si trattadi un modello troppo idealizzato.

Per ovviare a questo problema, e stato proposto un criterio, noto come misura di costo logaritmico,che assume che il costo di esecuzione delle operazioni dipenda dalla dimensione degli operandi coinvolti;nonostante fornisca una buona approssimazione, in svariati casi puo generare una complessita eccessivae non necessaria.

2.2 La notazione asintotica

Definizione 2.1. Data una funzione f(n), definiamo:

• O(f(n)) = g(n) : ∃c > 0 ∧ n0 ≥ 0 : g(n) ≤ cf(n),∀n ≥ n0 (g(n) cresce al piu come f(n));

• Ω(f(n)) = g(n) : ∃c > 0 ∧ n0 ≥ 0 : g(n) ≥ cf(n),∀n ≥ n0 (g(n) cresce almeno come f(n));

• Θ(f(n)) = g(n) : ∃c1, c2 > 0 ∧ n0 ≥ 0 : c1g(n) ≤ f(n) ≤ c2g(n),∀n ≥ n0 (g(n) cresce esattamentecome f(n)).

Proprieta 2.1. Date due funzioni f(n) e g(n), risulta g(n) = Θ(f(n)) se e solo se g(n) = O(f(n)) eg(n) = Ω(f(n)).

Proprieta 2.2. Θ gode della proprieta simmetrica: g(n) = Θ(f(n)) se e solo se f(n) = Θ(g(n)).

Proprieta 2.3. O,Ω sono simmetriche trasposte: f(n) = Ω(g(n)) se e solo se g(n) = O(f(n)).

Proprieta 2.4. Per tutte e tre le notazioni vale la proprieta transitiva: per la notazione O, ad esempio,f(n) = O(g(n)) ∧ g(n) = O(h(n))⇒ f(n) = O(h(n)).

Teorema 2.1. Siano f(n) e g(n) funzioni positive:

• limn→+∞f(n)g(n) = +∞

→ ∃M > 0 ∧ n0 > 0 : f(n)g(n) ≥M,∀n ≥ n0

→ f(n) ≥M · g(n)→ f(n) = Ω(g(n)) ∧ g(n) = O(f(n))

• limn→+∞f(n)g(n) = 0

→ preso ε > 0,∃n0 > 0 : f(n)g(n) ≤ ε,∀n ≥ n0

→ f(n) ≤ ε · g(n)→ f(n) = O(g(n)) ∧ g(n) = Ω(f(n))

13

Page 14: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

• limn→+∞f(n)g(n) = l 6= 0

→ preso ε > 0,∃n0 > 0 :∣∣∣ f(n)g(n) − l

∣∣∣ ≤ ε, ∀n ≥ n0

→ −ε ≤ f(n)g(n) − l ≤ ε

→ l − ε ≤ f(n)g(n) ≤ l + ε

→ (l − ε) · g(n) ≤ f(n) ≤ (l + ε) · g(n)→ f(n) = Θ(g(n))

2.3 Delimitazioni inferiori e superiori

Definizione 2.2. Un algoritmo A ha costo di esecuzione O(f(n)) su istanze di ingresso di dimensionen e rispetto ad una certa risorsa di calcolo, se la quantita r di risorsa sufficiente per eseguire A su unaqualunque istanza di dimensione n verifica la relazione r(n) = O(f(n)).

Definizione 2.3. Un problema P ha complessita O(f(n)) rispetto ad una data risorsa di calcolo se esisteun algoritmo che risolve P il cui costo di esecuzione rispetto a quella risorsa e O(f(n)).

Definizione 2.4. Un algoritmo A ha costo di esecuzione Ω(f(n)) su istanze di dimensione n e rispettoad una certa risorsa di calcolo, se la massima quantita r di risorsa necessaria per eseguire A su istanzedi dimensione n verifica la relazione r(n) = Ω(f(n)).

Definizione 2.5. Un problema P ha complessita Ω(f(n)) rispetto ad una data risorsa di calcolo se ognialgoritmo che risolve P ha costo di esecuzione Ω(f(n)) rispetto a quella risorsa.

Definizione 2.6. Dato un problema P con complessita Ω(f(n)) rispetto ad una data risorsa di calcolo,un algoritmo che risolve P e ottimo se ha costo di esecuzione O(f(n)) rispetto a quella risorsa.

2.4 Metodi di analisi

Per analizzare il tempo di esecuzione di un algoritmo, solitamente si usa distinguere fra tre diversecategorie di istanze, a parita di dimensione; sia T (I) il tempo di esecuzione dell’algoritmo sull’istanza I:

Caso peggiore:Tworst(n) = max

istanze didimensione n

T (I)

Caso migliore:Tbest(n) = min

istanze didimensione n

T (I)

Caso medio: sia P (I) la probabilita di occorrere dell’istanza I:

Tavg(n) =∑

istanze didimensione n

(T (I) · P (I))

2.5 Analisi di algoritmi ricorsivi

2.5.1 Metodo di iterazione

L’idea e quella di ridurre la ricorsione ad una sommatoria dipendente solo dalla dimensione del problemainiziale.

Esempio 2.1. Sia data la seguente relazione di ricorrenza e assumiamo, per semplicita di analisi, che nsia una potenza di 3:

T (n) =

1 se n = 1

9 · T (n/3) + n se n > 1

Srotolando la ricorsione otteniamo:

14

Page 15: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

T (n) = 9 · T (n/3) + n

= 9 · (9 · T (n/9) + n/3) + n

= 92 · T (n/32) + 9 · n/3 + n

= ...

= 9i · T (n/3i) +

i−1∑j=0

(9/3)jn

Dal momento che n/3i = 1 quando i = log3 n, risulta:

T (n) = 9log3n + n ·log3 n−1∑j=0

3j

Poiche log3 n = log9 n · log3 9, risulta 9log3 n = 9log9 n·log3 9 = n2; usando la serie geometrica, si ottiene:

T (n) = n2 +3log3 n − 1

3− 1= n2 +

n− 1

2= Θ(n2)

2.5.2 Metodo di sostituzione

L’idea e di intuire la soluzione della relazione di ricorrenza ed utilizzare il principio di induzione perdimostrare che l’intuizione e corretta.

Esempio 2.2. Sia data la seguente relazione di ricorrenza:

T (n) =

1 se n = 1

T (bn/2c) + n se n > 1

Intuizione: T (n) = O(n), ossia dimostrare che esistono c > 0 e n0 > 0 tali che T (n) ≤ c · n, ∀n ≥ n0

Passo base: provo n = 1T (1) = 1 ≤ c · 1→ c ≥ 1

Ipotesi induttiva: supponiamo di avere c > 0 tale per cui T (bn/2c) ≤ c · bn/2c.

Passo induttivo: sia n > 1T (n) = T (bn/2c) + n

≤ c · bn/2c+ n

≤ c · n2

+ n

Rimane da provare che c · n2 + n ≤ c · n; cio risulta essere vero per c ≥ 2.

Affinche siano verificati sia il caso base che il passo induttivo, occorre prendere una qualsiasi c ≥ 2.

Esempio 2.3. Per illustrare altre sottigliezze relative all’uso del metodo di sostituzione, consideriamo laseguente relazione di ricorrenza:

T (n) =

1 se n = 1, 2

9 · T (bn/3c) + n se n > 2

Intuizione: T (n) = O(n2), ossia dimostrare che esistono c > 0 e n0 > 0 tali che T (n) ≤ c·n2,∀n ≥ n0

Passo base: T (1) = T (2) = 1 ≤ c · 12 ≤ c · 22 → c ≥ 1

Ipotesi induttiva: assumiamo che la disuguaglianza sia soddisfatta per ogni k < n

15

Page 16: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Passo induttivo: sia n > 2T (n) = 9 · T (bn/3c) + n

≤ 9 · c · bn/3c2 + n

≤ 9 · c · (n/3)2 + n

= c · n2 + n

Usando questa soluzione, non riusciamo a dimostrare la nostra affermazione poiche c ·n2 +n > c ·n2;possiamo risolvere facilmente il problema usando un’ipotesi induttiva piu forte, in modo da far comparireun addendo negativo negativo che, sommato ad n, faccia tornare i conti; provando con l’ipotesi T (n) ≤c · (n2 − n) otteniamo:

T (n) = 9 · T (bn/3c) + n

≤ 9 · c · ((n/3)2 − n/3) + n

= c · n2 − 3 · c · n+ n

Rimane da provare che c ·n2− 3 · c ·n+n ≤ c · (n2−n); cio risulta essere vero per c ≥ 1/2. Abbiamo,pero, un altro problema: il passo base non e piu verificato; infatti T (1) = 1 > c · (12 − 1) = 0; cio puoessere risolto cambiando n0, che prima avevamo scelto pari a 1.

Poiche T (2) = 1 ≤ c · (4 − 2) per c ≥ 1/2, vediamo se possiamo scegliere n0 = 2: per poterlo fare,dobbiamo definire tutti i casi che si riconducono a T (1) come casi base e verificare che, per tutti questi,esista c che verifichi la nostra condizione; in particolare, in questo esempio, dobbiamo definire come passibase T (3), T (4), T (5), oltre a T (2) (per n ≥ 6 ci si riconduce a un caso per cui la condizione valga):

T (3) = 9 · T (1) + 3 = 12 ≤ c · (32 − 3) per c ≥ 2

T (4) = 9 · T (1) + 4 = 13 ≤ c · (42 − 4) per c ≥ 13/12

T (5) = 9 · T (1) + 5 = 14 ≤ c · (52 − 5) per c ≥ 7/10

Affinche siano verificati tutti i casi base e il passo induttivo, dobbiamo avere n0 = 2 e c ≥ 2.

2.5.3 Il teorema fondamentale delle ricorrenze

Si tratta di un metodo per analizzare algoritmi basati sulla tecnica del dividi et impera, in cui:

• un problema di dimensione n viene diviso in a sottoproblemi di dimensione n/b;

• dividere in sottoproblemi e combinare le soluzioni richiede tempo f(n).

La relazione di ricorrenza corrispondente a questo scenario e la seguente:

T (n) = a · T(nb

)+ f(n) (2.1)

Per analizzare la relazione di ricorrenza, consideriamo l’albero della ricorsione ed assumiamo che nsia una potenza esatta di b e che la ricorsione si fermi quando n = 1.

Proprieta 2.5. I sottoproblemi al livello i dell’albero della ricorsione hanno dimensione n/bi.

Proprieta 2.6. Il contributo di un nodo di livello i al tempo di esecuzione (escluso il tempo speso nellechiamate ricorsive) e f(n/bi).

Proprieta 2.7. Il numero di livelli nell’albero della ricorsione e logb n.

Proprieta 2.8. Il numero di nodi al livello i dell’albero della ricorsione e ai.

Usando le proprieta appena elencate, si puo riscrivere la relazione di ricorrenza nella seguente forma:

T (n) =

logb n∑i=0

ai · f( nbi

)(2.2)

La soluzione della (2.2) e data dal seguente teorema, noto come teorema fondamentale delle ricorrenze.

16

Page 17: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Teorema 2.2. La relazione di ricorrenza

T (n) =

1 se n = 1

a · T (n/b) + f(n) se n > 1

ha soluzione:

1. T (n) = Θ(nlogb a), se f(n) = O(nlogb a−ε) per ε > 0;

2. T (n) = Θ(nlogb a · log n), se f(n) = Θ(nlogb a);

3. T (n) = Θ(f(n)), se f(n) = Ω(nlogb a+ε) per ε > 0 e a·f(n/b) ≤ c·f(n) per c < 1 ed n sufficientemente grande.

Proof. Assumiamo per semplicita che n sia una potenza esatta di b.

Caso 1: riscriviamo il termine generico della sommatoria 2.2:

ai · f( nbi

)= O

(ai ·

( nbi

)logb a−ε)= O

(nlogb a−ε ·

( a · bεblogb a

)i)= O(nlogb a−ε · (bε)i)

Per limitare superiormente T (n) si puo scrivere:

T (n) =

logb n∑i=0

O(nlogb a−ε · (bε)i) = O

(nlogb a−ε ·

logb n∑i=0

(bε)i

)= O

(nlogb a−ε ·

(bε·(logb n+1) − 1

bε − 1

))=

O

(nlogb a−ε ·

(bε · nε − 1

bε − 1

))= O(nlogb a−ε · nε) = O(nlogb a)

Analizzando l’equazione 2.2 e considerando solo i tempi di esecuzione relativi ai nodi sull’ultimolivello dell’albero di ricorsione, otteniamo:

T (n) ≥ alogb n = nlogb a → T (n) = Ω(nlogb a)

Dalle due limitazioni segue che T (n) = Θ(nlogb a).

Caso 2: anche in questo caso, riscriviamo il termine generico della sommatoria:

ai · f( nbi

)= Θ

(ai ·

( nbi

)logb a)

= Θ(nlogb a ·

( a

blogb a

)i)= Θ(nlogb a)

Da cui segue:

T (n) =

logb n∑i=0

Θ(nlogb a) = Θ(nlogb a · logb n).

Caso 3: sotto l’assunzione a · f(n/b) ≤ c · f(n), risulta facile dimostrare che ai · f(n/bi) ≤ ci · f(n);infatti:

ai · f( nbi

)= ai−1 · a · f

(n/bi−1

b

)≤ ai−1 · c · f

( n

bi−1

)Iterando il ragionamento si ottiene la disuguaglianza desiderata. Usando l’equazione 2.2, la seriegeometrica con base c < 1 e la disuguaglianza appena dimostrata, si puo scrivere:

T (n) =

logb n∑i=0

ai · f( nbi

)≤ f(n) ·

∞∑i=0

ci = f(n) · 1

1− c= O(f(n))

Dalla relazione 2.2, si ricava immediatamente che T (n) = Ω(f(n)), da cui T (n) = Θ(f(n)).

Esempio 2.4. Consideriamo la seguente relazione di ricorrenza:

T (n) =

O(1) se n = 1

T (n/2) +O(1) altrimenti

Si ha f(n) = O(1) = Θ(nlog2 1); ci troviamo, dunque, nel caso 2 del teorema, e quindi risulta T (n) =Θ(log n).

17

Page 18: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Esempio 2.5. Consideriamo la seguente relazione di ricorrenza:

T (n) =

O(1) se n = 1, 2

9 · T (n/3) + n altrimenti

Si ha f(n) = n = O(nlog3 9−ε); dal caso 1 del teorema fondamentale, risulta che T (n) = Θ(n2).

Esempio 2.6. Consideriamo la seguente relazione di ricorrenza:

T (n) =

O(1) se n = 1

T (n/2) + n+ logn +1

Si ha f(n) = n+log n+1 = Θ(n) = Ω(nlog2 1−ε), che puo ricadere nel caso 3 del teorema fondamentale;occorre infatti trovare c < 1 tale che, per n sufficientemente grande, valga:

a · f(n/b) ≤ c · f(n)

→ 1 ·(n

2+ log

n

2+ 1)≤ c · (n+ log n+ 1)

→ c ≥n2 + log n

2 + 1

n+ log n+ 1

(=

1

2< 1 per n→ +∞

)Esistera n0 tale che, per n ≥ n0, si ha

n2 + log n

2 + 1

n+ log n+ 1≤ 3

4

E sufficiente prendere c = 3/4 affinche la disuguaglianza del caso 3 del teorema fondamentale siaverificata per n sufficientemente grande; segue che T (n) = Θ(n).

Esempio 2.7. Consideriamo la seguente relazione di ricorrenza:

T (n) =

O(1) se n = 1, 2

3 · T (n/3) + n · log n altrimenti

Nessuno dei casi del teorema principale puo essere applicato; si potrebbe pensare di utilizzare il terzocaso, ma questo non e possibile poiche n · log n e solo logaritmicamente, e non polinomialmente, piugrande di nlog3 3 = n.

2.5.4 Analisi dell’albero della ricorsione

La tecnica consiste nell’analizzare l’albero delle chiamate ricorsive, indicando le dimensioni dei problemidi ogni chiamata ricorsiva, ed analizzando la dimensione totale dei problemi ad ogni livello dell’albero.

Esempio 2.8. Consideriamo la seguente relazione di ricorrenza:

T (n) =

1 se n = 1, 2

9 · T (n/3) + n2 · log n altrimenti

n9

n/3 n/3 n/3 n/3 n/3 n/3 n/3 n/3 n/3

.... .... .... .... .... .... .... .... ....

Figure 2.1: Parte iniziale dell’albero di ricorsione

Calcoliamo il costo di ciascun livello dell’albero di ricorsione:

18

Page 19: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Liv. 0: problema di dimensione n e costo n2 · log n → totale = n2 · log n;

Liv. 1: problema di dimensione n3 e costo

(n3

)2

· log n3 → totale = 9 ·

(n3

)2

· log n3 ;

Liv. 2: problema di dimensione n32 e costo

(n32

)2

· log n32 → totale = 92 ·

(n32

)2

· log n32 ;

Liv. i: problema di dimensione n3i e costo

(n3i

)2

·log n3i → totale = 9i·

(n3i

)2

·log n3i = n2·log n−i·n2·log 3);

Foglie: problemi di dimensione 1→ n3k = 1→ k = log3 n.

T (n) =

log3 n−1∑i=0

(n2 · log n− n2 · i · log 3)︸ ︷︷ ︸contributo nodi interni

+ 9log3 n︸ ︷︷ ︸contributo foglie

= n2 · log n ·log3 n−1∑i=0

1− n2 · log 3 ·log3 n−1∑i=0

i+ n2

= n2 · log n · log3 n− n2 · log 3 · (log3 n− 1) · (log3 n)

2+ n2

= n2 · log n · log3 n− n2 · log 3 · log23 n

2+ n2 · log 3 · log3 n

2+ n2

Risulta quindi T (n) = Θ(n2 · log2 n).

2.5.5 Cambiamenti di variabile

Si tratta di una tecnica che viene utilizzata quando la relazione di ricorrenza presenta delle radici; permaggiori informazioni, vedere l’esempio.

Esempio 2.9. Consideriamo la seguente relazione di ricorrenza:

T (n) =

O(1) se n = 1

T (√n) +O(1) altrimenti

Eseguiamo la sostituzione n = 2x (ossia x = log n), da cui√n = 2x/2 e T (2x) = T (2x/2) + O(1);

poniamo inoltre T (2x) = R(x), da cui otteniamo la relazione di ricorrenza R(x) = R(x/2) + O(1),risolvibile con il teorema principale (R(x) = O(log x)). Combinando le uguaglianze T (2x) = O(log x) en = 2x, si ha T (n) = O(log log n).

2.6 Analisi ammortizzata

una tecnica usata nel campo dell’analisi delle complessita per calcolare il costo medio di una singolaoperazione, all’interno di una sequenza che puo contenere operazioni molto costose, in maniera piu precisa,invece di sovrastimare tutte le operazioni attribuendo loro costo massimo.

Attenzione: l’analisi del caso medio considera la tipologia di input “medio”, ovvero quello piuprobabile; l’analisi ammortizzata non usa la teoria della probabilita, ma considera una serie di operazionie valuta le prestazioni medie di ciascuna operazione nel caso pessimo.

Nell’analisi ammortizzata, si fa sostanzialmente uso di tre metodi:

• metodo dell’aggregazione;

• metodo degli accantonamenti ;

• metodo del potenziale.

19

Page 20: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

In seguito, considereremo l’esempio di un contatore binario: dato un array A[k − 1...0] di 0, 1, cherappresenta il numero

x =

k−1∑i=0

(A[i] · 2i)

si vuole calcolare il costo di n incrementi, con x inizialmente a zero; l’algoritmo di incremento e il seguente:

1 increment (array A → void)

2 i = 0

3 while(i < length(A) && A[i] == 1)

4 A[i] = 0

5 i = i + 1

6

7 if(i < length(A))

8 A[i] = 1

Seguendo la tecnica di analisi tradizionale, poiche nel caso peggiore la complessita dell’incremento eO(k), concludiamo che il costo di n incrementi e O(n · k). Proviamo, invece, ad usare ciascuna delle tretecniche dell’analisi ammortizzata e vediamo che risultati otteniamo.

2.6.1 Metodo dell’aggregazione

Idea: se una sequenza di n operazioni impiega, nel caso peggiore, un tempo T (n), allora il costo ammor-tizzato di ogni operazione e T (n)/n.

Esempio 2.10. Facciamo n operazioni di increment: chiaramente non tutti i bit cambiano ad ognichiamata. In particolare:

• A[0] cambia ad ogni chiamata, per un totale di n volte;

• A[1] cambia ogni due chiamate, per un totale di bn/2c volte;

• A[2] cambia ogni quattro chiamate, per un totale di bn/4c volte;

• A[i] cambia la meta delle volte di A[i− 1], ossia bn/2ic volte.

Il numero totale di cambi in n operazioni e:

T (n) =

k∑i=0

⌊ n2i

⌋≤

k∑i=0

n

2i= n ·

k∑i=0

(1

2

)i≤ n ·

∞∑i=0

(1

2

)i= 2 · n

Quindi, il costo medio delle operazioni nel caso pessimo e 2 · n/n = 2 = O(1).

2.6.2 Metodo degli accantonamenti

Idea: vengono assegnati costi diversi a operazioni differenti; qualche operazione potrebbe essere as-sociata a un costo minore o maggiore di quello effettivo, detto costo ammortizzato. Quando il costoammortizzato supera quello effettivo, la differenza viene trattenuta come credito: questo puo essere usatosuccessivamente per pagare operazioni il cui costo ammortizzato e minore di quello effettivo.

Siano:

• Ci: costo effettivo dell’i-esima operazione;

• Ci: costo ammortizzato dell’i-esima operazione;

dopo n operazioni, dev’essere valida la relazione:

n∑i=1

Ci ≥n∑i=1

Ci

Il credito totale e dato dalla seguente formula:

n∑i=1

Ci −n∑i=1

Ci

20

Page 21: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Esempio 2.11. Definiamo i costi nel seguente modo:

• impostare un bit a 1 costa 2 unita;

• impostare un bit a 0 costa 0 unita.

Il costo ammortizzato di ogni operazione di increment e 2 unita, in quanto viene impostato un solo bit a1, mentre un numero variabile di bit a 0. Ora dobbiamo provare che il credito totale e sempre maggioreo uguale a zero; definiamo innanzitutto bi come il numero di bit a 1 dopo l’i-esima operazione.

Proprieta 2.9. Se ogni operazione di increment viene pagata con costo ammortizzato 2 e il contatoree inizialmente nullo, allora dopo i operazioni il credito e maggiore o uguale a bi.

Proof. Procediamo per induzione su i.

Caso base: si ha i = 0; il credito e 0 e bi = 0, in quanto il contatore e inizialmente nullo.

Ipotesi induttiva: per k < i, il credito dopo la k-esima operazione e maggiore o uguale a bk.

Passo induttivo: sia i > 0; per ipotesi si ha che il credito, dopo i − 1 operazioni, e maggiore o ugualea bi−1. L’operazione i-esima:

• deposita due unita, da cui il credito iniziale e maggiore o uguale a bi−1 + 2;

• imposta a zero una serie si di bit: si ha si ≤ bi;• se il contatore non e stato azzerato, imposta un bit a 1.

Il costo effettivo della chiamata e quindi minore o uguale a si + 1. All’uscita:

• bi ≤ bi−1 − si + 1;

• il credito e dato dalla differenza tra credito iniziale e costo effettivo:

credito ≥ bi−1 + 2− (si + 1)

= bi−1 − si + 1

≥ bi

Dunque il credito residuo non e mai negativo.

2.6.3 Metodo del potenziale

Idea: rappresentiamo il credito prepagato come una sorta di “energia potenziale” che puo essere liberataper pagare le operazioni future; il potenziale e associato alla struttura e dipende dalle operazioni fatte.

Fissiamo una struttura ed eseguiamo n operazioni:

φ : 0, 1, ..., n → R

dove:

• φ(0) e il potenziale iniziale;

• φ(i) e il potenziale dopo l’i-esima operazione;

• Ci e il costo dell’i-esima operazione;

• Ci e il costo ammortizzato dell’i-esima operazione.

I fondi effettivi devono essere pari alle spese sostenute, ossia:

Ci + φ(i− 1) = Ci + φ(i)

da cui:Ci = Ci + φ(i)− φ(i− 1)

21

Page 22: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Si ha:n∑i=1

Ci =

n∑i=1

(Ci + φ(i)− φ(i− 1))

=

n∑i=1

Ci +

n∑i=1

φ(i)−n∑i=1

φ(i− 1)

=

n∑i=1

Ci + φ(n) +

n−1∑i=1

φ(i)−n∑i=2

φ(i− 1)− φ(0)

=

n∑i=1

Ci + φ(n) +

n−1∑i=1

φ(i)−n−1∑j=1

φ(j)− φ(0)

=

n∑i=1

Ci + φ(n)− φ(0)

Vogliamo che valga:n∑i=1

Ci ≥n∑i=1

Ci

ossia:φ(n)− φ(0) ≥ 0 (2.3)

Se non sappiamo quante operazioni saranno fatte, per garantire la relazione 2.3, si impone φ(i) ≥ φ(0);di solito e comodo porre φ(0) = 0 e provare φ(i) ≥ 0.

Esempio 2.12. Scegliamo φ(i) come il numero di bit a 1 dopo la i-esima operazione: si ha φ(0) = 0 eφ(i) ≥ 0 per ogni i > 0; abbiamo un buon potenziale, in quanto soddisfa φ(i) ≥ φ(0). Consideriamo lai-esima operazione e sia si il numero di bit impostati a zero nel corso di questa operazione; si ha:

bi =

bi−1 − si se bi−1 = k

bi−1 − si + 1 se bi−1 < k

Ci =

si se bi−1 = k

si + 1 se bi−1 < k

Da cui:

Ci =

si + bi − bi−1 se bi−1 = k

si + 1 + bi − bi−1 se bi−1 < k

=

si + bi−1 − si − bi−1 se bi−1 = k

si + 1 + bi−1 − si + 1− bi−1 se bi−1 < k

=

0 se bi−1 = k

2 se bi−1 < k

Scegliendo 2 come costo ammortizzato siamo a posto.

2.7 Esercizi

Esercizio 2.1. Dimostrare che f(n) ∈ Θ(g(n)) sse f(n) ∈ O(g(n)) ∩ Ω(g(n)).

Svolgimento: (⇒) Supponiamo che f(n) ∈ Θ(g(n)). Allora esistono due costanti c0, c1 ∈ R+ edun numero naturale n0 ∈ N tali che per ogni n ≥ n0 abbiamo c0g(n) ≤ f(n) ≤ c1g(n). Il fatto che∀n ≥ n0. c0g(n) ≤ f(n) ci dice che f(n) ∈ Ω(g(n)), mentre (∀n ≥ n0).f(n) ≤ c1g(n) implica chef(n) ∈ O(g(n)).(⇐) Siccome f(n) ∈ Ω(g(n)), esistono due costanti c0 ∈ R+ e n0 ∈ N tali che f(n) ≤ c0g(n), per ognin ≥ n0. Siccome f(n) ∈ O(g(n)), esistono due costanti c′0 ∈ R+ e n′0 ∈ N tali che c′0g(n) ≤ f(n),per ogni n ≥ n′0. Sia m0 = max(n0, n

′0). Allora c′0g(n) ≤ f(n) ≤ c0g(n), per ogni n ≥ m0. Dunque

f(n) ∈ Θ(g(n)).

22

Page 23: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Esercizio 2.2. Dimostrare che per n > 6 si ha Fn > 2n2 .

Svolgimento: Ricordiamo la definizione ricorsiva della serie di Fibonacci:

Fn =

1 se n = 1 oppure n = 2

Fn−1 + Fn−2 se n ≥ 3

Prodediamo dunque con una prova per induzione completa. Il caso base e n = 7. Abbiamo F7 = 13 >

272 =

√128 perche 13 =

√169. Per ipotesi induttiva ora sappiamo che Fn−1 > 2

n−12 e Fn−2 > 2

n−22 ,

dunque Fn = Fn−1 + Fn−2 > 2n−12 + 2

n−22 = 2

n2√2

+ 2n2

2 > 2n2 poiche 2 +

√2 > 2

√2.

Esercizio 2.3. Dire perche il tempo di calcolo dell’algoritmo Fibonacci2 (pag. 6 [1]) cresce cosı rapida-mente al crescere di n (argomentando usando l’albero di ricorsione).

Svolgimento: Come dice anche il libro stesso, la formula di ricorrenza che calcola la complessitadell’algoritmo definisce la funzione di Fibonacci stessa. L’esercizio 2.2 ci dice che Fn ∈ Ω(2

n2 ), e pertanto

l’algoritmo ha complessita almeno esponenziale.

Esercizio 2.4. Spiegare come l’algoritmo Fibonacci3 (pag. 9 [1]) e migliore di Fibonacci2.

Svolgimento: La complessita di Fibonacci3 e lineare nella dimensione dell’input mentre gli eser-cizi 2.2,2.3 ci dicono che la complessita di Fibonacci2 e esponenziale nella dimensione dell’input.

Esercizio 2.5. Dimostrare che√n+ 10 ∈ Θ(

√n).

Svolgimento: Dobbiamo trovare due costanti c0, c1 ∈ R+ ed un numero naturale n0 ∈ N tali che perogni n ≥ n0 abbiamo c0

√n ≤√n+ 10 ≤ c1

√n.

Le soluzioni (nell’incognita n) della disequazione c0√n ≤√n+ 10 sono n ≥ −10

(1−c20). Scegliendo c0 = 2

abbiamo n ≥ 103 .

Le soluzioni (nell’incognita n) della disequazione√n+ 10 ≤ c1

√n sono n ≥ 10

(c21−1). Scegliendo c1 = 2

abbiamo n ≥ 10.L’intersezione dei due intervalli di soluzioni n : n ≥ 10 e n : n ≥ 10

3 e uguale a [10,+∞). Quindise scegliamo n0 = 10, c0 = 2 e c1 = 2 abbiamo che il sistema

c0√n ≤√n+ 10√

n+ 10 ≤ c1√n

e soddisfatto per ogni n ≥ n0.

Esercizio 2.6. Dimostrare che 12n

2 − 3n ∈ Θ(n2).

Svolgimento: Dobbiamo trovare due costanti c0, c1 ∈ R+ ed un numero naturale n0 ∈ N tali che perogni n ≥ n0 abbiamo c0n

2 ≤ 12n

2 − 3n ≤ c1n2.Le soluzioni (nell’incognita n) della disequazione c0n

2 ≤ 12n

2 − 3n sono n ≥ 61−c0 . Scegliendo c0 = 1

2abbiamo n ≥ 12.

Le soluzioni (nell’incognita n) della disequazione 12n

2 − 3n ≤ c1n2 sono n ≥ −62c1−1 . Scegliendo c1 = 1

abbiamo n ≥ −6.L’intersezione dei due intervalli di soluzioni n : n ≥ 12 e n : n ≥ −6 e uguale a [12,+∞). Quindi

se scegliamo n0 = 12, c0 = 12 e c1 = 1 abbiamo che il sistema

c0n2 ≤ 1

2n2 − 3n

12n

2 − 3n ≤ c1n2

e soddisfatto per ogni n ≥ n0.

Esercizio 2.7. Dimostriamo che:

(1) f(n) ∈ O(g(n)) sse g(n) ∈ Ω(f(n))

(2) f(n) ∈ Θ(g(n)) sse g(n) ∈ Θ(f(n))

Svolgimento:

23

Page 24: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

(1) Supponiamo f(n) ∈ O(g(n)). Allora esistono c ∈ R+ e n0 ∈ N tali che ∀n ≥ n0. f(n) ≥ cg(n).Dunque, ponendo c′ = 1

c si ha ∀n ≥ n0. c′f(n) ≥ g(n) e siccome c′ ∈ R+, abbiamo mostrato che

g(n) ∈ Ω(f(n)). Il viceversa si fa in maniera analoga.

(2) Basta usare il punto (1).

Esercizio 2.8. Sia f una funzione per cui esiste un numero naturale n0 tale che f(n) > 0, per ognin ≥ n0. Dimostriamo che per ogni a, b ∈ R+, af(n) + b ∈ Θ(f(n)).

Svolgimento: Dobbiamo trovare c1, c2, n0 tali che ∀n ≥ n0. c1f(n) ≤ af(n) + b ≤ c2f(n). Scegliamoc1 = a e c2 = a+ b. Allora af(n) ≤ af(n) + b ≤ af(n) + bf(n), per ogni n ≥ n0.

Esercizio 2.9. Dimostriamo che loga n e in Θ(logb n).

Svolgimento: Poiche logb n = (logb a)(loga n), ponendo c = logb a abbiamo che c(loga n) ≤ logb n ≤c(loga n) per ogni n ≥ 0.

Esercizio 2.10. Verificare che n(2 + sinn) = Θ(n).

Svolgimento: Consideriamo le due disequazioni c1n ≤ n(2 + sinn) ≤ c2n. Abbiamo che n ≤n(2 + sinn) e quindi basta scegliere c1 = 1. Similmente n(2 + sinn) ≤ c2n sse 2 + sinn ≤ c2. Scegliendoc2 = 4 cio e sempre vero.

Esercizio 2.11. Ordinare le seguenti classi di complessita: n2, n log n, n3 + log n,√n, n2 + 2n log n,

log(log n), 17 log n, 10n32 , n5 − n4 + 2n, 5n2 log(log n), 3n2 + n3 log n, n+ 6 log n.

Svolgimento: Iniziamo confrontando n5−n4 +2n e 3n2 +n3 log n. Vogliamo dire che 3n2 +n3 log n ∈o(n5 − n4 + 2n). Calcoliamo limx→∞

n5−n4+2n3n2+n3 logn = limx→∞

n2−n3n +logn

= +∞.

Poniamo y = log n. Allora log n ≤√n sse y2 ≤ n sse y2 ≤ 2y. Questa disuguaglianza e vera a partire

dal valore y = 4 e dunque dal valore n0 = 16 in poi. Quindi log(log n) ≤ log(√n) ≤

√√n = n

14 .

Pertanto esiste un n0 tale che 5n2 log(log n) ≤ 5n94 ∈ O(n3 + log n). Similmente possiamo ordinare

tutte le altre funzioni. Alla fine ci risulta che

• 3n2 + n3 log n ∈ O(n5 − n4 + 2n),

• n3 + log n ∈ O(3n2 + n3 log n),

• 5n2 log(log n) ∈ O(n3 + log n),

• n2 + 2n log n ∈ O(5n2 log(log n)),

• n2 ∈ O(n2 + 2n log n),

• 10n32 ∈ O(n2),

• n log n ∈ O(10n32 ),

• n+ 6 log n ∈ O(n log n)

•√n ∈ O(n+ 6 log n),

• 17 log n ∈ O(√n),

• log(log n) ∈ O(17 log n).

Inoltre nessuna coppia di queste funzioni appartiene alla stessa Θ-classe di equivalenza.

Esercizio 2.12. Scrivere un algoritmo che prende in input una lista e calcola il numero dei massimilocali. Calcolarne quindi la complessita.

Svolgimento: Ecco un possibile algoritmo.

24

Page 25: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

9 input: array A di interi

10 output: il numero dei massimi locali in A

11

12 c := 0;

13 j := 0;

14 while( j<lentgh(A) )

15 if (j>0 and j+1<length(A) and A[j-1] < A[j] > A[j+1])

16 c := c+1;

17

18 if (j>0 and j=length(A) -1 and A[j-1] < A[j])

19 c := c+1;

20

21 if (j-1=0 and j<length(A) and A[j-1] > A[j])

22 c := c+1;

23

24 j := j+1;

25

26 return c;

La sua complessita e Θ(n) dove n e la lunghezza di A.

Esercizio 2.13. Risolvere le seguenti relazioni di ricorrenza utilizzando il master theorem:

1. T (n) = 2T (n4 ) + n0.51

2. T (n) = 3T (n3 ) +√n

3. T (n) = 64T (n8 ) + n2 log n

Svolgimento: Per i casi base (n = 1) le ricorrenze sono definite come Θ(1).

1. Siccome 0.51 = log4(2)+ε con ε > 0, abbiamo che n0.51 = Ω(nlog4(2)+ε). Risolvendo la disequazione2(n4 )0.51 ≤ cn0.51 rispetto ad n otteniamo 2

40.51 ≤ c. Siccome 240.51 < 1, possiamo scegliere per c

un valore nell’intervallo ( 240.51 , 1), che soddisfa la disequazione per ogni n ≥ 0. Quindi T (n) =

Θ(nlog4(2)).

2. Abbiamo che√n ∈ O(nlog3(3)−ε) e dunque T (n) = Θ(nlog3(3)).

3. Abbiamo che n2 log n ∈ Ω(nlog8(64)+ε). Risolvendo la disequazione 64(n8 )2(log n8 ) ≤ cn2 log n

rispetto ad n otteniamo 1− 3logn ≤ c. Al crescere di n l’intervallo (0, 1− 3

logn ) tende all’intervallo

(0, 1). Siccome c va scelto nell’intervallo (1− 3logn , 1), non c’e un valore di c che vada bene per tutti

gli n a partire da un certo naturale in poi. Qui il master theorem non si puo applicare.

Esercizio 2.14. Trovare i limiti asintotici superiori ed inferiori (migliori possibile) per T (n) in ciascunadelle seguenti ricorrenze (supponendo che T (n) = Θ(1) per n ≤ 2).

1. T (n) = 3T (n2 ) + n log n

2. T (n) = 5T (n5 ) + nlogn

3. T (n) = 4T (n2 ) + n2√n

4. T (n) = 3T (n3 + 5) + n2

5. T (n) = 2T (n2 ) + nlogn

6. T (n) = T (n− 1) + 1n

7. T (n) = T (n− 1) + log n

8. T (n) = T (n− 2) + 2 log n

9. T (n) =√nT (√n) + n

25

Page 26: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Svolgimento: (1) Siccome log2 3 > 1 e n log n ∈ O(nlog2 3−ε) per un certo ε > 0 (p.e. log2 3−12 ) basta

applicare il Master Theorem per concludere che T (n) ∈ Θ(nlog2 3).

(2) In questo caso logb a = log5 5 = 1. Notiamo che nlogn 6∈ Θ(n) perche n 6∈ O( n

logn ). Per vedere

cio basta considerare la disequazione n ≤ cnlogn , le cui soluzioni in n sono intervalli della forma (0, 2c].

Notiamo anche che nlogn 6∈ O(n1−ε) perche la disequazione n

logn ≤cnnε ha come soluzioni i naturali n tali

che nε

logn ≤ c. Per ogni c > 0 fissato questa disequazione ha un insieme finito di soluzioni naturali. Infine

esiste un ε > 0 tale che nlogn ∈ Ω(n1+ε) perche

nlogn ≥ cn1+ε

ssen

logn ≥ cnnε

sse1

nε logn ≥ c

e per ogni c > 0 fissato esiste un n0 > 0 tale che per ogni n ≥ n0 abbiamo 1nε logn ≥ c. Basta prendere

ad esempio ε = 12 . Ora vediamo che

n5

log n5

≥ c nlogn

sselogn

5 logn−5 log 5 ≥ c

La funzione f(x) = log x5 log x−5 log 5 e monotona decrescente per x ≥ 10 e quindi basta scegliere c = f(10) < 1.

Pertanto il Master Theorem ci dice che T (n) ∈ Ω(nε).

(3) In questo caso logb a = log2 4 = 2. Inoltre n2√n = n

52 ∈ Ω(n2+ε) (basta scegliere 0 < ε < 1

2 ). Oravediamo che

4(n2 )52 ≥ cn

52

sse4

252

≥ c

Quindi possiamo applicare il Master Theorem e concludere che T (n) ∈ Θ(n52 ).

(4) Nella forma T (n) = 3T (n3 + 5) + n2 non si puo applicare il Master Theorem. Pero possiamo effettuare

un cambio di variabile y 7→ n + 15 e risolvere S(y) = 3T (y3 ) + y−152 . Siccome f(y) = y−15

2 ∈ Θ(ylog3 3)concludiamo che S(y) ∈ Θ(y log y). Infine T (n) = S(y − 15) ∈ Θ((y − 15) log(y − 15)) = Θ(n log n).

(5) In questo caso logb a = 1. Non si possono applicare i casi del Master Theorem perche nlogn 6∈ O(n1−ε)

e nlogn 6∈ Ω(n1+ε). Allora useremo il metodo dell’iterazione:

T (n) = 2log2 n + n∑log2 n−1j=0

1log2

n

2j

= n+ n∑log2 n−1j=0

1log2 n−j

= n+ n∑log2 ni=1

1i

≤ n+ n log2 n

Quindi T (n) ∈ O(n+ n log2 n).

(6) Non si possono applicare i casi del Master Theorem ma useremo il metodo dell’iterazione:

T (n) = T (n− 1) + 1n

=∑n−1i=0

1n−i

=∑ni=1

1i

≤ n

Quindi T (n) ∈ O(n).

26

Page 27: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

(7) Non si possono applicare i casi del Master Theorem ma useremo il metodo dell’iterazione:

T (n) = T (n− 1) + log n

=∑n−1i=0

1log(n−i)

=∑ni=1

1log i

≤ n

Quindi T (n) ∈ O(n).

(8) Non si possono applicare i casi del Master Theorem ma useremo il metodo dell’iterazione:

T (n) = T (n− 2) + 2 log n

=∑n−1

2i=0

12 log(n−2i)

≤ n

Quindi T (n) ∈ O(n).

(9) Non si possono applicare i casi del Master Theorem ma useremo il metodo dell’iterazione:

T (n) = n+ n12T (n

12 )

= n120 + n

121 (n

121 + n

122 T (n

122 ))

=∑di=0(n

1

2i∏ij=0 n

1

2j )

=∑di=0(n

1

2i n∑i

j=0( 12 )j )

=∑di=0(n

1

2i n2− 1

2i )

=∑di=0(n

1

2in2

n12i

)

=∑di=0 n

2

≤ n2 log2 n

dove d e il massimo numero naturale tale che n1

2d ≥ 1. Troviamo che T (n) ∈ O(n2 log n).

27

Page 28: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

28

Page 29: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Chapter 3

Correttezza degli algoritmi

3.1 Algoritmi iterativi

Per dimostrare la correttezza degli algoritmi iterativi si utilizza l’invariante di ciclo, ossia una proposizione(riguardante i contenuti delle variabili della procedura o programma) che rispetta le seguenti proprieta:

Inizializzazione: la proposizione e vera immediatamente prima di entrare nel ciclo.

Mantenimento: se la proposizione e vera prima di eseguire un’iterazione, lo e anche al termine dell’iterazione.

Terminazione: al termine del ciclo, la proposizione permette di ricavare la proprieta che permette didimostrare la correttezza dell’algoritmo.

Esempio 3.1. Consideriamo l’algoritmo fibonacciIterativoModificato, del quale vogliamo dimostrareil fatto che calcoli l’n-esimo numero di Fibonacci; l’invariante di ciclo e il seguente:

Ad ogni iterazione, b = Fi−1 e a = Fi−2

Inizializzazione: poiche i = 3, dobbiamo verificare che b = F2 e a = F1; la dimostrazione e immediata,poiche b = 1 = F2 e a = 1 = F1.

Mantenimento: assumiamo l’invariante verificato per una generica i-esima iterazione e dimostriamoche esso vale anche al termine di tale iterazione; ricordiamo inoltre, nonostante non sia esplici-tamente indicato, che al termine dell’iterazione viene incrementato l’indice i. Grazie alla nostraassunzione, abbiamo b = Fi−1 e a = Fi−2: alla variabile c viene assegnato il valore della sommaa + b = Fi−2 + Fi−1 = Fi, alla variabile a viene assegnato il valore di b = Fi−1, alla variabile b ilvalore di c = Fi ed i viene incrementata (i = i+ 1); e immediato dimostrare che continua a valerel’invariante, ossia che b = F(i+1)−1 e a = F(i+1)−2.

Terminazione: all’uscita del ciclo, si ha i = n+1, dunque b = F(n+1)−1 = Fn, che e il valore restituito,come volevasi dimostrare.

3.2 Algoritmi ricorsivi

La dimostrazione viene svolta procedendo per induzione; occorre formalizzare una proprieta utile perdimostrare la correttezza dell’algoritmo e provare che:

• valga per i casi base;

• assumendo che valga per problemi di dimensione inferiore, ossia per le chiamate ricorsive eseguite,provare che vale anche per il problema iniziale (passo induttivo).

Esempio 3.2. Consideriamo l’algoritmo fibonacciRicorsivo e formalizziamo la seguente proprieta:

L’output della chiamata di funzione fibonacciRicorsivo(n) e l’n-esimo numero di Fibonacci.

29

Page 30: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Casi base: per n = 1 e n = 2, l’algoritmo restituisce 1 = F1 = F2.

Ipotesi induttiva: supponiamo che, per k < n, fibonacciRicorsivo(k) restituisca Fk.

Passo induttivo: l’algoritmo restituisce fibonacciRicorsivo(n− 1) + fibonacciRicorsivo(n− 2)(sia n > 2); per ipotesi, essi restituiscono, rispettivamente, Fn−1 e Fn−2, la cui somma e Fn, comevolevasi dimostrare.

30

Page 31: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Chapter 4

Pile e code

4.1 Pile

La pila e una struttura dati, realizzabile sia con strutture indicizzate, sia collegate, che puo essere descrittadal seguente schema generale:

Dati: una sequenza S di n elementi.

Operazioni:

isEmpty() → booleanoRestituisce true se S e vuota, false altrimenti.

push(elem e) → voidAggiunge e come ultimo elemento di S.

pop() → elemToglie da S l’ultimo elemento e lo restituisce.

top() → elemRestituisce l’ultimo elemento di S, senza rimuoverlo.

4.2 Code

La coda, come la pila, e una struttura dati realizzabile sia mediante strutture indicizzate, sia con strutturecollegate; la realizzazione di una coda segue il seguente schema generale:

Dati: una sequenza S di n elementi.

Operazioni:

isEmpty() → booleanoRestituisce true se S e vuota, false altrimenti.

enqueue(elem e) → voidAggiunge e come ultimo elemento di S.

dequeue() → elemToglie da S il primo elemento e lo restituisce.

first() → elemRestituisce il primo elemento di S, senza rimuoverlo.

4.3 Esercizi

Esercizio 4.1. Realizzare una coda Q utilizzando due pile P1 e P2.

31

Page 32: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Svolgimento: Supponiamo di avere due pile P1 e P2. La pila P1 ci serve per mantenere la collezionedi oggetti, mentre P2 serve come ausilio per le operazioni.Metodo enqueue dell’oggetto Q.

void enqueue(Item x)

while(!P_1.isEmpty())

P_2.push(P_1.pop())

P_1.push(x)

while(!P_2.isEmpty())

P_1.push(P_2.pop())

Item dequeue(Item x)

return P_1.pop()

boolean isEmpty()

return P_1.isEmpty()

Esercizio 4.2. Realizzare una pila P utilizzando due code Q1 e Q2.

Svolgimento: Supponiamo di avere due code Q1 e Q2. La pila Q1 ci serve per mantenere la collezionedi oggetti, mentre Q2 serve come ausilio per le operazioni.

void push(Item x)

while(!Q_1.isEmpty())

Q_2.enqueue(Q_1.dequeue())

Q_1.enqueue(x)

while(!Q_2.isEmpty())

Q_1.enqueue(Q_2.dequeue())

Item pop(Item x)

return Q_1.dequeue()

boolean isEmpty()

return Q_1.isEmpty()

32

Page 33: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Chapter 5

Liste

5.1 Esercizi

Esercizio 5.1. Data una lista singola scorrendola una sola volta spezzarla a meta:

void split(List l, List *l1, List *l2)

Proof. Ipotizziamo una dichiarazione di lista come seguente

struct Node

int key; // chiave intera

struct Node* next;

typedef Node* List;

Il metodo viene invocato cosı, dove l e una lista esistente:

List l1,l2;

split(l,&l1,&l2);

Abbiamo due possibilita:

• possiamo fare in modo che l1 ed l2 puntino alla testa di due nuove liste create copiando il contenutodei record componenti la lista l;

• possiamo alterare la lista l e far puntare l1 al primo record di l, ed l2 al record di mezzo di l.

Scegliamo la seconda opzione, che comporta meno operazioni.

void split(List l, List *l1, List *l2)

List p1 = l, p2 = l;

List tail1;

while(p2 != NULL & p2->next != NULL)

tail1 = p1;

p1 = p1->next;

p2 = (p2->next)->next;

*l1 = l;

tail1->next = NULL;

*l2 = p1;

Esercizio 5.2. Realizzare una funzione

Lista union(Lista S1, Lista S2)

33

Page 34: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

che date due liste S1 e S2 i cui record non contengono campi chiave ripetuti, restituisce una lista S i cuirecord non contengono campi chiave ripetuti e contiene tutti e soli gli elementi di S1 ed S2.

Proof. Adottiamo una soluzione in cui viene creata una nuova lista contenente copie dei campi chiavedelle liste originarie.

Lista union(Lista S1, Lista S2)

List aux = (List)malloc(sizeof(struct Node));

List head = aux;

List tail = aux;

//copio nella nuova lista gli elementi di S1

//che non compaiono in S2

while(S1 != NULL)

tail = aux;

found = 0;

List p2 = S2;

while(p2 != NULL && found == 0)

if (S1->key == p2->key) found = 1;

p2=p2->next;

if (found == 0) aux->key = S1->key;

aux->next = (List)malloc(sizeof(struct Node));

aux = aux->next;

//copio gli elementi di S2 in coda alla nuova lista

while(S2 != NULL)

tail = aux;

aux->key = S2->key;

aux->next = (List)malloc(sizeof(struct Node));

aux = aux->next;

tail->next = NULL;

return head;

Esercizio 5.3. Realizzare una funzione

Lista union(Lista S1, Lista S2)

che date due liste S1 e S2 i cui record sono ordinati in maniera crescente secondo il campo chiave e nonsono ripetuti, restituisce una lista S i cui record sono ordinati in maniera crescente secondo il campochiave e non sono ripetuti e contiene tutti e soli gli elementi di S1 ed S2.

Proof. Adottiamo una soluzione in cui viene creata una nuova lista contenente copie dei campi chiavedelle liste originarie.

Lista union(Lista S1, Lista S2)

List aux = (List)malloc(sizeof(struct Node));

List head = aux;

List tail = aux;

while(S1 != NULL && S2 != NULL)

tail = aux;

if (S1->key < S2->key)

aux->key = S1->key;

S1=S1->next;

if (S1->key == S2->key)

aux->key = S1->key;

S1=S1->next;

34

Page 35: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

S2=S2->next;

if (S2->key < S1->key)

aux->key = S2->key;

S2=S2->next;

aux->next = (List)malloc(sizeof(struct Node));

aux = aux->next;

while(S1 == NULL && S2 != NULL)

tail = aux;

aux->key = S2->key;

S2=S2->next;

aux->next = (List)malloc(sizeof(struct Node));

aux = aux->next;

while(S2 == NULL && S1 != NULL)

tail = aux;

aux->key = S1->key;

S1=S1->next;

aux->next = (List)malloc(sizeof(struct Node));

aux = aux->next;

tail->next = NULL;

return head;

Esercizio 5.4. Trovare il numero di foglie ed il numero di nodi interni di un albero k-ario completod’altezza h.

Proof. Intanto precisiamo che un albero k-ario completo e d’altezza h si caratterizza per il fatto che ogninodo interno ha esattamente k figli e tutte le foglie hanno la stessa profondita. Un albero con solo laradice ha altezza 0. Il numero totale di nodi dell’albero e dato dalla somma dei nodi dei vari livelli, datodalla sommatoria

∑hi=0 k

i. L’ultimo addendo corrisponde al numero di foglie dell’albero, mentre tutti iprecedenti addendi danno il numero dei nodi interni. Dunque il numero di foglie e kh, ed il numero di

nodi interni e∑h−1i=0 k

i = 1−kh1−k .

Esercizio 5.5. Trovare l’altezza di un albero k-ario completo con n foglie.

Proof. Siccome sappiamo dal precedente esercizio un albero di altezza h ha n = kh foglie, allora h =logk n.

Esercizio 5.6. Dato un array v ordinato in senso crescente di n interi, il cui valore puo essere solo 0 e1, progettare un algoritmo efficiente, di tipo divide-et-impera, che restituisca il numero di occorrenze delnumero 1 in v. Calcolare la complessita al caso pessimo dell’algoritmo proposto indicando, e risolvendo,la corrispondente relazione di ricorrenza.

Proof. Osserviamo che, visto come una stringa, l’array v e della forma 0∗1∗.

int occorrenze1(int v[], int start, int end)

int pivot = (end-start)/2;

if

if (v[pivot] == 0)

return occorrenze1(v,pivot+1,end);

else

int left=0, right=0;

if (pivot-1>=start)

35

Page 36: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

left = occorrenze1(v,start,pivot-1);

if (pivot+1<=end)

right = occorrenze1(v,pivot+1,end);

return 1+ left+ right;

Esercizio 5.7. Progettare un algoritmo di costo Θ(n log n) (in termini di tempo di esecuzione), ricevutoin input un intero k e un array a, non ordinato, di n elementi distinti, restituisca il k-esimo elemento piupiccolo di a.

Proof. Possiamo ordinare l’array tramite mergeSort in-place (ovvero a viene modificato) e poi restituirea[k − 1].

36

Page 37: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Chapter 6

Alberi

6.1 Introduzione

Definizione 6.1. Un albero e una coppia T = (N,A) costituita da un insieme N di nodi e da un insiemeA ⊆ N ×N di coppie di nodi, dette archi.

In un albero, ogni nodo v (esclusa la radice) ha un solo padre tale che (u, v) ∈ A; ogni nodo, inoltre,puo avere un certo numero di figli w tali che (v, w) ∈ A, ed il loro numero e detto grado del nodo. Unnodo senza figli e chiamato foglia e tutti i nodi che non sono ne foglia ne radice sono detti nodi interni.

La profondita di un nodo e definita come segue:

• la radice ha profondita zero;

• se un nodo ha profondita k, i suoi figli avranno profondita k + 1.

I nodi che hanno lo stesso padre sono detti fratelli, e dunque avranno la stessa profondita. L’altezzadi un albero e definita come la massima profondita tra quelle delle varie foglie.

Un albero d-ario e un albero in cui tutti i nodi tranne le foglie hanno grado d; se tutte hanno medesimaprofondita, si dice che e completo.

Lo schema generale delle operazioni eseguibili su un albero e il seguente:

Dati: un insieme di nodi e un insieme di archi

Operazioni:

numNodi() → interoRestituisce il numero di nodi presenti nell’albero.

grado(nodo v) → interoRestituisce il numero di figli del nodo v.

padre(nodo v) → nodoRestituisce il padre del nodo v nell’albero, null se v e la radice.

figli(nodo v) → 〈nodo, nodo, ..., nodo〉Restituisce i figli del nodo v.

aggiungiNodo(nodo u) → nodoInserisce un nuovo nodo vcome figlio di u e lo restituisce. Se v e il primo nodo ad essere inseritonell’albero, diventa la radice.

aggiungiSottoalbero(albero a, nodo u) → alberoInserisce nell’albero il sottoalbero a in modo che la sua radice diventi figlia di u.

rimuoviSottoalbero(nodo v) → alberoStacca e restituisce l’intero sottoalbero radicato in v.

37

Page 38: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

6.2 Rappresentazioni

Le modalita di rappresentazione di un albero possono essere essenzialmente suddivise in due categorie:le rappresentazioni indicizzate e le rappresentazioni collegate.

Le prime, nonostante risultino essere di facile realizzazione, rendono difficoltoso l’inserimento e lacancellazione di nodi nell’albero, mentre le seconde risultano essere decisamente piu flessibili, nonostantesiano leggermente piu complesse da implementare.

6.2.1 Rappresentazioni indicizzate

Vettore padri

La piu semplice rappresentazione possibile per un albero T = (N,A) con n nodi e quella basata sulvettore padri : e un array di dimensione n le cui celle contengono coppie (info, parent), dove info e ilcontenuto informativo del nodo e parent il riferimento al padre (o null se si tratta della radice). Conquesta implementazione, da ogni nodo e possibile risalire al padre in tempo O(1), ma la ricerca dei figlirichiede tempo O(n).

Vettore posizionale

Consideriamo un albero d-ario completo con n nodi, dove d ≥ 2; un vettore posizionale e un array P didimensione n tale che P [v] contiene l’informazione associata al nodo v e i figli sono memorizzati nelleposizioni P [d · v + i], con 0 ≤ i ≤ d − 1. Da ciascun nodo e possibile risalire in tempo costante sia alproprio padre (indice bv/dc se v non e la radice), sia a uno qualsiasi dei propri figli.

6.2.2 Rappresentazioni collegate

Puntatori ai figli

Se ogni nodo dell’albero ha al piu grado d, e possibile mantenere in ogni nodo un puntatore a ciascunodei possibili figli (se il figlio non e presente, si imposta a null il riferimento).

Lista figli

Se il numero massimo di figli non e noto a priori, si puo mantenere per ogni nodo una lista di puntatoriai figli.

Primo figlio - fratello successivo

Variante della soluzione precedente, prevede di mantenere per ogni nodo un puntatore al primo figlio euno al fratello successivo (null se non e presente, rispettivamente, il figlio o fratello); per scandire tutti ifigli di un nodo, e sufficiente visitare il primo figlio e poi tutti i suoi fratelli.

6.3 Visite

1

2 3

4 5 6

Figure 6.1: Esempio di albero

38

Page 39: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

6.3.1 Visita in profondita

In una visita in profondita, si prosegue la visita dall’ultimo nodo lasciato in sospeso: puo essere realizzatamediante l’utilizzo di pile o, in maniera piu semplice, usando la ricorsione.

1 visitaSimmetrica(nodo r → void)

2 if (r != null)

3 visitaSimmetrica(figlio sinistro di r)

4 visita il nodo r

5 visitaSimmetrica(figlio destro di r)

6

7

Tre varianti classiche della visita in profondita sono le seguenti:

Visita in preordine: si visita prima la radice, poi vengono eseguite le chiamate ricorsive sul figliosinistro e destro (Figure 6.1 → 1, 2, 4, 3, 5, 6)

Visita simmetrica: si effettua prima la chiamata sul figlio sinistro, poi si visita la radice e infine siesegue la chiamata ricorsiva sul figlio destro (Figure 6.1 → 4, 2, 1, 5, 3, 6)

Visita in postordine: si effettuano prima le chiamate ricorsive sul figlio sinistro e destro, poi vienevisitata la radice (Figure 6.1 → 4, 2, 5, 6, 3, 1)

6.3.2 Visita in ampiezza

La visita in ampiezza e realizzata tramite l’uso di code e la sua caratteristica principale e il fatto che inodi vengono visitati per livelli: l’ordine di visita dell’albero rappresentato in Figure 6.1 e 1, 2, 3, 4, 5, 6.

6.4 Alberi binari di ricerca

Definizione 6.2. Un albero binario di ricerca e un albero binario che soddisfa le seguenti proprieta:

• ogni nodo v contiene un elemento elem(v) cui e associata una chiave chiave(v) presa da un dominiototalmente ordinato;

• le chiavi nel sottoalbero sinistro di v sono minori o uguali a chiave(v);

• le chiavi nel sottoalbero destro di v sono maggiori o uguali a chiave(v).

Un albero binario di ricerca e descritto dal seguente schema generale:

Dati: un albero binario di ricerca di altezza h e n nodi, ciascuno contenente coppie (elem, chiave).

Operazioni:

search(chiave k) → elemPartendo dalla radice, ricerca un elemento con chiave k, usando la proprieta di ricerca perdecidere quale sottoalbero esplorare (complessita O(h)).

insert(elem e, chiave k) → voidCrea un nuovo nodo v contenente la coppia (e, k) e lo aggiunge all’albero in posizione oppor-tuna, in modo da mantenere la proprieta di ricerca (complessita O(h)).

delete(elem e) → voidSe il nodo v contenente l’elemento e ha al piu un figlio, elimina v collegando il figlio all’eventualepadre, altrimenti scambia il nodo v con il suo predecessore ed elimina il predecessore (comp-lessita O(h)).

39

Page 40: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

6.5 Esercizi

Esercizio 6.1. Trovare l’altezza di un albero binario.

Svolgimento:

HEIGHT(x)

if (x == NIL)

return 0

return 1+MAX(HEIGHT(x.left),HEIGHT(x.right))

Esercizio 6.2. Trovare l’altezza di un albero k-ario realizzato con left child, right sibling.

Svolgimento:

HEIGHT(x)

if (x == NIL)

return 0

y := x.leftChild

height := 0

while (y != NIL)

a:=HEIGHT(y)

if (height < a)

height:= a

y := y.rightSibling

return 1+height

Esercizio 6.3. Scrivere un algoritmo per trovare il numero di foglie di un albero binario. Dimostrarnela correttezza per induzione. Calcolarne la complessita.

Svolgimento:

LEAVES(x)

if (x == NIL)

return 0

if (x.left == NIL AND x.right == NIL)

return 1

return LEAVES(x.left)+LEAVES(x.right)

Esercizio 6.4. Verificare se un albero binario e completo.

Svolgimento: Ricordiamo che un albero binario e completo se ogni nodo interno ha esattamente 2figli e tutte le foglie hanno la stessa profondita. Immaginiamo che l’algoritmo COMPLETE ritorni comerisultato un tipo coppia. Nel linguaggio C si puo simulare questo comportamento utilizzando parametripassati per indirizzo. Se c = (x, y) e un dato di tipo coppia, allora π1(c) = x e π2(c) = y.

COMPLETE(x)

if (x == NIL)

return (TRUE, 0)

if ((x.left == NIL AND x.right != NIL) OR (x.left != NIL AND x.right == NIL))

return (FALSE,1)

c_l = COMPLETE(x.left)

c_r = COMPLETE(x.right)

return (\pi_1(c_r) AND \pi_1(c_r) AND (\pi_2(c_l) == \pi_2(c_r)), 1+MAX(\pi_2(c_l),\pi_2(c_r)))

40

Page 41: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

L’albero x e completo sse π1(COMPLETE(x)) = TRUE.

Esercizio 6.5. Un nodo di un albero binario detto centrale se il numero di foglie del sotto-albero di cuiradice pari alla somma delle chiavi dei nodi appartenenti al percorso dalla radice al nodo stesso. Trovareil numero di nodi centrali in un albero binario.

Esercizio 6.6. Sia x un albero binario. Dato un certo livello k vogliamo stampare i nodi di quel livello.Qual’e la complessita dell’algoritmo rispetto a k?

Svolgimento:

PRINT-LEVEL(x,k,i)

if (x != NIL && i == k)

print(x)

if (x != NIL && i < k)

PRINT-LEVEL(x.left,k,i+1)

PRINT-LEVEL(x.right,k,i+1)

Per stampare i nodi del livello k bisogna invocare PRINT−LEV EL(x, k, 0). La complessita di PRINT−LEV EL(x, k, 0) e lineare nel numero di nodi dell’albero ristretto ai nodi di profondita alpiu k. Il caso

peggiore e quello in cui l’albero e completo: in tal caso i nodi di profondita alpiu k sono∑kj=0 2j = 2k+1−1.

Quindi la complessita e alpiu esponenziale in k, O(2k+1).

Ricordiamo che un BST A e un albero binario (memorizzato con una struttura a nodi linkati) taleche per ogni nodo x in A, ogni nodo y nel sottoalbero sinistro di x ed ogni nodo z nel sottoalbero destrodi x abbiamo che y.key ≤ x.key ≤ z.key.

Esercizio 6.7 (Appello del 03-02-09). Discutere la complessita asintotica dell’algoritmo di ricerca di unachiave in un albero BST con n nodi.

Svolgimento:

TREE-SEARCH(x, k)

if (x == NIL OR k == x.key)

return x

if (k < x.key)

return TREE-SEARCH(x.left, k)

else

return TREE-SEARCH(x.right, k)

Il tempo di calcolo e O(h), dove h e l’altezza dell’albero. Attenzione che la complessita in generale non eO(log n), visto che il caso peggiore e un albero a forma di linea che non contiene la chiave k. Alla peggiodunque il tempo di esecuzione e O(n), mentre se il BST e completo la complessita scende a O(log n).

Esercizio 6.8 (Appello del 05-02-10). Un nodo di un albero binario e detto centrale se il numero difoglie del sottoalbero di cui e radice e pari alla somma delle chiavi dei nodi appartenenti al percorso dallaradice al nodo stesso.

a. Scrivere una funzione efficiente in C che restituisca il numero di nodi centrali.

b. Discutere la complessita della soluzione trovata.

c. Se vogliamo modificare la funzione in modo che restituisca l’insieme dei nodi centrali che tipo distruttura dati si puo utilizzare per rappresentare l’insieme? La complessita dell’algoritmo deverimanere la stessa che nel caso (a).

Si deve utilizzare il seguente tipo per la rappresentazione di un albero binario:

41

Page 42: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

typedef struct Node

int key;

struct node * left;

struct node * right;

* Node;

Svolgimento:

int centrali(Node * x, int * count, int keysum)

int leaf_number = 0;

if (x != NULL)

if (x-> left == NULL && x->right == NULL)

if (keysum == 1) (*count)++;

return 1;

else

int left_leaf_number = centrali(x->left, count, keysum+(x->key));

int right_leaf_number = centrali(x->right, count, keysum+(x->key));

leaf_number = left_leaf_number+right_leaf_number;

if (keysum == leaf_number) (*count)++;

return leaf_number;

Se root e un puntatore alla radice dell’albero e count e una variabile intera, questa funzione va invocatacosı:

int leaves = centrali(root, &count, 0);

Alla fine ritroviamo in leaves il numero di foglie dell’albero e in count il numero di nodi centrali. Lacomplessita della nostra soluzione e Θ(n) dove n e il numero di nodi dell’albero.

6.6 Alberi AVL

Nel caso peggiore, l’altezza di un albero binario di ricerca puo essere proporzionale al numero n di nodi,mentre, se fosse bilanciato, avrebbe altezza logaritmica, migliorando l’efficienza delle operazioni; perrisolvere il problema, vengono usati gli alberi AVL.

Definizione 6.3. Un albero e bilanciato in altezza se le altezze dei sottoalberi sinistro e destro di ogninodo differiscono al piu di un’unita.

Definizione 6.4. Il fattore di bilanciamento β(v) di un nodo v e la differenza tra l’altezza del sottoalberosinistro e quella del sottoalbero destro di v:

β(v) = altezza(sin(v))− altezza(des(v)) (6.1)

Un albero AVL e un albero bilanciato in altezza e, oltre all’elemento e alla chiave, ciascun nodomantiene l’informazione sul fattore di bilanciamento. Per mantenere l’albero bilanciato a seguito dicancellazioni ed inserimenti, occorre operare, qualora risultasse necessario, delle rotazioni.

6.6.1 Ribilanciamento tramite rotazioni

Le operazioni di rotazione vengono effettuate su nodi sbilanciati, ossia nodi il cui fattore di bilanciamento,in valore assoluto, e maggiore o uguale a 2; si possono distinguere vari casi:

Sinistra - sinistra: si esegue quando un nodo ha coefficiente di bilanciamento +2 ed il figlio destro uncoefficiente pari a 0 o a +1 (in Figure 6.2 il nodo sbilanciato e quello con chiave 3).

Destra - destra: si esegue quando un nodo ha coefficiente di bilanciamento -2 ed il figlio sinistro uncoefficiente pari a 0 o -1 (in Figure 6.2 il nodo sbilanciato e quello con chiave 6).

42

Page 43: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Sinistra - destra: si esegue quando un nodo ha coefficiente di bilanciamento -2 e il figlio sinistro uncoefficiente pari a +1 (in Figure 6.2 il nodo sbilanciato e quello con chiave 3).

Destra - sinistra: si esegue quando un nodo ha coefficiente di bilanciamento +2 e il figlio destro uncoefficiente pari a -1 (in Figure 6.2 il nodo sbilanciato e quello con chiave 6).

Proprieta 6.1. Una rotazione SS, SD, DS o DD, applicata ad un nodo v con fattore di bilanciamento±2, fa decrescere di 1 l’altezza del sottoalbero radicato in v prima della rotazione.

Mentre l’operazione di ricerca si svolge esattamente come in un albero binario di ricerca, le operazionidi cancellazione e inserimento sono soggette a modifica:

Inserimento

• si crea un nuovo nodo e lo si inserisce nell’albero con lo stesso procedimento usato per i BST;

• si ricalcolano i fattori di bilanciamento che sono mutati in seguito all’inserimento (solo i fattoridi bilanciamento dei nodi nel cammino tra la radice e il nuovo elemento possono mutare epossono essere facilmente calcolati risalendo nel cammino dalla foglia verso la radice);

• se nel cammino compare un nodo con fattore di bilanciamento pari a ±2, occorre ribilan-ciare mediante rotazioni (si puo dimostrare che e sufficiente una sola rotazione per bilanciarel’albero).

Cancellazione

• si cancella il nodo con il medesimo procedimento usato nei BST;

• si ricalcolano i fattori di bilanciamento mutati in seguito all’operazione (solo i nodi nel camminotra la radice e il padre del nodo eliminato possono aver subito una modifica del fattore);

• per ogni nodo con fattore di bilanciamento pari a ±2, procedendo dal basso verso l’alto, siopera una rotazione (puo essere necessario eseguire piu rotazioni, in questo caso).

6.6.2 Alberi di Fibonacci

Definizione 6.5. Tra tutti gli alberi di altezza h bilanciati in altezza, un albero di Fibonacci ha il minimonumero di nodi.

Un albero di Fibonacci di altezza h puo essere costruito unendo, tramite l’aggiunta di una radice, unalbero di Fibonacci di altezza h− 1 e uno di altezza h− 2; e facile verificare che ogni nodo interno di unalbero di questo tipo ha fattore di bilanciamento pari a +1 (o -1, dipende dalla costruzione): studiamoora il rapporto tra numero di nodi ed altezza di un albero di Fibonacci.

Lemma 6.1. Sia Th un albero di Fibonacci di altezza h e sia nh il numero dei suoi nodi; risulta h =Θ(log nh)

Proof. Per dimostrare la tesi, proviamo prima che nh = Fh+3 − 1, per induzione su h.

Passo base: si ha h = 0 e n0 = 1 = 2− 1 = F3 − 1.

Ipotesi induttiva: supponiamo nk = Fk+3 − 1 per k < h.

Passo induttivo: sia h > 0; si ha:

nh = 1 + nh−1 + nh−2 = 1 + Fh+2 − 1 + Fh+1 − 1 = Fh+3 − 1

Poiche Fh = Θ(φh), con φ ≈ 1.618, possiamo concludere che h = Θ(log nh).

Corollario 6.1. Un albero AVL con n nodi ha altezza O(log n).

Proof. Sia h l’altezza dell’albero AVL; per dimostrare che h = O(log n) consideriamo l’albero di Fibonaccidi altezza h, avente nh nodi: per definizione di albero di Fibonacci si ha nh ≤ n e, per il lemma appenadimostrato, si ottiene il risultato voluto.

43

Page 44: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

4

3 6

2 5 7

1

4

2 6

1 5 73

(a) Rotazione SS

4

3 6

1 5 7

2

4

2 6

1 5 73

(b) Rotazione SD

5

3 6

2 4 8

1

5

3 7

2 6 84

7 1

(c) Rotazione DS

5

3 6

2 4 7

1

5

3 7

2 6 84

8 1

(d) Rotazione DD

Figure 6.2: Esempi di rotazione

44

Page 45: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Chapter 7

Heap e code di priorita

7.1 Heap

Definizione 7.1. Uno heap e un albero binario quasi completo che rispetta la proprieta heap definitacome segue:

• nel caso di min-heap, il padre ha associata una chiave minore o uguale alle chiavi di tutti i suoi figli;

• nel caso di max-heap, il padre ha associata una chiave maggiore o uguale alle chiavi associati ai suoifigli.

Solitamente uno heap viene rappresentato utilizzando un vettore (a partire dalla posizione di indice1) dove, per un generico nodo in posizione i, si ha:

• il padre in posizione bi/2c;

• il figlio sinistro in posizione 2 · i;

• il figlio destro in posizione 2 · i+ 1.

Lemma 7.1. Uno heap con n nodi ha altezza O(log n).

Proof. Sia h l’altezza dello heap con n nodi; poiche lo heap e completo almeno fino a profondita h− 1, e

un albero binario completo di profondita h− 1 ha 2h−12−1 = 2h− 1 nodi, segue che 2h− 1 < n; con semplici

passaggi algebrici, si giunge alla relazione h < log2(n+ 1) = O(log n).

Nel seguito faremo riferimento solo a max-heap, ma quanto detto (con opportune modifiche dovutealla condizione heap diversa) puo essere applicato anche a min-heap.

7.1.1 Costruzione

Per costruire un max-heap, si utilizza una funzione ausiliaria heapifyDown.Tale funzione verifica che il valore di A[i] sia maggiore di quello dei figli, se presenti, e, in caso

contrario, A[i] migra verso il basso fino a che non vale la proprieta heap; la complessita e O(h), dove h el’altezza dell’albero. La funzione per la costruzione dello heap e la seguente:

Per dimostrare la correttezza della funzione, usiamo il seguente invariante di ciclo:

∀k : i+ 1 ≤ k ≤ length(A), A[k] e radice di uno heap.

Inizializzazione: si ha i = length(A)/2; ∀k : i + 1 ≤ k ≤ length(A), A[k] e una foglia e dunque,banalmente, radice di uno heap.

Mantenimento: assumiamo che la proprieta valga all’inizio di una generica iterazione e dimostriamoche vale anche alla fine; si ricorda che, ad ogni passo, i viene decrementata, nonostante non siaesplicitamente indicato. La chiamata heapifyDown(A, i) fa diventare A[i] radice di uno heap,senza togliere questa proprieta agli altri: al termine dell’iterazione si ha che A[(i − 1) + 1], A[(i −1) + 2], ..., A[length(A)] sono radici di heap, ossia quanto volevamo dimostrare.

Terminazione: si ha i = 0 e che A[1], A[2], ..., A[length(A)] sono tutti radici di heap, dunque A e unoheap.

45

Page 46: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Complessita

Per il calcolo della complessita, ci servono le seguenti formule:

∞∑k=0

xk =1

1− x(7.1)

Proof.x0 = 1∞∑k=0

xk −∞∑j=1

xj = 1

∞∑k=0

xk −∞∑k=0

xk+1 = 1

∞∑k=0

xk − x ·∞∑k=0

xk = 1

(1− x) ·∞∑k=0

xk = 1

∞∑k=0

xk =1

1− x

∞∑k=0

k · xk =x

(1− x)2(7.2)

Proof.∞∑k=0

xk =1

1− x

d

dx

∞∑k=0

xk =d

dx

1

1− x∞∑k=0

k · xk−1 =1

(1− x)2

x ·∞∑k=0

k · xk−1 =x

(1− x)2

∞∑k=0

k · xk =x

(1− x)2

Per procedere, dobbiamo calcolare quante volte la funzione buildHeap richiama heapify; dividiamoi vertici in base all’altezza: per ogni altezza h ce ne sono al piu n

2h+1 . Per nodi alla stessa altezza h, lacomplessita di heapify e O(h); la complessita totale risulta essere:

blognc∑h=0

⌈ n

2h+1

⌉·O(h) = O

(n ·blognc∑h=0

⌈ h

2h+1

⌉)Sostituendo x = 1/2 nell’equazione (7.2) otteniamo:

∞∑h=0

⌈ h

2h+1

⌉=

1/2

(1− 1/2)2= 2

Segue che:

O

(n ·blognc∑h=0

⌈ h

2h+1

⌉)= O

(n ·

∞∑h=0

⌈ h

2h+1

⌉)= O(n)

46

Page 47: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

7.1.2 Realizzazione

Per realizzare le operazioni di inserimento e rimozione, risulta utile un’ulteriore funzione d’appoggio,simmetrica a heapifyDown.

void heapifyUp (int A[], int i)

if (i != 1 && A[i] < A[padre(i)])

swap(A[i], A[padre(i)])

heapifyUp(A, padre(i))

Inserimento: viene creato un nuovo nodo e inserito come foglia nella prima posizione libera del vettoreusato per realizzare lo heap; a questo punto, per ripristinare la proprieta heap, viene richiamata lafunzione heapifyUp sul nodo appena inserito. La complessita dell’operazione e O(log n).

Cancellazione: il nodo da rimuovere viene scambiato con l’ultimo elemento occupato del vettore; aquesto punto, non sapendo se il nodo appena scambiato debba scendere o salire nell’albero, vengonorichiamate su di esso entrambe le funzioni heapifyUp e heapifyDown per ripristinare la proprietaheap. La complessita dell’operazione, anche in questo caso, e O(log n).

7.2 Code di priorita

Le code di priorita possono essere realizzate usando degli heap: a seconda del fatto che sia usato un min-heap o un max-heap, si possono avere code a min-priorita e code a max-priorita. Una coda a min-prioritae descritta dal seguente schema generale:

Dati: un insieme S di n elementi di tipo elem a cui sono associate chiavi di tipo chiave prese da ununiverso totalmente ordinato.

Operazioni:

findMin() → elemRestituisce l’elemento di S con la chiave minima.

insert(elem e, chiave k) → voidAggiunge a S un nuovo elemento e con chiave K.

delete(elem e) → voidCancella da S l’elemento e.

deleteMin() → voidCancella da S l’elemento con chiave minima.

increaseKey(elem e, chiave d) → voidIncrementa della quantita d la chiave dell’elemento e in S.

decreaseKey(elem e, chiave d) → voidDecrementa della quantita d la chiave dell’elemento e in S.

Una coda a max-priorita, invece, al posto di funzioni per ricercare ed estrarre l’elemento con chiaveminima, fornira funzioni per ricercare ed estrarre quello con chiave massima.

47

Page 48: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

48

Page 49: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Chapter 8

Algoritmi di ordinamento

8.1 Selection sort

L’algoritmo di ordinamento per selezione opera nel modo seguente: supponiamo che i primi k elementisiano ordinati; l’algoritmo sceglie il minimo degli n − k elementi non ancora ordinati e lo inserisce inposizione k+ 1; partendo da k = 0 e iterando n volte il ragionamento, si ottiene la sequenza interamenteordinata.

void selectionSort (int A[])

for k = 0 to length(A) - 2

m = k + 1

for j = m + 1 to length(A)

if (A[j] < A[m])

m = j

swap(A[m], A[k + 1])

Complessita

L’estrazione del minimo (righe 2 - 4) richiede n− k − 1 confronti e, poiche il ciclo esterno viene eseguiton− 1 volte, si ha:

T (n) =

n−2∑k=0

(n− k − 1) =

n−1∑i=1

i = Θ(n2)

8.2 Insertion sort

L’algoritmo di ordinamento per inserzione opera in modo simile al precedente: supponiamo che i primi kelementi siano ordinati; l’algoritmo prende il (k+ 1)-esimo elemento e lo inserisce nella posizione correttarispetto ai k elementi gia ordinati; partendo da k = 0 ed iterando n volte il ragionamento, il vettore vienecompletamente ordinato.

void insertionSort (int A[])

for k = 1 to length(A) - 1

value = A[k + 1]

j = k

while (j > 0 && A[j] > value)

A[j + 1] = A[j]

j--

A[j + 1] = value

49

Page 50: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Complessita

Le righe 4 - 6 individuano la posizione in cui l’elemento va inserito, eseguendo al piu k confronti; poicheil ciclo esterno viene eseguito n− 1 volte, si ha:

T (n) =

n−1∑k=1

k = O(n2)

8.3 Bubble sort

L’algoritmo di ordinamento a bolle opera una serie di scansioni del vettore: in ogni scansione sonoconfrontate coppie di elementi adiacenti e viene effettuato uno scambio se i due elementi non rispettanol’ordinamento; se durante una scansione non viene eseguito alcuno scambio, allora il vettore e ordinato.

void bubbleSort (int A[])

for i = 1 to length(A) - 1

for j = 2 to (n - i + 1)

if (A[j - 1] > A[j])

swap(A[j - 1], A[j])

if (non ci sono stati scambi)

break

Lemma 8.1. Dopo l’i-esima scansione, gli elementi A[n− i+ 1], ..., A[n] sono correttamente ordinati eoccupano la loro posizione definitiva, ovvero ∀h, k con 1 ≤ h ≤ k ∧n− i+ 1 ≤ k ≤ n, risulta A[h] ≤ A[k].

Proof. Procediamo per induzione sul numero i dell’iterazione.

Caso base: si ha i = 1; dopo la prima scansione, l’elemento massimo di A ha raggiunto l’n-esimaposizione, quindi il passo base e facilmente verificato.

Ipotesi induttiva: supponiamo che l’enunciato valga per le prime i− 1 scansioni.

Passo induttivo: verifichiamo la validita della proprieta dopo l’i-esima scansione; al termine di talescansione, il massimo degli elementi A[1], ..., A[n − i + 1] avra raggiunto la posizione n − i + 1 equindi, per ogni h < n − i + 1, risulta A[h] ≤ A[n − i + 1]; combinando questa osservazione conl’ipotesi induttiva, si puo verificare facilmente la validita dell’enunciato.

Complessita

Per il lemma appena dimostrato, dopo al piu n−1 cicli il vettore e ordinato e, nel caso peggiore, all’i-esimascansione vengono eseguiti n− i confronti; si ottiene quindi:

T (n) =

n−1∑i=1

(n− i) =

n−1∑j=1

j = O(n2)

8.4 Heap sort

L’algoritmo di ordinamento heap sort, come dice il nome, si basa sull’utilizzo di una struttura dati ditipo heap.

50

Page 51: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

void heapSort (int A[])

buildHeap(A)

for i = length(A) - 1 downto 1

swap(A[i], A[1])

heapifyDown(A[1..(i - 1)], 1)

Complessita

La funzione buildHeap ha complessita O(n), mentre heapifyDown, che viene richiamata n volte, hacomplessita O(log n); in totale si ha:

T (n) = O(n) + n ·O(log n) = O(n · log n)

8.5 Merge sort

L’algoritmo di ordinamento per fusione si basa sulla tecnica del divide et impera:

Divide: si divide il vettore in due parti di uguale dimensione; se ha un numero dispari di elementi, unadelle due parti conterra un elemento in piu.

Impera: supponendo di avere le due sottosequenze ordinate, si fondono in una sola sequenza ordinata.

Complessita

La complessita della funzione ausiliaria merge e O(n); la relazione di ricorrenza e la seguente:

T (n) = 2 · T (n/2) +O(n)

Applicando il secondo caso del teorema fondamentale, si ottiene:

T (n) = Θ(n · log n)

Per quanto riguarda lo spazio di memoria, mergeSort non opera in loco e pertanto ha un’occupazionedi memoria pari a 2 · n.

8.6 Quicksort

Anche questo tipo di algoritmo segue un approccio di tipo divide et impera:

Divide: sceglie un elemento x della sequenza (il perno), partiziona la sequenza in due sottosequenzecontenenti, rispettivamente, gli elementi minori o uguali a x e gli elementi maggiori di x, e ordinaricorsivamente le due sottosequenze.

Impera: concatena le sottosequenze ordinate.

L’invariante della procedura partition e il seguente:

Proprieta 8.1. In ogni istante, gli elementi A[i], ..., A[inf − 1] sono minori o uguali al perno, mentre glielementi A[sup+ 1], ..., A[f ] sono maggiori del perno.

51

Page 52: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Complessita

L’algoritmo ordina un vettoreA di dimensione n suddividendolo in due sottovettori, A1 eA2, di dimensionia e b tali che a + b = n − 1, ed ordinando ricorsivamente A1 e A2; poiche la partizione richiede n − 1confronti, si puo scrivere la seguente relazione di ricorrenza:

T (n) = T (a) + T (b) + n− 1

Nel caso peggiore, si ha che ad ogni passo viene scelto come perno l’elemento piu piccolo (o piu grande)della porzione di vettore considerato, riducendo la relazione di ricorrenza a:

T (n) = T (n− 1) + n− 1 = O(n2)

Dal risultato sembra che quickSort sia un algoritmo inefficiente; l’idea per migliorarlo consistenell’usare la randomizzazione. Supponiamo di scegliere il perno come il k-esimo elemento di A, dovek e scelto a caso: per calcolare il numero atteso di confronti, bisogna calcolare la somma dei tempi diesecuzione pesandoli in base alla probabilita di fare una certa scelta casuale; in questo caso, la scelta e ilvalore di k e la probabilita di scegliere il k-esimo elemento come perno, ∀k, 1 ≤ k ≤ n e 1/n. Otteniamola seguente relazione di ricorrenza:

T (n) =

n−1∑a=0

1

n· (T (a) + T (n− a− 1) + n− 1) = n− 1 +

n−1∑a=0

2

n· T (a) (8.1)

Dimostriamo, usando il metodo di sostituzione, che T (n) = O(n · log n), ossia che esiste una costanteα > 0 tale per cui C(n) ≤ α · n · log n per ogni n ≥ n0, n0 > 0.

Passo base: si ha n = 1; T (1) = 0 = α · (1 · log 1) per ogni α.

Ipotesi induttiva: supponiamo che esista α tale per cui T (i) ≤ α · i · log i per i < n.

Passo induttivo: usando l’ipotesi induttiva nella relazione 8.1 e la definizione di somme integrali, siottiene:

T (n) = n−1+

n−1∑i=0

2

n·T (i) ≤ n−1+

n−1∑i=0

2

n·α·i·log i = n−1+

2 · αn·n−1∑i=2

i·log i ≤ n−1+2 · αn·∫ n

2

x·log xdx

Procediamo usando il metodo di integrazione per parti:

T (n) ≤ n−1 +2 · αn·(n2 · log n

2− n

2

4+ 2 · ln 2 + 1

)= n−1 +α ·n · log n−α · n

2−O(1) ≤ α ·n · log n

quando n− 1 < α · (n/2), ossia per α ≥ 2.

Possiamo dunque concludere che l’algoritmo quickSort, su un input di dimensione n ha complessitaO(n2) nel caso peggiore, ma il numero atteso di confronti e O(n · log n).

8.7 Counting sort

Si tratta di un algoritmo per ordinare vettori di interi di n elementi compresi nell’intervallo [1, k].

Complessita

Il primo ciclo ha complessita O(k), il secondo O(n) e il terzo, nonostante sia costituito da due cicliinnestati, e anch’esso O(n); per rendersene conto, basta osservare che il tempo necessario per eseguire glin incrementi dev’essere uguale a quello necessario per gli n decrementi, e gli incrementi sono eseguiti dalsecondo ciclo. In totale la complessita risulta essere:

T (n) = O(n+ k)

L’algoritmo countingSort e assai efficiente se k = O(n), mentre e preferibile usarne altri all’aumentaredell’ordine di grandezza di k; si osservi, inoltre, che la memoria occupata e anch’essa O(n+ k).

52

Page 53: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

8.8 Radix sort

Si tratta di un algoritmo per ordinare interi in tempo lineare, quando l’intervallo dei numeri che pos-sono essere presenti nel vettore e troppo grande per pensare di utilizzare il countingSort; consistenell’ordinare, ad ogni ciclo, in base all’i-esima cifra, partendo da quella meno significativa fino a quellapiu significativa.

Complessita

Sia k il valore piu grande presente nel vettore; l’algoritmo esegue log10 k chiamate di bucketSort, ciascunadelle quali ha costo O(n), per un totale di O(n · log k); e possibile aumentare il valore della base usata nelbucketSort, senza pero aumentare significativamente il tempo di esecuzione, come afferma il seguenteteorema.

Teorema 8.1. Usando come base per il bucketSort un valore b = Θ(n), l’algoritmo radixSort ordinan interi in [1, k] in tempo

O

(n ·

(1 +

log k

log n

))

Proof. Ci sono logb k = O(logn k) passate di bucketSort, ciascuna delle quali dal costo O(n): il tempototale e O(n · logn k) = O(n · log k/ log n), per le regole del cambiamento di base dei logaritmi; perconsiderare il caso k < n, aggiungiamo O(n) alla complessita, che e il tempo richiesto per leggere lasequenza. Il risultato della somma e quanto si voleva dimostrare.

8.9 Limitazione inferiore per algoritmi basati sul confronto

Usiamo la seguente proprieta per stabilire la limitazione:

Proprieta 8.2. Il numero di confronti fatti dall’algoritmo A nel caso peggiore e pari all’altezza dell’alberodi decisione, ovvero alla lunghezza del piu lungo cammino dalla radice ad una foglia.

Lemma 8.2. Un albero di decisione per l’ordinamento di n elementi contiene almeno n! foglie.

Proof. Ad ogni foglia dell’albero di decisione non ci sono piu confronti da effettuare, dunque corrispondead una soluzione del problema dell’ordinamento; ogni soluzione corrisponde, a sua volta, ad una permu-tazione degli n elementi da ordinare, quindi l’albero deve contenere un numero di foglie pari almeno alnumero di permutazioni degli n elementi da ordinare, ossia n! foglie.

Lemma 8.3. Sia T un albero binario in cui ogni nodo interno ha esattamente 2 figli e sia k il numerodelle sue foglie: l’altezza e almeno log2 k.

Proof. Definiamo h(k) come l’altezza di un albero binario con k foglie (con 2 figli per ogni nodo interno)e dimostriamo il lemma per induzione su k.

Caso base: si ha k = 1; si tratta, dunque, di un albero con un solo nodo, quindi l’altezza e 0 ≥ log2 1.

Ipotesi induttiva: assumiamo che h(i) ≥ log2 i per i < k.

Passo induttivo: poiche uno dei sottoalberi ha almeno la meta delle foglie, si ha:

h(k) ≥ 1 + h(k

2

)≥ 1 + log2

(k2

)= 1 + log2 k − log2 2 = log2 k

come volevasi dimostrare.

Teorema 8.2. Il numero di confronti necessari per ordinare n elementi nel caso peggiore e Ω(n · log n).

53

Page 54: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Proof. Per il lemma 8.2, il numero di foglie di un albero di decisione e almeno n! e, per la proprieta 8.2,il numero di confronti necessari per l’ordinamento e, nel caso peggiore, pari all’altezza dell’albero, ossia≥ log n! per il lemma 8.3. La disuguaglianza di De Moivre - Stirling afferma che, per n sufficientementegrande, si ha:

√2 · π · n ·

(ne

)n≤ n! ≤

√2 · π · n ·

(ne

)n·(

1 +1

12 · n− 1

)Si ha dunque:

n! ≈√

2 · π · n ·(ne

)nda cui:

log n! ≈ n · log n− 1.4427 · n− 1

2· log n+ 0.826

Da questa relazione segue direttamente la limitazione inferiore che si voleva dimostrare.

54

Page 55: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Chapter 9

Tabelle hash

Sono strutture dati realizzate mediante vettori che permettono, nel caso medio, di eseguire operazioniin tempo costante. Sia U l’universo delle chiavi associabili agli elementi che vogliamo memorizzare; nelcaso in cui U non sia l’insieme di numeri naturali [0,m− 1], l’utilizzo di tavole ad accesso diretto (ossiatavole che usano direttamente la chiave come indice per reperire l’elemento nella tabella) risulta troppocostoso, a causa del fattore di carico troppo basso: per questo motivo vengono usate le funzioni hash perla trasformazione delle chiavi in indici.

Definizione 9.1. Il fattore di carico di una tavola e definito come il rapporto α = n/m tra il numero ndi elementi in essa memorizzati e la sua dimensione m.

Definizione 9.2. Una funzione hash e una funzione h : U → 0, ...,m− 1 che trasforma chiavi in indicidi una tavola.

Definizione 9.3. Una funzione hash h e perfetta se e iniettiva, ovvero ∀u, v ∈ U, u 6= v ⇒ h(u) 6= h(v).

Affinche una funzione hash sia perfetta, occorre che |U | ≤ m, ossia ci dev’essere spazio per tantielementi quante sono le chiavi possibili: questo comporta un enorme spreco di memoria se l’insieme dellechiavi e molto grande. Se una funzione hash non e perfetta, allora potrebbe verificarsi una collisione,ossia si possono avere piu chiavi diverse con lo stesso valore associato: per risolvere il problema, occorreoperare delle strategie di risoluzione delle collisioni, che hanno lo svantaggio di ridurre le prestazioni.

9.1 Definizione di funzioni hash

Definizione 9.4. SiaQ(i) =

∑k:h(k)=i

P (k)

la probabilita che, scegliendo una chiave, questa finisca nella cella i; una funzione hash h gode dellaproprieta di uniformita semplice se, ∀i ∈ 0, ...,m− 1,

Q(i) =1

m

Per definire funzioni hash con buone caratteristiche di uniformita, con l’assunzione che ogni chiaveabbia la stessa probabilita di essere scelta, si usano spesso le seguenti tecniche.

Metodo della divisione: il metodo calcola il resto della divisione della chiave k per m, dove m e ladimensione della tabella hash; sebbene nella maggior parte dei casi si hanno buoni risultati, in altripotrebbero verificarsi molte collisioni: la bonta del metodo dipende dalla scelta di m, che sarebbepreferibile fosse un numero primo vicino ad una potenza di due, e dal fatto che la funzione hashdovrebbe dipendere da tutti i bit della chiave.

Metodo del ripiegamento: consiste nel dividere la chiave k in l parti e definire la funzione hash comel’applicazione di una funzione f , con codominio 0, ...,m− 1, sulle parti di chiave ottenute con ladivisione; ossia:

h(k) = f(k1, k2, ..., kl)

55

Page 56: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

9.2 Risoluzione delle collisioni

9.2.1 Liste di collisione

Questo metodo consiste nell’associare a ciascuna cella della tabella hash una lista di chiavi, detta lista dicollisione, di lunghezza media pari al fattore di carico α; per questo motivo, assumendo che la funzione dihashing goda della proprieta di uniformita semplice, si ha che il tempo medio necessario per un’operazionedi ricerca o eliminazione e O(1 + α), mentre l’inserimento puo essere realizzato in tempo O(1).

9.2.2 Indirizzamento aperto

Nel caso in cui la posizione h(k) in cui inserire una chiave k sia gia occupata, il metodo prevede diposizionarla in un’altra cella vuota, anche se quest’ultima potrebbe spettare di diritto ad un’altra chiave.Le operazioni vengono realizzate come segue:

Inserimento:

• se v[h(k)] e vuota, inserisci la coppia (el, k) in tale posizione;

• altrimenti, a partire da h(k), ispeziona le celle della tabella secondo una sequenza opportuna diindici c(k, 0), c(k, 1), ..., c(k,m−1) e inserisci nella prima cella vuota; la sequenza, chiaramente,deve contenere tutti gli indici 0, ...,m− 1.

Ricerca:

• se, durante la scansione delle celle, ne viene trovata una con la chiave cercata, restituiscil’elemento trovato;

• altrimenti, se si arriva a una cella vuota o si e scandita l’intera tabella senza successo, restituiscinull.

Cancellazione: affinche la ricerca con il metodo appena descritto funzioni, occorre adottare una strategiaparticolare per la cancellazione, ossia utilizzare un valore speciale canc nel campo el dell’elementoche si vuole rimuovere: in particolare, l’inserimento trattera tale cella come vuota e si fermera sudi essa, mentre la ricerca la oltrepassera.

Le prestazioni delle operazioni implementate dipendono dalla particolare funzione c(k, i) usata, ossiadal tipo di scansione scelto:

Scansione lineare:c(k, i) = (h(k) + i) mod m con 0 ≤ i < m

Dopo un certo numero di inserimenti, tendono a formarsi degli agglomerati sempre piu lunghi di cellepiene, che comportano un decadimento delle prestazioni; si parla del problema di di agglomerazioneprimaria.

Scansione quadratica:

c(k, i) =⌊h(k) + c1 · i+ c2 · i2

⌋mod m, con 0 ≤ i < m e c1 e c2 opportuni

Nonostante la scansione quadratica distribuisca le chiavi in modo da evitare l’agglomerazione pri-maria, ogni coppia di chiavi k1 e k2 con h(k1) = h(k2) continua a generare la stessa sequenza discansione; questo da luogo all’agglomerazione secondaria.

Hashing doppio:c(k, i) = bh1(k) + i · h2(k)c mod m

con h1 e h2 funzioni hash distinte e m e h2(k) primi tra loro. Si tratta di un metodo che permettedi eliminare virtualmente il fenomeno dell’agglomerazione, facendo dipendere dalla chiave anche ilpasso dell’incremento dell’indice usando una seconda funzione hash.

Complessita

Nell’ipotesi che le chiavi associate agli elementi di una tavola hash siano prese dall’universo delle chiavicon probabilita uniforme, il numero medio di passi richiesto da un’operazione di ricerca (contando anchele celle marcate come canc) e descritto nella seguente tabella:

56

Page 57: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Esito ricerca Scansione lineare Scansione quadratica / Hashing doppio

Chiave trovata 12 + 1

2·(1−α) − 1α · ln(1− α)

Chiave non trovata 12 + 1

2·(1−α)21

1−α

57

Page 58: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

58

Page 59: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Chapter 10

Tecniche algoritmiche

10.1 Divide et impera

Si tratta di una tecnica gia incontrata in precedenza, utilizzata, ad esempio, dagli algoritmi di ordina-mento mergeSort e quickSort; il principio su cui si basa questa tecnica consiste nel dividere i dati iningresso in un certo numero di sottoinsiemi (divide), risolvere ricorsivamente il problema sui sottoinsiemie ricombinare le sottosoluzioni cos ottenute per ottenere la soluzione del problema originario (impera).

10.2 Programmazione dinamica

Si tratta di una tecnica bottom-up introdotta, in maniera informale, con l’algoritmo fibonacciIterativo,che si basa sull’utilizzo di una tabella per memorizzare le soluzioni dei sottoproblemi incontrati: inquesto modo, qualora si dovesse trovare un sottoproblema gia risolto, si puo usare la tabella per ricavarnevelocemente la soluzione, invece di ricalcolarla. In maniera del tutto generale, si puo descrivere la tecnicadi programmazione dinamica nel modo seguente:

1. identifichiamo dei sottoproblemi del problema originario ed utilizziamo una tabella per memorizzarei risultati intermedi ottenuti;

2. all’inizio, definiamo i valori iniziali di alcuni elementi della tabella, corrispondenti ai sottoproblemipiu semplici;

3. al generico passo, avanziamo in modo opportuno sulla tabella calcolando il valore della soluzionedi un sottoproblema (corrispondente ad un dato elemento della tabella) in base alla soluzione deisottoproblemi precedentemente risolti;

4. alla fine, restituiamo la soluzione del problema originario, che e stata memorizzata in un particolareelemento della tabella.

Esempio 10.1. Vogliamo risolvere il problema riguardante il calcolo della distanza tra due stringhe dicaratteri: siano X = x1x2...xm e Y = y1y2...yn due stringhe di caratteri, rispettivamente di lunghezza me n; possiamo definire il costo della trasformazione di X in Y come il numero di operazioni da apportarealla stringa X per ottenere Y . Le possibili operazioni che possiamo compiere sono:

• inserisci(a): inserisci il carattere a nella posizione corrente della stringa;

• cancella(a): cancella il carattere a dalla posizione corrente della stringa;

• sostituisci(a, b): sostituisci il carattere a con il carattere b nella posizione corrente della stringa.

Assumendo che il costo di ciascuna operazione sia 1, possiamo definire il costo della trasformazionetra X e Y come la somma di tutti i costi pagati per compiere le operazioni di trasformazione da X in Y ;la distanza tra due stringhe X e Y sara il costo minimo di trasformazione di X in Y .

Indichiamo con δ(X,Y ) la distanza tra le stringhe X e Y ; inoltre, data una stringa X, definiamo ilprefisso di X fino al carattere i-esimo come la stringa Xi = x1x2...xi se 1 ≤ i ≤ m, la stringa vuotaX0 = ∅ se i = 0. Anziche risolvere il problema generale, proviamo a considerare i sottoproblemi P (i, j),ovvero trovare la distanza δ(Xi, Yj) tra il prefisso Xi e il prefisso Yj :

59

Page 60: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

• alcuni sottoproblemi sono particolarmente semplici: la soluzione del sottoproblema P (0, j) e imme-diata, in quanto e sufficiente inserire, uno dopo l’altro, i j caratteri di Yj e dunque si ha δ(X0, Yj) = j;analogamente, la soluzione del sottoproblema P (i, 0) consiste nel cancellare, uno dopo l’altro, gli icaratteri di Xi e dunque si ha δ(Xi, Y0) = i;

• il problema che vogliamo risolvere e il sottoproblema P (m,n), ossia consiste nel calcolo della dis-tanza δ(Xm, Yn).

Ci manca solo un passo per poter scrivere l’algoritmo: come calcolare il valore della soluzione delsottoproblema P (i, j) in funzione della soluzione dei sottoproblemi precedentemente risolti; chiaramenteci sono varie possibilita, a seconda dei valori di xi e yj . In particolare, se xi = yj , il costo minimo pertrasformare Xi in Yj e pari al costo minimo per trasformare Xi−1 in Yj−1; definendo D come la matricein cui vengono salvati i risultati dei sottoproblemi, si ha D[i, j] = D[i − 1, j − 1]. Invece, se xi 6= yj ,dobbiamo distinguere in base all’ultima operazione eseguita per trasformare Xi in Yj :

• inserisci(yj): il costo minimo per la trasformazione e dato dal costo ottimo per trasformare Xi

in Yj−1, piu 1 per l’inserimento del carattere yj ; si ha dunque:

D[i, j] = D[i, j − 1] + 1

• cancella(xi): il costo minimo per la trasformazione e dato dal costo ottimo per trasformare Xi−1

in Yj , piu 1 per la cancellazione del carattere xi; si ha dunque:

D[i, j] = D[i− 1, j] + 1

• sostituisci(xi, yj): il costo minimo per la trasformazione e dato dal costo ottimo per trasformareXi−1 in Yj−1, piu per la sostituzione del carattere xi con yj ; si ha dunque:

D[i, j] = D[i− 1, j − 1] + 1

Le precedenti relazioni assumono che sia nota l’ultima operazione utilizzata per la trasformazionedi Xi in Yj , anche se in realta non e cos; tuttavia sono possibili solo tre tipi di operazione e, dunque,dev’essere necessariamente usata una di esse: per trovare la scelta ottima, quindi, basta calcolare i valorirelativi alle tre operazioni e scegliere il migliore. La relazione che lega la soluzione di un problema aquella di alcuni sottoproblemi e la seguente:

D[i, j] =

D[i− 1, j − 1] se xi = yj

1 + min D[i, j − 1], D[i− 1, j], D[i− 1, j − 1] se xi 6= yj

La tabella delle distanze mantenuta dall’algoritmo, per la trasformazione della stringa RISOTTO nellastringa PRESTO, e la seguente:

P R E S T O0 1 2 3 4 5 6

R 1 1 1 2 3 4 5I 2 2 2 2 3 4 5S 3 3 3 3 2 3 4O 4 4 4 4 3 3 3T 5 5 5 5 4 3 4T 6 6 6 6 5 4 4O 7 7 7 7 6 5 4

L’algoritmo e il seguente:

10.3 Paradigma greedy

Si tratta di una tecnica tipicamente usata per risolvere problemi di ottimizzazione; nella situazione piugenerale, in un problema di tale tipo avremo:

60

Page 61: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

• un insieme di possibili candidati;

• l’insieme dei candidati gia utilizzati;

• una funzione ammissibile che verifica se un insieme di candidati fornisce una soluzione (anche nonottima) al problema;

• una funzione ottimo che verifica se un insieme di candidati fornisce una soluzione ottima al prob-lema;

• una funzione seleziona per estrarre un elemento dall’insieme dei candidati possibili non ancoraesaminati;

• una funzione obiettivo che fornisce il valore di una soluzione.

Per risolvere il problema, occorre trovare un insieme di candidati che:

• e una soluzione;

• ottimizza il valore della funzione obiettivo.

Un algoritmo greedy generico puo essere schematizzato come segue:

Esempio 10.2. Consideriamo il problema del resto in un distributore automatico: vogliamo scrivereun algoritmo goloso per determinare l’insieme di monete da restituire per fare in modo che il numero dimonete sia minore possibile; avremo:

• l’insieme dei candidati possibili e l’insieme delle monete del distributore;

• la funzione ammissibile restituisce vero se il valore delle monete nell’insieme scelto non e superioreal resto che dev0essere restituito;

• la funzione ottimo restituisce vero se il valore delle monete dell’insieme scelto e pari al resto daerogare;

• la funzione seleziona sceglie la moneta di valore maggiore tra quelle ancora da considerare;

• la funzione obiettivo restituisce il numero di monete della soluzione;

• la funzione valore restituisce il valore totale delle monete nell’insieme considerato.

Il codice e il seguente:

61

Page 62: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

62

Page 63: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Chapter 11

Grafi

11.1 Definizioni preliminari

Definizione 11.1. Un grafo G = (V, E) consiste di:

• un insieme V di vertici ;

• un insieme E di coppie di vertici, detti archi

Definizione 11.2. Un grafo si dice non orientato se E rappresenta una relazione simmetrica in V , ossia(u, v) ∈ E ⇔ (v, u) ∈ E, altrimenti si dice orientato; nel primo caso si ha |E| ≤ n · (n− 1)/2, mentre nelsecondo |E| ≤ n2.

Definizione 11.3. Dato un grafo G = (V,E), G′ = (V ′, E′) e sottografo di G se V ′ ⊆ V e E′ ⊆E ∩ (V × V ′).

Definizione 11.4. Dato un grafo G = (V,E), G′ = (V ′, E′) e sottografo indotto di G se V ′ ⊆ V eE′ = E ∩ (V × V ′) (ossia, se contiene tutti e soli gli archi presenti in E i cui vertici appartengonoentrambi a V ′).

Definizione 11.5. Dato G = (V,E), un cammino in G e una sequenza di vertici π = 〈x0, x1, ..., xk〉 taliche (xi, xi+1) ∈ E,∀i = 0..k− 1; la lunghezza del cammino e pari al numero di archi che lo compongono.π si dice cammino semplice se i 6= j ⇒ xi 6= xj∀i, j = 0..k.

Definizione 11.6. Il vertice v si dice raggiungibile da u se esiste un cammino π tale che x0 = u e xk = v.

Definizione 11.7. Dato un cammino π, un sottocammino e una sequenza di vertici 〈xi, xi+1, ..., xj〉 con0 ≤ i ≤ j ≤ k.

Definizione 11.8. Un ciclo e un cammino dove x0 = xk; un ciclo si dice semplice se tutti i verticiintermedi sono distinti.

Definizione 11.9. La distanza δ(u, v) tra due vertici u e v e il numero minimo di archi di un qualsiasicammino da u a v; se v non e raggiungibile da u, allora δ(u, v) =∞.

Definizione 11.10. Se un cammino π da u a v e tale che length(π) = δ(u, v), allora π e un camminominimo.

Definizione 11.11. Un grafo non orientato G = (V,E) e connesso se, per ogni u, v ∈ V , esiste uncammino da u a v.

Definizione 11.12. Sia G = (V,E) un grafo non orientato; V ′ ⊆ V e componente connessa se:

• il sottografo indotto da V ′ e connesso;

• se V ′′ ⊆ V induce un sottografo connesso e V ′ ⊆ V ′′, allora V ′ = V ′′ (vincolo di massimalita).

Definizione 11.13. Un albero libero e un grafo non orientato, connesso e aciclico.

Proprieta 11.1. Sia G = (V,E) un albero libero, con |V | = n e |E| = m: allora m = n− 1.

63

Page 64: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Proof. Procediamo per induzione su n.

Caso base: si ha n = 1, ossia l’albero con un nodo (e nessun arco); si ha m = 0 = n− 1.

Ipotesi induttiva: assumiamo valida la proprieta per k < n.

Passo induttivo: sia n > 1; prendiamo v ∈ V e consideriamo il sottografo indotto da V − v, ossiaG′ = (V ′, E′) con V ′ = V − v e E′ = E ∩ (V ′ × V ′). Siano V1, V2, ..., Vk le componenti connessedi G′; si ha n1 +n2 + ...+nk = n− 1, con ni la cardinalita di Vi. Vi e connessa per definizione ed eaciclica, essendo sottografo indotto di un grafo aciclico; inoltre |Vi| < n, quindi posso usare l’ipotesi,ossia mi = ni − 1. Da ciascuna componente connessa ci dev’essere un arco che la congiunge a v,affinche il grafo di partenza sia un albero libero; si ha:

|E| =k∑

1=1

mi + k =

k∑i=1

(ni − 1) + k =

k∑i=1

ni −k∑i=1

1 + k = n− 1− k + k = n− 1

come volevasi dimostrare.

Definizione 11.14. Sia G = (V,E) un grafo non orientato: il grado di un vertice u ∈ V e definito come

deg(u) = |v ∈ V : (u, v) ∈ E|

Sia ora G = (V,E) un grafo orientato: il grado entrante e il grado uscente di un vertice u ∈ V sonodefiniti, rispettivamente, come

degin(u) = |v ∈ V : (v, u) ∈ E|degout(u) = |v ∈ V : (u, v) ∈ E|

Lemma 11.1. Sia G = (V,E) un grafo non orientato; si ha:∑u∈V

deg(u) = 2 · |E|

Sia ora G = (V,E) un grafo orientato; si ha:∑u∈V

degin(u) = |E|∑u∈V

degout(u) = |E|

11.2 Rappresentazione di grafi

Una struttura dati di tipo grafo e descritta dal seguente schema generale:

Dati: un insieme di vertici (di tipo vertice) e di archi (di tipo arco).

Operazioni:

numVertici() → interoRestituisce il numero di vertici presenti nel grafo.

numArchi() → interoRestituisce il numero di archi presenti nel grafo.

grado(vertice v) → interoRestituisce il numero di archi incidenti sul vertice v.

archiIncidenti(vertice v) → 〈arco, arco, ..., arco〉Restituisce, uno dopo l’altro, gli archi incidenti sul vertice v.

estremi(arco e) → 〈vertice, vertice〉Restituisce gli estremi x e y dell’arco e = (x, y).

opposto(vertice x, arco e) → verticeRestituisce y, l’estremo dell’arco e = (x, y) diverso da x.

64

Page 65: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

sonoAdiacenti(vertice x, vertice y) → booleanoRestituisce true se esiste l’arco (x, y), false altrimenti.

aggiungiVertice(vertice v) → voidInserisce un nuovo vertice v.

aggiungiArco(vertice x, vertice y) → voidInserisce un nuovo arco tra i vertici x e y.

rimuoviVertice(vertice v) → voidCancella il vertice v e tutti gli archi ad esso incidenti.

rimuoviArco(arco e) → voidCancella l’arco e.

11.2.1 Lista di archi

E una rappresentazione che si basa sull’utilizzo di:

• una struttura per rappresentare i vertici (tipo arraylist);

• una lista per rappresentare gli archi.

11.2.2 Liste di adiacenza

In questa rappresentazione, ogni vertice viene associato ad una lista contenente i suoi vertici adiacenti(struttura realizzata con array di liste).

11.2.3 Matrice di adiacenza

E una rappresentazione basata sull’uso di una matrice n × n le cui righe e colonne sono indicizzate daivertici del grafo:

M [u, v] =

1 se (u, v) ∈ E0 altrimenti

Si tratta di una rappresentazione utile per il seguente fatto:

Proprieta 11.2. Sia Mk = M ·M · ... ·M︸ ︷︷ ︸kvolte

: si ha Mk[u, v] = 1 se e solo se esiste un cammino di k vertici

che collega u a v.

11.2.4 Confronto tra le rappresentazioni

Operazione Lista di archi Lista di adiacenza Matrice di adiacenzagrado(v) O(m) O(deg(v)) O(n)

archiIncidenti(v) O(m) O(deg(v)) O(n)sonoAdiacenti(x, y) O(m) O(min deg(x), deg(y)) O(1)aggiungiVertice(v) O(1) O(1) O(n2)aggiungiArco(x, y) O(1) O(1) O(1)rimuoviVertice(v) O(m) O(m) O(n2)rimuoviArco(e) O(m) O(deg(x) + deg(y)) O(1)

Table 11.1: Tempi di esecuzione

Lista di archi Lista di adiacenza Matrice di adiacenzaSpazio O(m+ n) O(m+ n) O(n2)

Table 11.2: Spazio occupato

65

Page 66: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

11.3 Visite di grafi

Visitare un grafo significa visitarne tutti i nodi, assicurandosi di passare per ciascuno una ed una solavolta, nell’ipotesi che il grafo sia connesso, partendo da un nodo sorgente s. Durante la visita, i nodivengono marcati con opportuni colori per tenere traccia del fatto che siano stati gia considerati o meno:

Verde: nodo non ancora considerato.

Giallo: nodo gia considerato, ma non ancora visitato.

Rosso: nodo gia visitato.

L’algoritmo costruisce un sottografo T di G i cui archi formano un albero radicato in s; mantiene,inoltre, una struttura U in cui inserisce i vertici da esplorare.

Proprieta 11.3.

• durante il ciclo while, U contiene solo vertici gialli, T − U solo vertici rossi e V − T solo verticiverdi ;

• ogni vertice raggiungibile da s viene inserito in U ;

• ogni vertice viene colorato esattamente una volta per ogni colore e nell’ordine verde, giallo, rosso:

→ ogni vertice viene inserito in U esattamente una volta;

→ il corpo del while viene eseguito una volta per ogni vertice;

• se il corpo del while viene eseguito sul vertice v, ha lo stesso costo asintotico della ricerca dei verticiche sono in Adj[v]:

→ costo del while =∑v∈V costo della ricerca dei vertici in Adj[v]

Complessita: il costo totale e dato da ”‘costo del primo for each”’ + ”‘costo del while”’

Lista di archi

costo while =∑v∈V O(m) = O(m · n)

costo totale = O(n+m · n) = O(m · n)

Liste di adiacenza

costo while =∑v∈V O(deg(v)) = O(

∑v∈V deg(v)) = O(2 ·m) = O(m)

costo totale = O(n+m)

Matrice di adiacenza

costo while =∑v∈V O(n) = O(

∑v∈V n) = O(n2)

costo totale = O(n+ n2) = O(n2)

Se U e gestito come:

• pila, viene eseguita una visita in profondita;

• coda, viene eseguita una visita in ampiezza.

Proprieta 11.4. Sia T l’albero prodotto dalla visita in ampiezza del grafo G: allora, per ogni nodo v,il livello di v in T e pari alla distanza tra la sorgente s e il nodo stesso; per tale ragione, T si dice alberodei cammini minimi.

66

Page 67: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

F

B I

E

A

D C H

G

F

B IE

A

D

C

H

G

F

B IE

A

D

C HG

Figure 11.1: Grafo, albero della visita in profondita e albero della visita in ampiezza partendo da F

67

Page 68: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

68

Page 69: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Chapter 12

Minimo albero ricoprente

Definizione 12.1. Dato un grafo G = (V,E) non orientato e connesso, un albero ricoprente di G e unsottografo T ⊆ E tale che:

• T e un albero;

• T contiene tutti i vertici di G.

Sia definita una funzione peso w : E → R; possiamo definire il costo di un albero di copertura comela somma dei pesi degli archi che lo compongono:

w(T ) =∑e∈T

w(e)

Definizione 12.2. Dato un grafo G = (V,E) non orientato, connesso e pesato sugli archi, un minimoalbero ricoprente di G e un albero di copertura di G di costo minimo.

Le definizioni viste finora possono essere estese al caso in cui G non sia connesso: in tal caso si parleradi minima foresta ricoprente.

Lemma 12.1. Siano G = (V,E) un grafo connesso e non orientato, T ⊆ E un albero di copertura,(u, v) ∈ E−T e p un cammino semplice da u a v con tutti gli archi in T (esiste in quanto T e connesso);allora (T − (x, y)) ∪ (u, v) e un albero di copertura.

Proof. Sia T ′ = (T − (x, y)) ∪ (u, v): poiche (u, v) /∈ T , si ha che (u, v) non fa parte del cammino p,ossia che (u, v) 6= (x, y), da cui |T ′| = |V | − 1. Ci rimane da provare che T ′ e connesso.Consideriamo il cammino p = p1, 〈x, y〉 , p2, dove:

• p1 e un cammino da u a x che non contiene (x, y);

• p2 e un cammino da y a v che non contiene (x, y).

Siano a, b ∈ V : dobbiamo trovare un cammino da a a b fatto di archi in T ′. Poiche T e connesso,esiste un cammino q da a a b fatto da archi in T ; possiamo avere due casi:

1. se q non contiene l’arco (x, y), e un cammino anche in T − (x, y) e dunque anche in T ′;

2. se q contiene l’arco (x, y), possiamo scrivere q = q1, 〈x, y〉 , q2 dove:

• q1 e un cammino da a a x che non contiene (x, y);

• q2 e un cammino da y a b che non contiene (x, y).

Sia q′ = q1,←p1, 〈u, v〉 ,

←p2, q2: q′ e cammino in T ′, dunque a e b sono connessi in T ′.

Abbiamo che T ′ e connesso e, avendo n− 1 archi, e anche aciclico: dunque e un albero di copertura,come volevasi dimostrare.

69

Page 70: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

12.1 Teorema fondamentale

Definizione 12.3. Un taglio (S, V − S) di un grafo non orientato G = (V,E) e una partizione di V .

Definizione 12.4. Un arco attraversa il taglio (S, V − S) se uno dei suoi estremi si trova in S e l’altroin V − S.

Definizione 12.5. Un taglio rispetta un insieme A di archi se nessun arco di A attraversa il taglio.

Definizione 12.6. Un arco che attraversa un taglio si dice leggero se ha peso pari al minimo tra i pesidi tutti gli archi che attraversano tale taglio.

Definizione 12.7. Sia A sottoinsieme di un qualche albero di copertura minimo; un arco si dice sicuroper A se puo essere aggiunto ad A e quest’ultimo continua ad essere sottoinsieme di un albero di coperturaminimo.

Teorema 12.1. Sia G = (V,E,w) un grafo non orientato, connesso e pesato; sia inoltre:

• A ⊆ E contenuto in qualche MST;

• (S, V − S) un taglio che rispetta A;

• (u, v) ∈ E un arco leggero che attraversa il taglio.

Allora (u, v) e sicuro per A.

Proof.

Ipotesi: esiste T ⊆ E MST tale che A ⊆ T .

Tesi: dobbiamo trovare T ′ ⊆ E MST tale che A ∪ (u, v) ⊆ T ′.

Poiche (S, V − S) rispetta A e (u, v) attraversa il taglio, allora (u, v) /∈ A. Possiamo distinguere duecasi:

1. se (u, v) ∈ T , allora A ∪ (u, v) ⊆ T MST.

2. se (u, v) /∈ T , dal momento che quest’ultimo e connesso, esistera in esso un cammino semplice pda u a v; poiche (u, v) attraversa il taglio, esiste almeno un arco (x, y) di p che lo attraversa. SiaT ′ = (T − (x, y))∪ (u, v): per il lemma precedentemente dimostrato, e un albero di copertura.Si ha:

(a) (u, v) ∈ T ′;(b) A ⊆ T e, poiche (x, y) attraversa il taglio ed il taglio rispetta A, (x, y) /∈ A; da questo segue:

A ⊆ T − (x, y) → A ⊆ (T − (x, y)) ∪ (u, v) = T ′ → A ∪ (u, v) ⊆ T ′

T ′ e un albero di copertura contenente A ∪ (u, v).(c) w(T ′) = w(T )−w(x, y)+w(u, v); dal momento che (x, y) attraversa il taglio e (u, v) attraversa

il taglio ed e leggero:

w(x, y) ≥ w(u, v)→ w(u, v)− w(x, y) ≤ 0→ w(T ′) ≤ w(T )

Dal momento che T e MST per ipotesi, segue che w(T ′) = w(T ); dunque anche T ′ e MST econtiene A ∪ (u, v).

Corollario 12.1. Sia G = (V,E,w) un grafo non orientato, connesso e pesato; siano:

• A ⊆ E contenuto in un MST;

• C componente connessa della foresta GA = (V,A);

• (u, v) ∈ E arco leggero che connette C ad un’altra componente connessa di GA.

Allora (u, v) e sicuro per A.

70

Page 71: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Proof. e sufficiente applicare il teorema fondamentale considerando il taglio (C, V − C); poiche:

• il taglio rispetta A;

• (u, v) e leggero per il taglio;

si hanno le ipotesi del teorema, dal quale si ottiene che (u, v) e sicuro per A.

12.2 Algoritmo di Kruskal

L’algoritmo mantiene, istante per istante, una foresta contenuta in qualche MST; per poter gestire gliinsiemi disgiunti che rappresentano le varie componenti connesse della foresta, occorre usare una strutturadati appropriata. La tecnica utilizzata consiste nel partizionare l’insieme V in k classi tali che:

•⋃ki=1 Vi = V

• i 6= j ⇒ Vi ∩ Vj = ∅

e rapppresentare ogni classe con un elemento della classe stessa; devono essere permesse le seguentioperazioni:

makeSet(v): crea una classe il cui unico elemento e v e lo elegge come rappresentante della stessa(costo O(1));

findSet(v): restituisce il rappresentante della classe cui v appartiene (costo O(1));

union(u, v): unisce le classi di u e v (partendo da una partizione generata da n chiamate amakeSet, se si eseguono k union, il costo totale di tutte le operazioni e O(k · log k)).

Invariante di ciclo: A ⊆MST .

Complessita

1. O(1)

2-3. O(n)

4. O(m · logm)

5-8. in tutte le iterazioni, si eseguono in totale:

6. 2 findSet per ogni arco → O(2 ·m)

7. A viene aggiornato n− 1 volte (diventa un albero) → O(n)

8. n− 1 union → O(n · log n)

Totale: O(1) + 2 ·O(n) +O(m · logm) +O(2 ·m) +O(n · log n) = O(m · logm) = O(m · log n), poichem = O(n2).

Esempio di esecuzione

Assumiamo che gli archi siano ordinati nel modo seguente: AB, CD, BD, BC, AD, AC. Consideriamo,nell’ordine, gli archi che vengono selezionati:

1. AB : poiche i nodi A e B non sono ancora collegati, l’arco viene selezionato;

2. CD : non esiste un cammino tra C e D, dunque l’arco viene selezionato;

3. BD : non esiste un cammino tra B e D, quindi l’arco viene scelto (il MST e ora pronto);

4. BC : esiste gia un cammino tra B e C, dunque l’arco non viene selezionato;

5. AD : e gia presente un cammino tra A e D, percio l’arco viene scartato;

6. AC : tra A e C esiste gia un cammino, quindi l’arco non viene scelto.

71

Page 72: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

A B

C D

1

36

2

45

A B

C D

1

36

2

45

A B

C D

1

36

2

45

A B

C D

1

36

2

45

Figure 12.1: Simulazione dell’esecuzione dell’algoritmo di Kruskal

12.3 Algoritmo di Prim

L’algoritmo di Prim e fondato direttamente sul teorema fondamentale degli alberi ricoprenti minimi emantiene, istante per istante, un albero contenuto in qualche MST; l’algoritmo, inoltre, vuole in ingressoanche un nodo r ∈ V che sara la radice dell’albero di copertura.Viene utilizzata una struttura dati del tipo coda a min-priorita per gestire l’insieme dei vertici Q nonancora inclusi nell’albero; per ciascun vertice u ∈ Q vengono memorizzati i seguenti attributi:

• key[u] e la chiave di priorita: il suo valore e pari al minimo tra i pesi di tutti gli archi che colleganou ai nodi dell’albero V −Q, se u e adiacente a un vertice di tale albero, altrimenti il valore e infinito.

• π[u] memorizza il predecessore di u nell’albero generato dall’algoritmo.

Si puo ricostruire l’albero finale utilizzando i nodi e le informazioni sui predecessori:

A = (u, π[u]) ∈ E : u ∈ (V − r)

Correttezza: segue direttamente dal teorema fondamentale (ad ogni iterazione, basta considerare iltaglio (V −Q,Q).

Complessita

1-5. O(n)

7. n estrazioni di costo O(log n)→ O(n · log n)

8-11. consideriamo tutti i vertici adiacenti a quello estratto: l’operazione piu costosa e il decremento dellachiave, del costo O(log n): per ogni vertice u ∈ Q, si paga:∑

v∈Adj[u]

O(log n) = deg(u) ·O(log n)

Considerando tutti i vertici, si ha:∑u∈V

δ(u) ·O(log n) = 2 ·m ·O(log n) = O(m · log n)

12. costo della ricostruzione O(n)

Totale: O(n) +O(n · log n) +O(m · log n) +O(n) = O(m · log n), poiche m ≥ n− 1.

Esempio di esecuzione

Per ciascun nodo, e indicata la coppia (chiave, predecessore) associata ad ogni iterazione del ciclo; i nodimarcati in nero sono quelli ancora presenti in Q, il nodo rosso e quello estratto nell’iterazione consideratae quelli blu sono i nodi gia estratti da Q ed esaminati.

L’albero restituito dall’algoritmo, ricostruito a partire dai dati dell’ultima figura, e quello costituitodagli archi AB, BD e CD.

72

Page 73: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

A B

C D

1

36

2

45

(0, NIL) (∞, NIL)

(∞, NIL) (∞, NIL)

A B

C D

1

36

2

45

(0, NIL) (1, A)

(6, A) (5, A)

A B

C D

1

36

2

45

(0, NIL) (1, A)

(4, B) (3, B)

A B

C D

1

36

2

45

(0, NIL) (1, A)

(2, D) (3, B)

A B

C D

1

36

2

45

(0, NIL) (1, A)

(2, D) (3, B)

A B

C D

1

36

2

45

(0, NIL) (1, A)

(2, D) (3, B)

Figure 12.2: Simulazione dell’esecuzione dell’algoritmo di Prim (nodo sorgente a)

73

Page 74: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

74

Page 75: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Chapter 13

Cammini minimi con sorgentesingola

Definizione 13.1. Sia G = (V,E,w) un grafo orientato e pesato; dato il cammino p = 〈v0, v1, ..., vk〉 in

G, il valore w(p) =∑ki=1 w(vi−1, vi) rappresenta il peso del cammino.

Dati u, v ∈ V , definiamo:

C(u, v) = p : p e cammino da u a v in GL’insieme e infinito se il grafo e ciclico (infatti basta eseguire piu volte un ciclo per ottenere cammini

diversi).

Definizione 13.2. La distanza da u a v corrisponde al peso minimo di un cammino da u a v:

δ(u, v) =

+∞ se C(u, v) = ∅minp∈C(u,v) w(p) se C(u, v) 6= ∅

Definizione 13.3. Sia p = 〈u, ..., v〉: si dice che p e cammino minimo se w(p) = δ(u, v).

Varianti al problema dei cammini minimi

• cammino minimo tra due vertici;

• cammini minimi con sorgente singola;

• cammini minimi con destinazione singola;

• cammini minimi tra tutte le coppie di vertici.

Cicli di peso negativo

A B

3

-6

L’esistenza dei cicli di peso negativo e problematica nell’ambito della ricerca deicammini minimi; nell’esempio in figura, non esiste un cammino minimo tra a e b:infatti, se supponiamo di aver trovato un cammino minimo, basta eseguire un’altravolta il ciclo e se ne ottiene uno di peso inferiore.

Rappresentazione dei cammini minimi

Ad ogni vertice, associamo un attributo π[u], che rappresenta il precedente di u in un albero di camminiminimi; gli algoritmi aggiornano opportunamente i valori di π in modo che, alla fine, l’albero rappresentatosia un albero di cammini minimi. Definiamo:

Sottografo dei predecessori indotto da πGπ = (Vπ, Eπ)Vπ = v ∈ V : π[v] 6= NIL ∪ sEπ = (π[v], v) : v ∈ Vπ − s

75

Page 76: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Albero dei cammini minimi: dato G = (V,E,w) orientato e pesato, l’albero dei cammini minimi eG′ = (V ′, E′), con V ′ ⊆ V , E′ ⊆ E tale che:

• V ′ e l’insieme dei vertici raggiungibili da s in G;

• G′ e albero radicato in s;

• ∀u ∈ V ′, l’unico cammino da s a u in G′ e un cammino minimo da s a u in G.

13.1 Cammini minimi e rilassamento

Lemma 13.1 (Sottocammini di cammini minimi sono cammini minimi). Siano G = (V,E,w) un grafoorientato e pesato e p = 〈v0, v1, .., vk〉 cammino minimo da v0 a vk; presi gli indici 0 ≤ i < j ≤ k, ilsottocammino pij = 〈vi, ..., vj〉 e cammino minimo da vi a vj.

Proof. Procediamo per assurdo. Assumiamo che pij non sia minimo: esistera dunque un cammino q davi a vj tale che w(q) < w(pij); consideriamo ora il cammino p0i, q, pjk:

w(p0i, q, pjk) = w(p0i) + w(q) + w(pjk)

< w(p0i) + w(pij) + w(pjk)

= w(p)

Ma p e cammino minimo per ipotesi: assurdo. Quindi pij deve essere minimo.

Proposizione 13.1. Siano G = (V,E,w) grafo orientato e pesato e p = 〈v0, ..., vk〉 cammino minimo dau = v0 a v = vk; allora ∀i = 0..k, δ(u, v) = δ(u, vi) + δ(vi, v).

Proof. Segue direttamente dal lemma precedente; sia p = p0i, pik:

w(p) = w(p0i) + w(pik)

δ(u, v) = δ(u, vi) + δ(vi, v)

come si voleva dimostrare.

Corollario 13.1. Siano G = (V,E,w) un grafo orientato e pesato e p un cammino da s a v scomponibilein un cammino da s a u ∈ V , di nome p′ e un arco da u a v; allora il peso di p e pari a δ(s, v) =δ(s, u) + w(u, v).

Lemma 13.2. Siano G = (V,E,w) un grafo orientato e pesato e s ∈ V un nodo sorgente; allora,∀(u, v) ∈ E si ha δ(s, v) ≤ δ(s, u) + w(u, v).

Proof. Dobbiamo distinguere due casi:

• u non e raggiungibile da s:

δ(s, u) = +∞→ δ(s, v) = δ(s, u) + w(u, v)

• u e raggiungibile da s, dunque esiste un cammino p da s a u; sia q il cammino formato da p e (u, v):

δ(s, v) ≤ w(q)

= w(p) + w(u, v)

= δ(s, u) + w(u, v)

In entrambi i casi la proprieta e valida, dunque il lemma e dimostrato.

76

Page 77: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Algoritmi

Gli algoritmi che analizzeremo (Dijkstra, Bellman-Ford) aggiornano due attributi assegnati ai nodi:

d[u] : stima del peso del cammino minimo dalla sorgente a u;

π[u] : predecessore di u nell’albero dei predecessori.

Al termine vogliamo avere:

• d[u] = δ(s, u);

• Gπ e l’albero dei cammini minimi.

Inizializzazione

Rilassamento

Lemma 13.3. Dopo la chiamata a relax(u, v, w) si ha che d[v] ≤ d[u] +w(u, v), qualunque sia l’ordinedelle chiamate alla funzione.

Lemma 13.4. Siano G = (V,E,w) un grafo orientato e pesato e s ∈ V il nodo sorgente; supponiamoche all’inizio sia stata invocata initSingleSource(G, s). Allora:

1. ∀u ∈ V si ha d[u] ≥ δ(s, u);

2. la proprieta al punto 1 rimarra invariata per qualunque sequenza di relax;

3. nel momento in cui si dovesse verificare che d[u] = δ(s, u) per qualche u ∈ V , allora d[u] non verrapiu modificato da alcuna chiamata di relax.

Proof.

1. Dopo initSingleSource(G, s):

• se u 6= s, d[u] = +∞ ≥ δ(s, u)

• se u = s, d[u] = 0

– se s non sta in un ciclo negativo:δ(s, s) = 0

d[s] = δ(s, s)

– se s sta in un ciclo negativo:δ(s, s) = −∞d[s] = 0 ≥ δ(s, s)

2. Procediamo per assurdo. Assumiamo che, dopo un certo numero di relax, ci sia un vertice v taleche d[v] < δ(s, v). Supponiamo, inoltre, che v sia il primo vertice per cui valga questa proprieta,immediatamente dopo la chiamata relax(u, v, w); abbiamo:

d[v] = d[u] + w(u, v) < δ(s, v) ≤ δ(s, u) + w(u, v)

e, per la proprieta transitiva:

d[u] + w(u, v) < δ(s, u) + w(u, v)

d[u] < δ(s, u)

Visto che d[u] non puo essere stato modificato da relax(u, v, w), dev’essere stato cambiato primada un’altra chiamata; ma v e stato definito come il primo vertice tale per cui d[v] < δ(s, v): assurdo.

3. Osserviamo che:

• nessuna relax, per definizione, incrementa d[u], ma puo solo decrementarlo;

• d[u] ≥ δ(s, u) dopo ogni relax.

77

Page 78: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Segue che, dal momento in cui d[u] = δ(s, u), tale valore non puo piu cambiare.

Corollario 13.2. Se G e inizializzato con initSingleSource(G, s) e v non e raggiungibile da s, allorad[v] = +∞ non verra mai aggiornato da alcuna relax.

Lemma 13.5. Siano dati G = (V,E,w) grafo orientato e pesato e p il cammino minimo da s a v cheinclude (u, v) come arco finale. Supponiamo di inizializzare con initSingleSource(G, s) e chiamiamorelax piu volte; se, ad un certo punto, si ha d[u] = δ(s, u), allora dopo la chiamata relax(u, v, w) si had[v] = δ(s, v).

Proof. Prima di relax(u, v, w) vale δ(s, v) ≤ d[v] per il lemma 13.4 e che d[u] = δ(s, u) per ipotesi. Doporelax(u, v, w) si ha che:

d[v] ≤ d[u] + w(u, v)

= δ(s, u)︸ ︷︷ ︸w(p′)

+w(u, v)

= w(p′) + w(u, v)

= w(p)

= δ(s, v)

dove p′ e cammino minimo da s a u essendo sottocammino di p. Dal lemma 13.4 si ha che δ(s, v) ≤ d[v],da cui segue d[v] = δ(s, v).

13.2 Algoritmo di Dijkstra

Complessita

Sia Q implementato come heap binario:

2. O(n)

3. O(1)

4. O(n)

5-9. il ciclo viene eseguito n volte:

6. ogni estrazione costa O(log n), per un totale di O(n · log n)

7. O(1), per un totale di O(n)

8-9. chiama relax una volta per ogni arco del grafo, quindi si ha un costo totale di O(m · log n);ogni chiamata, infatti, puo modificare la chiave di priorita, operazione dal costo O(log n)

Totale: 3 ·O(n) +O(1) +O(n · log n) +O(m · log n) = O((n+m) · log n).

Sia Q implementato come array lineare:

2. O(n)

3. O(1)

4. O(n)

5-9. il ciclo viene eseguito n volte:

6. bisogna scorrere ogni volta l’intero array, per un totale di O(n2)

7. O(1), per un totale di O(n)

8-9. chiama relax una volta per ogni arco del grafo, che ha costo costante; in totale, dunque, ilcosto e O(m)

Totale: 3 ·O(n) +O(1) +O(n2) +O(m) = O(n2 +m).La prima organizzazione risulta migliore nel caso il grafo sia sparso (m = O(n)), mentre la seconda e

conveniente se il grafo e denso (m = O(n2)).

78

Page 79: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Correttezza

Teorema 13.1. Sia G = (V,E,w) un grafo orientato e pesato con w(u, v) ≥ 0,∀(u, v) ∈ E. Allora, altermine dell’esecuzione dell’algoritmo, si ha:

1. d[u] = δ(s, u),∀u ∈ V ;

2. Gπ e l’albero dei cammini minimi.

Proof. Dimostriamo solo il primo punto, in quanto il secondo segue da relax.Proviamo, comunque, una proprieta piu forte: ∀u ∈ V , nel momento in cui u e inserito in S, valed[u] = δ(s, u) (e per il lemma 13.4, non diminuira ulteriormente).Procediamo per assurdo: assumiamo che u sia il primo vertice tale che d[u] 6= δ(s, u) nel momento in cuiviene inserito in S. Dopo initSingleSource(G, s) si ha d[s] = 0; nel grafo non ci sono cicli negativi,poiche i pesi sono tutti non negativi, dunque si ha δ(s, s) = 0: abbiamo dunque d[s] = δ(s, s), quindi ilvertice u non puo essere s.Visto che s viene estratto per primo, S 6= ∅ quando u viene inserito; puo essere δ(s, u) = +∞? DopoinitSingleSource, d[u] = +∞, quindi ancora prima di iniziare le iterazioni si ha d[u] = δ(s, u); nelleiterazioni si eseguono delle chiamate a relax che, pero, non modificano d[u]: segue, dunque, che udev’essere raggiungibile da s, ossia δ(s, u) < +∞. Sia p il cammino minimo da s a u; la situazione che siha quando viene estratto u da Q e:

79

Page 80: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

s

x y

uS

p1 p2

Q = V − S

Sia (x, y) arco di p tale che x ∈ S e y ∈ Q. Si ha:

d[u] ≤ d[y], perche u estratto da Q che contiene anche y;

d[u] = minv∈Q

d[v]

d[x] = δ(s, x) perche u e il primo vertice per cui non valed[u] = δ(s, u) e x e inserito in S prima di u. Inoltre, quando estato inserito x, e stata chiamata relax(x, y, w); dopo questachiamata, d[y] = δ(s, y) per il lemma 13.5.

δ(s, y) ≤ δ(s, u) poiche i pesi sono non negativi.

δ(s, u) 6= d[u] per ipotesi e d[u] ≥ δ(s, u) per il lemma 13.4; segue che d[u] > δ(s, u).

Da tutte queste proprieta, segue:

d[u] ≤ d[y]

= δ(s, y)

≤ δ(s, u)

< d[u]

Si ottiene dunque un assurdo: il vertice u che cercavamo non esiste e la correttezza e dimostrata.

Esempio di esecuzione

Per ciascun nodo, e indicata la coppia (chiave, predecessore) associata ad ogni iterazione del ciclo; i nodimarcati in nero sono quelli ancora presenti in Q, il nodo rosso e quello estratto nell’iterazione consideratae quelli blu sono i nodi gia estratti da Q ed esaminati. In ogni figura, sono evidenziati gli archi checompongono il sottografo indotto da π.

A

B C

DE

3 2 1 3

6

6

27

5

3

(0, NIL)

(∞, NIL)

(∞, NIL) (∞, NIL)

(∞, NIL)

A

B C

DE

3 2 1 3

6

6

27

5

3

(0, NIL)

(3, A)

(5, A) (∞, NIL)

(∞, NIL)

A

B C

DE

3 2 1 3

6

6

27

5

3

(0, NIL)

(3, A)

(5, A) (∞, NIL)

(9, B)

A

B C

DE

3 2 1 3

6

6

27

5

3

(0, NIL)

(3, A)

(5, A) (11, E)

(8, E)

A

B C

DE

3 2 1 3

6

6

27

5

3

(0, NIL)

(3, A)

(5, A) (10, C)

(8, E)

A

B C

DE

3 2 1 3

6

6

27

5

3

(0, NIL)

(3, A)

(5, A) (10, C)

(8, E)

Figure 13.1: Simulazione dell’esecuzione dell’algoritmo di Dijkstra (nodo sorgente a)

13.3 Algoritmo di Bellman-Ford

L’algoritmo di Dijkstra presenta dei problemi nel caso in cui siano presenti dei cicli di peso negativo: perrisolverli, e stato proposto l’algoritmo di Bellman-Ford.

80

Page 81: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

algoritmo bellmanFord (grafo pesato G, sorgente s) → booleano

1 initSingleSource(G, s)

2 for i = 1 to |V| - 1 do

3 for each (u, v) ∈ E do

4 relax(u, v, w)

5 for each (u, v) ∈ E do

6 if(d[v] > d[u] + w(u, v)) then

7 return false

8 return true

L’algoritmo restituisce:

• false, se e stato trovato un ciclo negativo;

• true altrimenti.

Osservazione: l’algoritmo ritorna true se e solo se d[v] ≤ d[u] + w(u, v),∀(u, v) ∈ E.

Correttezza

Teorema 13.2. Siano G = (V,E,w) un grafo orientato e pesato e s ∈ V il nodo sorgente:

1. se il grafo non contiene cicli negativi raggiungibili da s allora, alla fine di bellmanFord(G, s) siha:

(a) per ogni u ∈ V risulta d[u] = δ(s, u);

(b) Gπ e un albero di cammini minimi;

(c) l’algoritmo ritorna true;

2. se il grafo G contiene cicli negativi raggiungibili da s, l’algoritmo ritorna false.

Proof.

Punto 1a. Per ipotesi, G non ha cicli negativi raggiungibili da s. Sia u ∈ V ; dobbiamo provare chevale d[u] = δ(s, u) al termine dell’esecuzione dell’algoritmo:

1. se u non e raggiungibile da s, si ha δ(s, u) = +∞. Dopo initSingleSource(G, s) vale d[u] =+∞ = δ(s, u) e, poiche relax non modifica ulteriormente d[u] per il lemma 13.4, al termine valeancora d[u] = δ(s, u);

2. se u e raggiungibile da s, si ha δ(s, u) < +∞. Sia p = 〈x0, ..., xk〉 cammino minimo da s a u, conx0 = s e xk = u; p non ha cicli e, inoltre, il numero di nodi di p, ossia k+ 1, e inferiore o uguale allacardinalita di V . Consideriamo il predecessore di u nel cammino e chiamiamolo v: se p e camminominimo e d[v] = δ(s, v), dopo relax(v, u, w) vale d[u] = δ(s, u).

Proprieta 13.1. Se esiste un cammino minimo da s a u con k archi, allora dopo il k-esimo ciclodell’algoritmo (righe 2-4) vale d[u] = δ(s, u) (invariante del ciclo).

Proof. Procediamo per induzione su k.

Caso base: abbiamo k = 0, dunque u = s; si ha d[s] = 0 per initSingleSource e δ(s, s) = 0 perl’ipotesi dell’assenza di cicli negativi, dunque la proprieta e dimostrata per il caso base.

Ipotesi induttiva: supponiamo che la proprieta valga per i < k.

Passo induttivo: sia k > 0; consideriamo il cammino p = 〈x0, ..., xk〉, con x0 = s e xk = u. Peripotesi induttiva, alla k−1-esima iterazione, d[xk−1] = δ(s, xk−1); all’iterazione k-esima, tra levarie chiamate, viene eseguita relax(xk−1, xk, w) e, per il lemma 13.5, si ha d[xk] = δ(s, xk),ossia d[u] = δ(s, u).

Dunque, al termine del ciclo, tutti i cammini sono stati sistemati (se non ci sono cicli negativi) ehanno al piu n− 1 archi.

81

Page 82: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Punto 1b. Segue direttamente da relax.

Punto 1c. Dobbiamo dimostrare che d[v] ≤ d[u] + w(u, v),∀(u, v) ∈ E. Per il lemma 13.2, si haδ(s, v) ≤ δ(s, u) + w(u, v); consideriamo (u, v) ∈ E:

d[v] = δ(s, v)

≤ δ(s, u) + w(u, v)

= d[u] + w(u, v)

L’ultima uguaglianza segue dal punto 1a.

Punto 2. Dal punto 1 sappiamo che, se non ci sono cicli negativi raggiungibili da s, allora l’algoritmoritorna true. Proviamo ora il viceversa, ossia che, se l’algoritmo ritorna true, non ci sono cicli negativiraggiungibili da s.Sia C = 〈x0, ..., xk〉 un ciclo raggiungibile da s; poiche, per ipotesi, l’algoritmo ritorna true, si ha:

d[v] ≤ d[u] + w(u, v)

In particolare, considerando gli archi (xi, xi+1) con i = 0..k − 1:

d[xi+1] ≤ d[xi] + w(xi, xi+1)

k−1∑i=0

d[xi+1] ≤k−1∑i=0

d[xi] +

k−1∑i=0

w(xi, xi+1)

d[x1] + d[x2] + ...+ d[xk] ≤ d[x0] + d[x1] + ...+ d[xk−1] +

k−1∑i=0

w(xi, xi+1)

d[xk] ≤ d[x0] +

k−1∑i=0

w(xi, xi+1)

Poiche C e un ciclo, si ha x0 = xk, ossia d[x0] = d[xk]; segue:

0 ≤k−1∑i=0

w(xi, xi+1) = w(C)

Abbiamo cos dimostrato che, se l’algoritmo ritorna true, non esistono cicli negativi raggiungibili das; segue dunque che, se ci sono cicli negativi raggiungibili da s, l’algoritmo restituisce false.

Complessita

1. O(n)

2-4. vengono eseguite m · n chiamate a relax, il cui costo e O(1); in totale si ha O(m · n)

5-7. il ciclo viene eseguito m volte ed ogni iterazione ha costo O(1); in totale si paga e O(m)

8. O(1)

Totale: O(n) +O(m · n) +O(m) +O(1) = O(m · n).

L’algoritmo risulta essere computazionalmente piu costoso rispetto a quello di Dijkstra, ma puo essereapplicato anche se gli archi hanno pesi negativi: la scelta di quale algoritmo utilizzare, dunque, dipendeda come e definita la funzione peso.

Esempio di esecuzione

L’ordine di analisi degli archi segue l’ordine alfabetico con cui sono identificati i vertici: prima tutti gliarchi che partono da a, poi quelli che partono da b, etc. Le figure si riferiscono a:

1. situazione dopo initSingleSource;

2. situazione dopo la prima passata di tutti gli archi;

3. situazione dopo la seconda passata di tutti gli archi (le successive non producono variazioni).

Chiaramente l’algoritmo restituisce true.

82

Page 83: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

A

B C

DE

3 2 1 3

6

6

27

5

3

(0, NIL)

(∞, NIL)

(∞, NIL) (∞, NIL)

(∞, NIL)

A

B C

DE

3 2 1 3

6

6

27

5

3

(0, NIL)

(3, A)

(5, A) (11, C)

(8, E)

A

B C

DE

3 2 1 3

6

6

27

5

3

(0, NIL)

(3, A)

(5, A) (10, C)

(8, E)

Figure 13.2: Esempio di esecuzione dell’algoritmo di Bellman - Ford (nodo sorgente a)

83

Page 84: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

84

Page 85: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Chapter 14

Cammini minimi fra tutte le coppie

Consideriamo il problema dei cammini minimi fra tutte le coppie in un grafo G = (V,E,w) orientato,pesato, dove possono essere presenti archi (ma non cicli) di peso negativo; assumiamo, inoltre, che gli nvertici siano identificati da numeri interi da 1 a n.

14.1 Cammini minimi e moltiplicazione di matrici

Matrice di adiacenza pesata

Si tratta di una matrice n × n che, oltre a specificare se esiste l’arco (i, j), indica anche il peso di talearco.

wi,j =

0 se i = j

w(i, j) se i 6= j ∧ (i, j) ∈ E+∞ se i 6= j ∧ (i, j) /∈ E

Matrice delle distanze

E una matrice n × n, aggiornata dall’algoritmo, dove di,j contiene la stima della distanza tra i e j; altermine dell’esecuzione dell’algoritmo, vogliamo che di,j = δ(i, j),∀i, j ∈ V .

Moltiplicazione di matrici

Siano i, j ∈ V ; definiamo:

Ci,j = p = 〈x0, ..., xq〉 : x0 = i ∧ xq = j ∧ (xl−1, xl) ∈ E, l = 1..q

La distanza tra i e j puo essere definita come segue:

δ(i, j) = minp∈C(i,j)

w(p)

Fissiamo m ≥ 1:

C(m)i,j = p = 〈x0, ..., xq〉 : x0 = i ∧ xq = j ∧ (xl−1, xl) ∈ E, l = 1..q ∧ q ≤ m

d(m)i,j = min

p∈C(m)i,j

w(p)

Sono valide le seguenti relazioni:

C(1)i,j ⊆ C

(2)i,j ⊆ ... ⊆ C

(m)i,j ⊆ C

(m+1)i,j ⊆ ... ⊆ Ci,j

Ci,j =⋃m∈NC(m)i,j

85

Page 86: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

d(1)i,j ≥ d

(2)i,j ≥ ... ≥ d

(m)i,j ≥ ... ≥ δ(i, j)

Poiche non sono presenti, per ipotesi, cicli negativi, possiamo assumere che i cammini minimi siano

cammini semplici, dunque formati al piu da n− 1 archi; ossia, si ha d(n−1)i,j = d

(n)i,j = d

(n+1)i,j = ... = δ(i, j).

L’idea e di progettare un algoritmo per il calcolo di d(m)i,j in modo che, quando arriviamo a d

(n−1)i,j ,

otteniamo proprio le distanze; cerchiamo una formula ricorsiva per il calcolo di d(m)i,j , per induzione.

Caso base: si ha m = 1

C(1)i,j =

〈i〉 se i = j

〈i, j〉 se i 6= j ∧ (i, j) ∈ E∅ se i 6= j ∧ (i, j) /∈ E

d(1)i,j =

0 se i = j

w(i, j) se i 6= j ∧ (i, j) ∈ E+∞ se i 6= j ∧ (i, j) /∈ E

Ipotesi induttiva: supponiamo di essere riusciti a calcolare la matrice delle distanze D(m−1).

Passo induttivo: sia m > 1 e proviamo a calcolare D(m) usando l’ipotesi. Prendiamo i, j ∈ V : p ∈ C(m)i,j

puo essere scomposto come p = p′, j, con p′ ∈ C(m−1)i,k ; in generale, i cammini minimi in C(m)

i,j sonoscomponibili come segue:

.

.

.

.

.

k1

k2i

j

(kπ, j)

(k2, j)

(k1, j)

da cui:

d(m)i,j = min

p∈C(m)i,j

w(p) = mink∈V $k,j)∈E

d

(m−1)i,k + w(k, j)

Sia h ∈ V : se (h, j) /∈ E, allora d

(m−1)i,h + w(h, j) = +∞.

La formula cercata e la seguente:

d(m)i,j = min

k∈V

d

(m−1)i,k + w(k, j)

Per implementare la formula ricorsiva, definiamo la seguente funzione:

funzione extendShortestPath (matrice delle distanze D(m−1), matrice di adiacenza pesata W ) → ma-trice delle distanze D(m)

1 n = rows(D)

2 Dm : matrice[n][n]

3 for i = 1 to n do

4 for j = 1 to n do

5 Dm[i][j] = + ∞6 for k = 1 to n do

7 Dm[i][j] = min(Dm[i][j], D[i][k] + W[k][j])

8 return Dm

86

Page 87: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Complessita: Θ(n3).

La funzione definisce un nuovo tipo di prodotto tra matrici D⊗W = D′, dove D′ e la matrice calcolatada extendShortestPath:

algoritmo showAllPairsShortestPath (matrice di adiacenza pesata W )→ matrice delle distanze D(n−1)

1 n = rows(W)

2 D(1) = W

3 for m = 2 to n - 1 do

4 D(m) = D(m - 1) ⊗ W

5 return D(n - 1)

Complessita: Θ(n4).

14.2 Algoritmo di Floyd-Warshall

Consideriamo un grafo che goda delle proprieta descritte ad inizio capitolo; vogliamo determinare δ(i, j)per ogni coppia i, j. Costruiamo Ci,j in maniera incrementale; sia 0 ≤ k ≤ n e definiamo:

P(k)i,j = p = 〈x0, ..., xq〉 : x0 = i ∧ xq = j ∧ (xl−1, xl) ∈ E, l = 1..q ∧ xh ≤ k, h = 1..(q − 1)

Si tratta dell’insieme dei cammini da i a j i cui nodi interni sono in 1..k; osserviamo che P(n)i,j = Ci,j

quindi, se definiamo:

d(k)i,j = min

p∈P (k)i,j

w(p)

si ha:

d(n)i,j = δ(i, j)

L’obiettivo e calcolare d(n)i,j per ogni coppia di vertici in V ; procediamo per induzione su k.

Caso base: si ha k = 0; P(0)i,j e l’insieme dei cammini da i a j che non hanno nodi interni, dunque:

P(0)i,j =

〈i〉 se i = j

〈i, j〉 se i 6= j ∧ (i, j) ∈ E∅ se i 6= j ∧ (i, j) /∈ E

d(0)i,j =

0 se i = j

w(i, j) se i 6= j ∧ (i, j) ∈ E+∞ se i 6= j ∧ (i, j) /∈ E

Se chiamiamo D(k) = (d(k)i,j ), si ha D(0) = W .

Ipotesi induttiva: supponiamo di conoscere P(k−1)i,j .

Passo induttivo: sia k ≥ 1; usando l’ipotesi induttiva, cerchiamo di ottenere P(k)i,j . Innanzitutto, os-

serviamo che P(k−1)i,j ⊆ P (k)

i,j e definiamo P(k)i,j = P

(k)i,j −P

(k−1)i,j =

p ∈ P (k)

i,j : p passa per il vertice k

.

Si ha:d

(k)i,j = min

p∈P (k)i,j

w(p)

= min

(min

p∈P (k−1)i,j

w(p), minp∈P (k)

i,j

w(p)

)

87

Page 88: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Il primo parametro della funzione minimo e:

minp∈P (k−1)

i,j

w(p) = d(k−1)i,j

Per quanto riguarda il secondo, dobbiamo trovare il peso del cammino piu leggero da i a j che puopassare per i nodi 1..k e passa sicuramente per k; consideriamo cammini semplici, in quanto nonsono presenti cicli negativi: il cammino che cerchiamo puo essere scomposto in due parti:

1. cammino da i a k che puo passare per i nodi 1..k − 1;

2. cammino da k a j che puo passare per i nodi 1..k − 1.

Chiaramente le due parti dovranno essere entrambe minime, affinche il cammino totale lo sia: il

loro costo lo conosciamo ed e, rispettivamente, d(k−1)i,k e d

(k−1)k,j . Dunque, il secondo parametro della

funzione minimo e:

minp∈P (k)

1,j

w(p) = d(k−1)i,k + d

(k−1)k,j

La formula ricorsiva per il calcolo di d(k)i,j e dunque la seguente:

d(k)i,j =

w(i, j) se k = 0

min(d(k−1)i,j , d

(k−1)i,k + d

(k−1)k,j ) se k > 0

L’algoritmo segue direttamente dalla formula:

Complessita

Temporale: Θ(n3)Spaziale: Θ(n3)

Costruzione di un cammino minimo

Un metodo per costruire i cammini minimi usando l’algoritmo di Floyd Warshall consiste nell’usare lamatrice dei pesi di cammino minimo prodotta e costruire, in tempo O(n3), la matrice dei predecessori Π.Un secondo metodo prevede di calcolare Π ”‘in linea”’ con l’algoritmo, o meglio, si calcola una sequenza

di matrici Π(0), Π(1), ..., Π(n), dove Π = Π(n) e π(k)i,j e definito come il predecessore di j su un cammino

minimo dal vertice i avente tutti i vertici intermedi nell’insieme 1, ..., k.Si puo definire induttivamente π

(k)i,j ; quando k = 0 si ha:

π(0)i,j =

NIL se i = j o w(i, j) =∞i se i 6= j e w(i, j) <∞

Per k > 1, se prendiamo il cammino da i a j passante per k, allora il predecessore di j e lo stesso verticeche avevamo scelto come predecessore di j in un cammino da k con tutti i vertici intermedi nell’insieme1, ..., k − 1; altrimenti, scegliamo lo stesso predecessore di j che avevamo scelto su un cammino minimoda i con tutti i vertici nell’insieme 1, ..., k − 1. Formalmente:

π(k)i,j =

π

(k−1)i,j se d

(k−1)i,j ≤ d(k−1)

i,k + d(k−1)k,j

π(k−1)k,j se d

(k−1)i,j > d

(k−1)i,k + d

(k−1)k,j

Miglioramento

L’algoritmo che segue e una versione migliorata di Floyd Warshall ed ha complessita spaziale Θ(n2),mentre la complessita temporale non cambia (Θ(n3)): l’idea consiste nell’utilizzare sempre la stessamatrice, invece di utilizzarne una diversa per ciascun k.

88

Page 89: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

2

3

45

1

43

8

1

-5-4

6

7

2

Esempio di esecuzione

Simuliamo l’esecuzione sul seguente grafo:

D(0) =

0 3 8 ∞ −4∞ 0 ∞ 1 7∞ 4 0 ∞ ∞2 ∞ −5 0 ∞∞ ∞ ∞ 6 0

Π(0) =

NIL 1 1 NIL 1NIL NIL NIL 2 2NIL 3 NIL NIL NIL

4 NIL 4 NIL NILNIL NIL NIL 5 NIL

D(1) =

0 3 8 ∞ −4∞ 0 ∞ 1 7∞ 4 0 ∞ ∞2 5 −5 0 −2∞ ∞ ∞ 6 0

Π(1) =

NIL 1 1 NIL 1NIL NIL NIL 2 2NIL 3 NIL NIL NIL

4 1 4 NIL 1NIL NIL NIL 5 NIL

D(2) =

0 3 8 4 −4∞ 0 ∞ 1 7∞ 4 0 5 112 5 −5 0 −2∞ ∞ ∞ 6 0

Π(2) =

NIL 1 1 2 1NIL NIL NIL 2 2NIL 3 NIL 2 2

4 1 4 NIL 1NIL NIL NIL 5 NIL

D(3) =

0 3 8 4 −4∞ 0 ∞ 1 7∞ 4 0 5 112 −1 −5 0 −2∞ ∞ ∞ 6 0

Π(3) =

NIL 1 1 2 1NIL NIL NIL 2 2NIL 3 NIL 2 2

4 3 4 NIL 1NIL NIL NIL 5 NIL

D(4) =

0 3 −1 4 −43 0 −4 1 −17 4 0 5 32 −1 −5 0 −28 5 1 6 0

Π(4) =

NIL 1 4 2 1

4 NIL 4 2 14 3 NIL 2 14 3 4 NIL 14 3 4 5 NIL

D(5) =

0 1 −3 2 −43 0 −4 1 −17 4 0 5 32 −1 −5 0 −28 5 1 6 0

Π(5) =

NIL 3 4 5 1

4 NIL 4 2 14 3 NIL 2 14 3 4 NIL 14 3 4 5 NIL

89

Page 90: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

90

Page 91: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Chapter 15

Reti di flusso

15.1 Introduzione

Definizione 15.1. Una rete di flusso e un grafo orientato G = (V,E) con una funzione c : V × V → R+

detta funzione capacita.

• Assumiamo che c(u, v) > 0 se e solo se (u, v) ∈ E.

• In una rete di flusso, sono presenti due vertici particolari: la sorgente)e il pozzo.

• Per comodita, assumiamo che, per ogni v ∈ V , esista un cammino dalla sorgente al pozzo passanteper v.

Definizione 15.2. Sia G = (V,E) una rete di flusso e c : V × V → R+ funzione capacita; siano inoltres e t, rispettivamente, sorgente e pozzo: un flusso in G e una funzione f : V × V → R+ che soddisfa leseguenti proprieta:

Vincolo di capacita: ∀u, v ∈ V, f(u, v) ≤ c(u, v).

Vincolo di antisimmetria: ∀u, v ∈ V, f(u, v) = −f(v, u).

Conservazione del flusso: ∀u ∈ V − s, t ,∑vinV f(u, v) = 0.

Definizione 15.3. Sia f un flusso nella rete G con sorgente s: si definisce valore del flusso la quantita:

|f | =∑v∈V

f(s, v)

Proprieta 15.1. Per ogni u ∈ V, f(u, u) = 0.

Proof. Per la proprieta antisimmetrica, si ha:

f(u, u) = −f(u, u)→ 2 · f(u, u) = 0

da cui si ottiene il risultato cercato.

Proprieta 15.2. Se u, v ∈ V, (u, v) /∈ E ∧ (v, u) /∈ E, allora f(u, v) = f(v, u) = 0.

Proof. Per il vincolo di capacita si puo scrivere:

c(u, v) = 0→ f(u, v) ≤ c(u, v) = 0

e, per l’antisimmetria:

f(u, v) = −f(v, u)→ −f(u, v) ≤ 0→ f(u, v) ≥ 0

Affinche valgano entrambe le relazioni, si deve avere f(u, v) = 0. Con un ragionamento analogo, sipuo provare che anche f(v, u) = 0, il che conclude la dimostrazione.

91

Page 92: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Definizione 15.4. Sia u ∈ V ; il flusso netto positivo entrante in u e definito come:

FNPE(u) =∑v∈V

f(v,u)>0

f(v, u)

Il flusso netto positivo uscente da u e invece definito come:

FNPU(u) =∑v∈V

f(u,v)>0

f(u, v)

Lemma 15.1. Per ogni u ∈ V − s, t , FNPE(u) = FNPU(u).

Proof. Per la conservazione del flusso, si ha:

0 =∑v∈V

f(u, v) =∑v∈V

f(u,v)>0

f(u, v) +∑v∈V

f(u,v)<0

f(u, v) =∑v∈V

f(u,v)>0

f(u, v) +∑v∈V

f(v,u)>0

f(u, v)

=∑v∈V

f(u,v)>0

f(u, v)−∑v∈V

f(v,u)>0

f(u, v) = FNPU(u)− FNPE(u)

Dunque, si ottiene:

0 = FNPU(u)− FNPE(u)

da cui segue la proprieta che si voleva dimostrare.

Sommatoria estesa

Siano X,Y, Z ⊆ V ; definiamo:

f(X,Y ) =∑u∈X

∑v∈Y

f(u, v)

Per rendere piu compatta la notazione, definiamo:

• f(u , v) = f(u, v);

• f(u , Y ) = f(u, Y ).

Da questo punto di vista, possiamo definire il valore del flusso come:

|f | =∑v∈V

f(s, v) = f(s, V )

Proprieta 15.3. f(X,X) = 0.

Proof. Sia X = x1, x2, ..., xn: costruiamo una matrice M di dimensione n × n, dove Mi,j = f(xi, xj).Possiamo scrivere:

f(X,X) =

n∑i=1

n∑j=1

Mi,j

Gli elementi della diagonale principale sono tutti 0, per la proprieta 15.1; inoltre, per l’antisimmetria,si ha che Mi,j = −Mj,i, ossia Mi,j + Mj,i = 0. Da questi fatti, segue che f(X,X) = 0, come si volevadimostrare.

Proprieta 15.4. f(X,Y ) = −f(Y,X).

Proof.

f(X,Y ) =∑u∈X

∑v∈Y

f(u, v) =∑u∈X

∑v∈Y−f(v, u) = −

∑u∈X

∑v∈Y

f(v, u)

= −∑v∈Y

∑u∈X

f(v, u) = −f(Y,X)

92

Page 93: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Proprieta 15.5. Se X ∩ Y = ∅, si ha:

f(X ∪ Y,Z) = f(X,Z) + f(Y, Z)

altrimenti:f(X ∪ Y, Z) = f(X,Z) + f(Y,Z)− f(X ∩ Y,Z)

Usando queste proprieta, possiamo scrivere:

0 = f(V, V ) = f(s ∪ V − s , V ) = f(s, V ) + f(V − s , V )

= f(s, V ) + f(V − s, t ∪ t , V ) = f(s, V ) + f(V − s, t , V )︸ ︷︷ ︸=0 per cons. flusso

+f(t, V )

da cui segue:f(s, V ) + f(t, V ) = 0→ f(s, V ) = −f(t, V )→ f(s, V ) = f(V, t)

Il valore del flusso puo quindi essere definito, in modo equivalente, come:

|f | = f(s, V ) = f(V, t)

Somme di flussi

Siano f1 e f2 due flussi in G; definiamo:

f1 + f2 :V × V → R(u, v)→ f1(u, v) + f2(u, v)

• Il vincolo di capacita cade (non e detto che (f1 + f2)(u, v) ≤ c(u, v)).

• Il vincolo di antisimmetria permane:

(f1 + f2)(u, v) = f1(u, v) + f2(u, v) = −f1(v, u)− f2(v, u)

= −(f1(v, u) + f2(v, u)) = −(f1 + f2)(v, u)

• La conservazione del flusso permane; sia u ∈ V − s, t:∑v∈V

(f1 + f2)(u, v) =∑v∈V

(f1(u, v) + f2(u, v)) =∑v∈V

f1(u, v)︸ ︷︷ ︸=0

+∑v∈V

f2(u, v)︸ ︷︷ ︸=0

= 0

Problema di sorgenti e pozzi multipli

Per risolvere il problema del flusso massimo da piu sorgenti a piu destinazioni, e sufficiente usare unasupersorgente virtuale, dalla quale partono archi di capacita infinita diretti alle sorgenti reali, e unsuperpozzo virtuale, al quale arrivano archi di capacita infinita dai pozzi reali.

15.2 Problema del flusso massimo

Il problema che si vuole affrontare e quello del flusso massimo: data una rete di flusso, trovare un flussoil cui valore corrisponda al valore massimo tra tutti i flussi possibili.

Siano G = (V,E) rete di flusso, c : V × V → R+ capacita, f : V × V → R flusso e s, t ∈ V .

Definizione 15.5. La capacita residua cf e una funzione definita come segue:

cf :V × V → R+

(u, v)→ c(u, v)− f(u, v)

Poiche f e un flusso, si ha f(u, v) ≤ c(u, v), da cui c(u, v)−f(u, v) ≥ 0 per ogni coppia (u, v): dunquecf e una capacita a tutti gli effetti.

93

Page 94: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Definizione 15.6. Una rete residua e un grafo Gf = (V,Ef ), con Ef = (u, v) : cf (u, v) > 0.

Osservazione: Gf con cf e una rete di flusso.

Proposizione 15.1. Siano G = (V,E) rete di flusso, f : V × V → R flusso in G, Gf rete residua ef ′ : V × V → R flusso in Gf ; definendo:

f + f ′ :V × V → R(u, v)→ f(u, v) + f ′(u, v)

valgono:

1. f + f ′ e un flusso in G;

2. |f + f ′| = |f |+ |f ′|.

Proof.

Punto 1. Dimostriamo che valga il vincolo di capacita, in quanto le altre due proprieta sono valideper la somma di due flussi qualsiasi; vogliamo provare che (f + f ′)(u, v) ≤ c(u, v),∀(u, v) ∈ V × V .

(f + f ′)(u, v) = f(u, v) + f ′(u, v)︸ ︷︷ ︸≤cf (u,v)

≤ f(u, v) + cf (u, v) = f(u, v) + c(u, v)− f(u, v) = c(u, v)

Punto 2.

|f + f ′| =∑v∈V

(f + f ′)(s, v) =∑v∈V

(f(s, v) + f ′(s, v)) =∑v∈V

f(s, v) +∑v∈V

f ′(s, v) = |f |+ |f ′|

Definizione 15.7. Definiamo la capacita di un cammino come la capacita minima tra tutte le capacitadegli archi che compongono il cammino.

Definizione 15.8. Siano G una rete di flusso e f flusso in G:

• un cammino aumentante e un cammino semplice tra la sorgente s e il pozzo t nella rete residua Gf ;

• la capacita residua minima di un cammino aumentante p e definita come:

cf (p) = min cf (u, v) : (u, v) e arco di p > 0

Definizione 15.9. Sia p un cammino aumentante; il flusso associato a p e una funzione fp : V ×V → Rdefinita come:

fp =

cf (p) se (u, v) ∈ p−cf (p) se (v, u) ∈ p0 altrimenti

Lemma 15.2. Sia fp il flusso associato al cammino aumentante p; allora:

• fp e flusso in Gf ;

• |fp| = cf (p) > 0.

Proof.

Prima parte. Verifichiamo che valgono le tre proprieta caratterizzanti un flusso:

Vincolo di capacita: fp(u, v) ≤ cf (u, v).

• se (u, v) ∈ p, fp(u, v) = cf (p) ≤ cf (u, v);

• se (u, v) e tale che (v, u) ∈ p, allora fp(u, v) = −cf (p) < 0 ≤ cf (u, v);

94

Page 95: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

• se (u, v) /∈ p ∧ (v, u) /∈ p, fp(u, v) = 0 ≤ cf (u, v).

Vincolo di antisimmetria: e valido per definizione.

Conservazione del flusso: sia u ∈ V − s, t:

• se u /∈ p allora, per ogni vertice v ∈ V , si ha (u, v) /∈ p da cui fp(u, v) = 0; dunque∑v∈V fp(u, v) = 0.

• se u ∈ p, consideriamo il vertice w precedente nel cammino e il vertice v successivo; si ha:∑v∈V

fp(u, v) = fp(u,w)︸ ︷︷ ︸−cf (p)poiche

(w,u)∈p

+ fp(u, v)︸ ︷︷ ︸cf (p)poiche

(u,v)∈p

= 0

Seconda parte.

|fp| =∑v∈V

fp(s, v) = f(s, V ) = cf (p)

Si ha che s 6= t, dunque fra i due esiste almeno un arco; non sono presenti archi entranti in s, poichee il nodo sorgente: il contributo, quindi, e dato da f(s, V ).

Algoritmo per il calcolo del flusso massimo

Un generico algoritmo per il calcolo del flusso massimo puo essere descritto come segue:

• parti da un flusso banale (f(u, v) = 0,∀(u, v) ∈ V × V );

• finche non hai un flusso massimo:

– considera la rete residua e cerca un cammino aumentante;

– sfrutta tale cammino per definire un flusso in Gf ;

– aggiungi il flusso trovato a quello di partenza.

15.3 Flusso massimo - taglio minimo

Un altro metodo per il calcolo del flusso massimo si riconduce al problema del taglio minimo.

Definizione 15.10. Siano G una rete di flusso, s sorgente e t pozzo:

• un taglio in G e una coppia (S, T ) con S ⊆ V e T = V − S tali che s ∈ S e t ∈ T ;

• la capacita associata al taglio e:

c(S, T ) =∑u∈S

∑v∈T

c(u, v)

• il flusso netto associato al taglio e dato da:

f(S, T ) =∑u∈S

∑v∈T

f(u, v)

Si tratta di un flusso ben definito, in quanto f(S, T ) ≤ c(S, T ).

Problema del taglio minimo: data una rete di flusso G, trovare il taglio con capacita minima (e ilduale del problema del flusso massimo: per trovare il flusso massimo occorre trovare la capacita minimatra tutti i possibili tagli).

Lemma 15.3. Siano G = (V,E) rete di flusso, f flusso in G e (S, T ) taglio in G: allora |f | = f(S, T ).

95

Page 96: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Proof. Osserviamo innanzitutto che:

f(S, V ) = f(S, S ∪ T ) = f(S ∪ (V − S)) = f(S, S)︸ ︷︷ ︸=0

+f(S, V − S) = f(S, V − S)

Usando questo fatto, possiamo procedere con la dimostrazione:

f(S, T ) = f(S, V − S) = f(S, V ) = f(s ∪ (S − s), V ) = f(s, V ) + f(S − s , V )

= |f |+∑

u∈S−s

=0︷ ︸︸ ︷∑v∈V

f(u, v)

︸ ︷︷ ︸=0

= |f |

L’ultimo passaggio segue dal principio di conservazione del flusso.

Corollario 15.1. Siano G = (V,E) rete di flusso, f flusso arbitrario in G e (S, T ) taglio arbitrario:allora |f | ≤ c(S, T ).

Proof.|f | = f(S, T ) ≤ c(S, T )

Il nostro obiettivo e calcolare f∗:

c(S, T)

| f* | = c(S*, T*)

| f |

Siano (S∗, T ∗) il taglio con capacita minima e f∗ il flusso tale che |f∗| =c(S∗, T ∗):

∀(S, T ), c(S∗, T ∗) ≤ c(S, T )

∀f, |f | ≤ |f∗|

Teorema 15.1 (Flusso massimo - taglio minimo). Siano G rete di flusso, s sorgente, t pozzo e f flussoin G; le seguenti affermazioni sono equivalenti:

(a) f e massimo;

(b) la rete residua Gf non ammette cammini aumentanti;

(c) esiste un taglio (S, T ) in G tale che c(S, T ) = |f |.

Proof. Diamo una dimostrazione ciclica, ossia che a⇒ b, b⇒ c e c⇒ a.

Prima parte: a ⇒ b. Assumiamo, per assurdo, che esista un cammino aumentante p in Gf e siacf (p) > 0 la sua capacita residua; possiamo definire fp flusso in Gf , con |fp| = cf (p). f + fp e un flussoin G e si ha:

|f + fp| = |f |+ |fp|︸︷︷︸>0

> |f |

Abbiamo trovato un flusso in G con valore strettamente maggiore del flusso massimo, il che e chiaramenteun assurdo: dunque, non puo esistere un cammino aumentante in Gf .

Seconda parte: b⇒ c. Definiamo:

S = v : esiste un cammino da s a v in GfT = V − S (i vertici non raggiungibili da s in Gf )

Si ha che s ∈ S e t /∈ S per ipotesi, in quanto abbiamo supposto che non esista un cammino aumentantein Gf . (S, V − S) e un taglio in G e, in Gf , abbiamo la seguente situazione:

96

Page 97: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

S V - S

t

vu

s

Siano u ∈ S e v ∈ V −S: in Gf non e presente l’arco (u, v) poiche, se esistesse, v sarebbe raggiungibileda s e dunque dovrebbe trovarsi in V . Per ogni u ∈ S e v ∈ V − S si ha:

cf (u, v) = 0

da cui, per come e definita cf :

c(u, v)− f(u, v) = 0→ c(u, v) = f(u, v)

Da questa relazione, possiamo provare quanto si vuole dimostrare:

C(S, V − S) =∑u∈S

∑v∈V−S

c(u, v) =∑u∈S

∑v∈V−S

f(u, v) = f(S, V − S) = |f |

Terza parte: c⇒ a. Consideriamo un flusso f ′ in G:

c(S, T )︸ ︷︷ ︸=|f |

≥ f ′(S, T ) = |f ′|

da cui si ottiene |f | ≥ |f ′|, come si voleva dimostrare.

15.4 Algoritmo di Ford-Fulkerson

Correttezza

Il teorema 15.1 ci dice che, se l’algoritmo termina, allora e corretto; con capacita razionali l’algoritmo siferma sicuramente, mentre le capacita irrazionali sono problematiche.

Complessita

1-3. Θ(m)

4. la ricerca di un cammino aumentante viene eseguita mediante una visita del grafo, quindi il costoe O(m)

5-8. O(m)

Quante volte troviamo un cammino aumentante? Se f∗ e il flusso massimo, partendo da zero edavendo capacita intere, possiamo aggiornare il flusso corrente |f∗| volte; dunque la complessita totale eO(|f∗| ·m) (complessita pseudopolinomiale).

Esempio di esecuzione

Simuliamo l’esecuzione dell’algoritmo sul seguente grafo:Dal momento che l’algoritmo non specifica quale tra i tanti cammini aumentanti prendere, nella

simulazione ne saranno presi alcuni senza criteri di scelta particolari; ogni immagine rappresenta lasituazione al termine dell’esecuzione di ciascuna iterazione del ciclo while: a sinistra il grafo di partenzacon i valori di flusso aggiornati, a destra la corrispondente rete residua.

Cammino p1 = 〈s, v1, v3, v2, v4, t〉 , cf (p1) = 4Cammino p2 = 〈s, v1, v3, t〉 , cf (p2) = 8

97

Page 98: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

v3

v4

ts

v2

v1

16

12

10

4 9

7

20

4

14

13

v3

v4

ts

v2

v1

4/16

4/12

0/100/4

4/9

0/7

0/20

4/4

4/14

0/13

v3

v4

ts

v2

v112

8

10 4

5 7

20

4

10

13

4

4

4

4

v3

v4

ts

v2

v1

12/16

12/12

0/100/4

4/9

0/7

8/20

4/4

4/14

0/13

v3

v4

ts

v2

v14

10 4

5 7

12

4

10

13

12

4

4

12

8

98

Page 99: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Cammino p3 = 〈s, v2, v4, v3, t〉 , cf (p3) = 7

v3

v4

ts

v2

v1

12/16

12/12

0/100/4

4/9

7/7

15/20

4/4

11/14

7/13

v3

v4

ts

v2

v14

10 4

5 7

5

4

3

7

12

4

11

12

15

6

Cammino p4 = 〈s, v2, v3, t〉 , cf (p4) = 4

v3

v4

ts

v2

v1

12/16

12/12

0/100/4

0/9

7/7

19/20

4/4

11/14

11/13

v3

v4

ts

v2

v14

10 47

1

4

3

2

12

11

12

19

11

9

Nella rete residua non esistono piu cammini aumentanti; infatti, l’arco (v4, t) e saturo e, anche sel’arco (v3, t) ha capacita residua 1, non e saturabile poiche il vertice v3 non e piu raggiungibile: il flussomassimo, dunque, e quello illustrato nell’ultima figura.

Problemi

L’algoritmo, anche con grafi semplici, potrebbe avere costo di esecuzione molto elevato; consideriamoquello in figura:

ts

v2

v1

100000

100000100000

100000

1

Supponiamo che l’algoritmo faccia ripetutamente le seguenti scelte:

• cammino 〈s, v1, v2, t〉 di capacita 1;

• cammino 〈s, v2, v1, t〉 di capacita 1.

evidente che si tratta di scelte infelici, che aumentano enormemente il tempo di esecuzione, ma e altret-tanto vero che l’algoritmo non vincola sulla scelta del cammino aumentante: un’ottimizzazione, moltosemplice da realizzare, sara descritta nel prossimo paragrafo.

15.4.1 Ottimizzazione di Edmond-Karp

L’ottimizzazione di Edmond-Karp consiste nello scegliere, ad ogni iterazione, il cammino aumentante dilunghezza minima tra tutti quelli possibili.

99

Page 100: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Definizione 15.11. Siano dati una rete di flusso G con sorgente s e pozzo t e un flusso f in G; consideratoun nodo u, definiamo df(u) come la distanza (espressa come numero di archi) tra la sorgente s e il nodou nella rete residua Gf .

Lemma 15.4. Siano G = (V,E) rete di flusso, s sorgente e t pozzo; siano inoltre f flusso in G, Gf lacorrispondente rete residua, p cammino aumentante in Gf con il minimo numero di archi, g = f + fpflusso dato dall’algoritmo di Ford-Fulkerson con ottimizzazione di Edmond-Karp e Gg la corrispondenterete residua: allora, per ogni u ∈ V − s, t, si ha dg(u) ≤ df(u).

Proof. Procediamo per assurdo. Supponiamo che esista z ∈ V − s, t tale che dg(z) < df(z); allora,definendo:

W = z ∈ V − s, t : dg(z) < df(z)

si ha W 6= ∅. Sia v ∈W tale che dg(v) e minima tra tutti gli elementi di W ; valgono le seguenti proprieta:

1. dg(v) < df(v) poiche v ∈W ;

2. se u ∈ W , allora dg(v) ≤ dg(u), per quanto detto sopra; riscrivendo, se dg(v) > dg(u), allorau /∈ W , quindi dg(u) ≥ df(u) (abbiamo sfruttato il fatto che A ⇒ B e logicamente equivalente a¬B ⇒ ¬A).

Il fatto che dg(v) < df(v) ci dice che dg(v) e un valore finito (in quanto df(v) puo essere infinito), ovverov e raggiungibile da s in Gg. Definiamo q cammino minimo da s a u in Gg con il minor numero di archi;sia u l’ultimo vertice di q prima del vertice v (u esiste poiche v 6= s): poiche q e cammino minimo, alloraanche il sottocammino da s a u e minimo. Quindi:

dg(v) = dg(u) + 1→ dg(u) < dg(v)

Per il punto 2:dg(u) ≥ df(u)

Riassumendo, abbiamo u, v ∈ V con v 6= s tali che:

(a) dg(u) ≥ df(u);

(b) dg(v) = dg(u) + 1.

Sostanzialmente, abbiamo che u si sta allontanando dalla sorgente e vogliamo provare, per assurdo, chev si sta avvicinando!Utilizzando le proprieta a e b proviamo che cf (u, v) < 0 per ottenere un assurdo (in quanto le capacitaresidue sono positive per definizione); per fare cio, dimostriamo che non e possibile che cf (u, v) siamaggiore oppure uguale a zero.

Caso 1. cf (u, v) > 0. Se cf (u, v) > 0, allora nella rete residua Gf esiste l’arco (u, v) e, in particolare,si ha questa situazione:

s

u

v

cammino minimo

da s a v

cammino minimo

da s a u

Per la disuguaglianza triangolare, si ottiene:

df(v) ≤ df(u) + 1 ≤per a dg(u) + 1 =per b dg(v)

Dunque si ha df(v) ≤ dg(v); ma poiche v ∈ W , otteniamo un assurdo: dunque non puo esserecf (u, v) > 0.

Caso 2. cf (u, v) = 0. Se cf (u, v) = 0, allora (u, v) /∈ Ef , ossia (u, v) non e arco di Gf ; ricordiamo,inoltre, che (u, v) ∈ Eg, quindi la situazione puo essere schematizzata come segue:

100

Page 101: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

s

u

v

Gg

cammino q

Gf s

u

v

L’arco e apparso da Gf a Gg; l’unico modo per apparire e che ci sia stato un decremento di flussolungo (u, v), ossia un incremento di flusso lungo (v, u). (v, u) e un arco del cammino aumentante e, percome e fatto l’algoritmo, visto che il cammino aumentante e minimo, l’arco (v, u) si trova su un camminominimo da s a u.

Gfs

u

v

t

cammino minimo

da s a v

Segue che:

df(u) = df(v) + 1

→ df(v) = df(u)− 1

df(v) = df(u)− 1 ≤per a dg(u)− 1 =per b dg(v)− 2

Da questa relazione otteniamo df(v) < dg(v); ma poiche v ∈W , otteniamo un assurdo: dunque non puoessere cf (u, v) = 0.

Abbiamo dimostrato che non possiamo avere cf (u, v) > 0 e cf (u, v) = 0, dunque si ha necessariamentecf (u, v) < 0 e abbiamo trovato l’assurdo; quindi W = ∅ e la dimostrazione del lemma e conclusa.

Corollario 15.2. Se g e calcolato dopo f da Ford-Fulkerson con ottimizzazione di Edmond-Karp, alloradg(u) ≥ df(u),∀u ∈ V − s, t.

Teorema 15.2. Il numero totale di cicli dell’algoritmo di Ford-Fulkerson con ottimizzazione di Edmond-Karp e dell’ordine di O(m · n).

Proof. La dimostrazione si basa sul concetto di arco critico.

Definizione 15.12. Un arco critico e un arco (u, v) su un cammino aumentante p dove cf (u, v) = cf (p),ovvero cf (u, v) e minima su p.

Ad ogni iterazione ci sara almeno un arco critico, quello che viene saturato. Quante volte un arcopuo diventare critico? Consideriamo la rete residua Gf e prendiamo il cammino aumentante (con ilnumero minimo di archi); sia (u, v) arco critico: in Gf si ha df(v) = df(u) + 1, mentre in Gg l’arco (u, v)scompare. Affinche (u, v) sia nuovamente critico, deve ricomparire in una rete residua successiva, ovverol’arco (v, u) deve far parte di un cammino aumentante; immediatamente prima della riapparizione di(u, v), la situazione e la seguente:

Ghs

u

v

t

dh(u) = dh(v) + 1

101

Page 102: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Dal corollario, si ottiene dh(v) ≥ df(v), da cui dh(v) + 1 ≥ df(v) + 1; segue che:

dh(u) = dh(v) + 1 ≥ df(v) + 1 = df(u) + 2

da cui:dh(u) ≥ df(u) + 2

Affinche un arco sia raggiungibile, la distanza dev’essere al piu n, dunque un arco puo diventare criticoal piu n/2 volte: il numero di cammini aumentanti, quindi, e al massimo m · n/2.

Usando il teorema e considerando che ogni ciclo costa O(m), si ottiene che la complessita dell’algoritmodi Ford-Fulkerson con ottimizzazione di Edmond-Karp e O(m2 · n).

15.5 Abbinamento massimo nei grafi bipartiti

Definizione 15.13. Un grafo non orientato G = (V,E) si dice bipartito se:

• V = L ∪R, con L ∩R = ∅;

• E ⊆ L×R.

Definizione 15.14. Dato G = (V,E) grafo bipartito, un abbinamento in G e un insieme M di archi(M ⊆ E) tale che, per ogni (u, v), (w, z) ∈M , si ha u 6= w se e solo se v 6= z.

Definizione 15.15. Un abbinamento M e massimo se, per ogni abbinamento M ′, si ha |M | ≥ |M ′|.

Assumiamo che ogni vertice in G ne abbia almeno uno adiacente: possiamo ridurre il problemadell’abbinamento massimo al problema del flusso massimo aggiungendo supersorgente e superpozzo, dove:

• la supersorgente e collegata ai nodi di L con archi di capacita 1;

• i vertici di R sono collegati al superpozzo via archi di capacita 1.

Il flusso deve essere a valori interi, altrimenti si possono inviare valori frazionari e alcuni flussi costruibilinon rispettano la definizione di abbinamento.

Definizione 15.16. Dato un grafo bipartito G = (V,E) con L ∪ R = V , definiamo la rete di flussoG′ = (V ′, E′) associata:

Vertici: V ′ = V ∪ s, t;

Archi: E′ = (s, u) : u ∈ L ∪ (u, v) : u ∈ L ∧ v ∈ R ∧ (u, v) ∈ E ∪ (v, t) : v ∈ R;

Capacita:

c(x, y) =

1 se (x, y) ∈ E′

0 altrimenti

Osservazioni

• E ⊆ E′ → |E| ≤ |E′|;

• |E′| = |E|+ |L|+ |R|; poiche abbiamo assunto che ogni vertice abbia almeno un arco incidente, siha |E| ≥ |V | /2, da cui |V | ≤ 2 · |E|: dunque |E′| ≤ 3 · |E|.

Da questi due punti si ha che |E′| = Θ(|E|).

Definizione 15.17. Un flusso f in una rete di flusso G = (V,E) e a valori interi se f(u, v) e un valoreintero per ogni (u, v) ∈ V × V .

Lemma 15.5. Siano G un grafo bipartito e G′ la corrispondente rete di flusso:

(a) se M e abbinamento in G, allora esiste un flusso f in G′ tale che |M | = |f |;

(b) se f e un flusso a valori interi in G′, allora esiste un abbinamento M in G tale che |f | = |M |.

102

Page 103: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Proof.

Punto a. Sia M abbinamento in G; definiamo f ′ : V × V → R come segue:

• se (u, v) ∈M , poniamo:

– f(s, u) = f(u, v) = f(v, t) = 1;

– f(t, v) = f(v, u) = f(u, s) = −1;

• altrimenti f(u, v) = 0.

Valgono:

1. f e flusso in G′;

2. |f | = |M |.

Proviamo il seconda punto dal momento che, per quanto riguarda il primo, e facile verificare che su fvalgono le proprieta che caratterizzano un flusso.Consideriamo il taglio (s ∪ L,R ∪ t) in G′; si ha:

• f(s ∪ L,R ∪ t) = |M | poiche gli archi che danno contributo unitario al flusso sono tutti e soligli archi di M ;

• f(s ∪ L,R ∪ t) = |f | per il teorema 15.1.

Punto b. Sia f flusso in G′ a valori interi; valgono le seguenti proprieta:

1. f(u, v) > 0⇒ f(u, v) = c(u, v) = 1;

2. se u ∈ L:

• f(u, s) ∈ 0,−1;• f(u, L) = 0;

• se v ∈ R, f(u, v) ∈ 0, 1;• f(u, t) = 0;

3. se v ∈ R:

• f(v, s) = 0;

• f(v,R) = 0;

• se u ∈ L, f(v, u) ∈ 0, 1;• f(u, t) ∈ 0, 1;

4. f(s, t) = 0.

Definiamo:M = (u, v) : u ∈ L ∧ v ∈ R ∧ f(u, v) = c(u, v) = 1

Dobbiamo verificare che:

1. M ⊆ E;

2. M e abbinamento;

3. |f | = |M |.

Punto 1. Per ogni (u, v) ∈M , si ha c(u, v) = 1, quindi (u, v) ∈ E per definizione di G′: segue quindiche M ⊆ E.

Punto 2. Per verificare che M e abbinamento, dobbiamo mostrare che, se (u, v), (w, z) ∈ M , allorau 6= w e v 6= z; procediamo per assurdo, assumendo che la condizione non sia verificata, ovvero che u = wo v = z. Evitiamo di considerare il caso u = w e v = z, in quanto significa che abbiamo considerato duevolte lo stesso arco; rimangono due possibilita:

• u = w e v 6= z;

• u 6= w e v = z.

103

Page 104: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Consideriamo il primo punto; la situazione puo essere schematizzata come segue:

s u

v

z

1/1

1/1

? / 1

f(u, V ′) =∑v∈V ′

f(u, v) = f(u, s)︸ ︷︷ ︸≥1

+ f(u, L)︸ ︷︷ ︸=0

+f(u,R) + f(u, t)︸ ︷︷ ︸=0

≥ −1 + f(u,R)

= −1 + f(u, v)︸ ︷︷ ︸=1

+ f(u, z)︸ ︷︷ ︸=1

+ f(u,R− v, z)︸ ︷︷ ︸≥0

≥ −1 + 1 + 1 = 1

Otteniamo f(u, V ′) ≥ 1, contro il principio di conservazione del flusso; per quanto riguarda il sec-ondo punto, si puo procedere in maniera analoga. Abbiamo dunque trovato l’assurdo, quindi M e unabbinamento.

Punto 3. Consideriamo il taglio (L ∪ s , R ∪ t):

|f | = f(L ∪ s , R ∪ t) = f(L,R) + f(L, t)︸ ︷︷ ︸=0

+ f(s,R)︸ ︷︷ ︸=0

+ f(s, t)︸ ︷︷ ︸=0

= f(L,R)

=∑u∈Lv∈R

f(u, v) +∑u∈Lv∈R

f(u,v)>0

f(u, v) +∑u∈Lv∈R

f(u,v)=0

f(u, v)

︸ ︷︷ ︸=0

+∑u∈Lv∈R

f(u,v)<0

f(u, v)

︸ ︷︷ ︸=0

=∑u∈Lv∈R

f(u,v)=1

1

=∑

(u,v)∈M

1 = |M |

Corollario 15.3. Un abbinamento massimo in un grafo bipartito G corrisponde a un flusso massimo avalori interi nella rete di flusso associata G′ e viceversa.

Possiamo dunque risolvere il problema dell’abbinamento massimo usando un algoritmo di flusso mas-simo, a patto che quest’ultimo produca flussi a valori interi.

Teorema 15.3 (Teorema di integralita). Se la funzione di capacita assume solo valori interi e f e ilflusso massimo calcolato dall’algoritmo di Ford-Fulkerson, allora:

• |f | e intero;

• f(u, v) e intero per ogni (u, v) ∈ E.

La dimostrazione puo essere fatta per induzione sul numero di interazioni: si parte con f = 0 e siaggiorna con la capacita minima sul cammino aumentante, dove tale capacita e intera.

Complessita

Consideriamo la rete di flusso G′ = (V ′, E′) associata al grafo bipartito G = (V,E): come detto prece-dentemente, si ha V ′ = L ∪R ∪ s, t e |E′| = Θ(|E|). Sappiamo che:

• ogni iterazione del ciclo costa O(|E′|) = O(|E|);

• il numero di iterazioni eseguite e min(|L| , |R|): infatti, ad ogni ciclo il flusso e incrementato almenodi un’unita fino a raggiungere il valore massimo (e il numero massimo di archi dell’abbinamento eal piu min(|L| , |R|) ≤ |V |).

La complessita e quindi O(|V | · |E|).

104

Page 105: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

15.6 Caso di studio: segmentazione di immagini

Data un’immagine, si vuole suddividere i pixel che la compongono in due gruppi: quelli che costituisconoil soggetto in primo piano e quelli che fanno parte dello sfondo. Consideriamo l’immagine da analizzarecome un grafo non orientato dove:

• V e l’insieme dei pixel che compongono l’immagine;

• E e l’insieme delle coppie di pixel “vicini”.

Possiamo tenere la relazione di vicinanza vaga, in modo da risolvere il problema nella sua forma piugenerale; solitamente si ha:

Pixel: sono una rete di punti sul piano;

Vicinanza: i vicini di un punto sono i punti contigui nella rete.

Per ogni pixel u, inoltre, siano date:

• a(u): probabilita che u stia in primo piano;

• b(u): probabilita che u stia nello sfondo.

Non e necessario che a(u) e b(u) siano complementari; assumiamo inoltre che le probabilita siano valoriarbitrari non negativi e siano dati come parte del problema. In condizioni di isolamento, diremmo che:

• se a(u) > b(u), allora u e in primo piano;

• se b(u) > a(u), allora u e in secondo piano.

In generale, le decisioni che prendiamo sui vicini di u potrebbero influenzare la decisione su dove po-sizionare lo stesso u; l’idea e di rendere le etichette (sfondo / primo piano) uniformi, minimizzandoi passaggi tra primo piano e sfondo. Per fare cio definiamo, per ogni coppia (u, v) ∈ E, la quantitap(u, v) ≥ 0, detta separation penalty, che si deve pagare per piazzare uno tra u e v in primo piano e l’altrosullo sfondo.

Segmentation problem: trovare una partizione dell’insieme dei pixel V negli insiemi A e B dove:

• A contiene i pixel in primo piano;

• B contiene i pixel sullo sfondo;

in modo da massimizzare la quantita:

q(A,B) =∑u∈A

a(u) +∑v∈B

b(v)︸ ︷︷ ︸aumenta per

grandi probabilita

−∑

(u,v)∈E(u∈A∧v∈B)∨(u∈B∧v∈A)

p(u, v)

︸ ︷︷ ︸penalizza le coppie in cui

un elemento e in primo pianoe l’altro sullo sfondo

Possiamo cercare di ricavare la partizione (A,B) riducendoci a un problema di taglio minimo; ci sonopero alcune differenze:

1. la funzione obiettivo dev’essere massimizzata e non minimizzata;

2. il grafo non ha ne sorgente ne pozzo;

3. il grafo non e orientato.

Punto 1. Definiamo Q come segue:

Q =∑u∈V

(a(u) + b(u)) =∑u∈A

(a(u) + b(u)) +∑u∈B

(a(u) + b(u))

=∑u∈A

a(u) +∑u∈A

b(u) +∑u∈B

a(u) +∑u∈B

b(u)

105

Page 106: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

da cui: ∑u∈A

a(u) +∑u∈B

b(u) = Q−∑u∈A

b(u)−∑u∈B

a(u)

Riprendiamo la funzione quantita q:

q(A,B) = Q−∑u∈A

b(u)−∑u∈B

a(u)−∑

(u,v)∈E(u∈A∧v∈B)∨(u∈B∧v∈A)

Se definiamo:q′(A,B) =

∑u∈A

b(u) +∑u∈B

a(u) +∑

(u,v)∈E(u∈A∧v∈B)∨(u∈B∧v∈A)

possiamo scrivere:q(A,B) = Q− q′(A,B)

Possiamo concludere che massimizzare q equivale a minimizzare q′.

Punto 2. Aggiungiamo una supersorgente s che rappresenta lo sfondo, un superpozzo t che rappre-senta il primo piano e consideriamo V ′ = V ∪ s, t.

Punto 3. Trasformiamo ogni arco non orientato in una coppia di archi orientati.

Costruiamo la rete di flusso associata G′ = (V ′, E′), con:

• V ′ = V ∪ s, t;

• E′ = (u, v) : (u, v) ∈ E ∪ (v, u) : (u, v) ∈ E ∪ (s, u) : u ∈ V ∪ (u, t) : u ∈ V ;

• c : E′ → R+ definita come segue:

– per ogni (u, v) ∈ E:

∗ c(u, v) = p(u, v)

∗ c(v, u) = p(u, v)

– per ogni u ∈ V :

∗ c(s, u) = b(u)

∗ c(u, t) = a(u)

Sia (B ∪ s , A ∪ t) un taglio in G′:

c(B ∪ s , A ∪ t) = c(B,A) + c(B, t) + c(s,A) + c(s, t)︸ ︷︷ ︸=0

=∑u∈B

∑v∈A

c(u, v) +∑u∈B

c(u, t) +∑u∈A

c(s, u)

=∑u∈B

∑v∈A

p(u, v) +∑u∈B

a(u) +∑u∈A

b(u)

= q′(A,B)

Minimizzare q(A,B) equivale a minimizzare q′(A,B) che, a sua volta, equivale a trovare un tagliominimo (B ∪ s , A ∪ t) in G′.

Teorema 15.4. La soluzione al problema della segmentazione in un grafo G puo essere ottenuta con unalgoritmo di taglio minimo nella corrispondente rete di flusso G′. Ovvero, un taglio minimo (B∪s , A∪t) in G corrisponde alla partizione (A,B) che massimizza il valore di q(A,B).

106

Page 107: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Chapter 16

String matching

16.1 Introduzione

Informalmente, il problema del pattern matching consiste nel trovare le occorrenze di una stringa dicaratteri all’interno di un testo; definiamo:

• testo: array[1..n];

• pattern: array[1..m], con m ≤ n.

Gli elementi di T e P appartengono ad un alfabeto Σ e sono spesso chiamati caratteri.

Definizione 16.1. Il pattern P occorre nel testo T con uno spostamento s se 0 ≤ s ≤ n−m e ∀i = 1..msi ha T [s+ i] = P [i].

Definizione 16.2. Se P occorre in T con spostamento s, allora s si dice spostamento valido.

Alla luce di queste definizioni, il problema dello string matching puo essere visto nel seguente modo:dato un pattern P e un testo T , trovare tutti gli spostamenti validi con cui P occorre in T .

Notazione e definizioni

• Σ: alfabeto finito;

• Σ∗: insieme di tutte le stringhe di lunghezza finita formate con i caratteri in Σ;

• ε: stringa nulla (ε ∈ Σ∗).

• data x ∈ Σ∗, |x| indica la lunghezza della stringa, ovvero il numero di caratteri che la compongono(|ε| = 0);

• date x, y ∈ Σ∗, xy e la concatenazione delle stringhe x e y: vale |xy| = |x|+ |y|;

• date w, x ∈ Σ∗, w e prefisso di x (w < x) se x = wy, con y ∈ Σ∗; w e suffisso di x (w = x) sex = yw, con y ∈ Σ∗.

Osservazioni

Siano w, x ∈ Σ∗ con |w| = m e |x| = n:

• w < x se e solo se w occorre in x con spostamento 0;

• w = x se e solo se w occorre in x con spostamento n−m.

Se x = S[1..n], allora

• per ogni m, con 1 ≤ m ≤ n si ha:S[1..m] < S[1..n]

S[m..n] = S[1..n]

107

Page 108: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

• per ogni m, k con 1 ≤ m ≤ k ≤ n si ha:

S[1..m] < S[1..k]

S[k..n] = S[m..n]

Proprieta

• w < x⇒ |w| ≤ |x|;

• w = x⇒ |w| ≤ |x|;

• ε < x, ∀x ∈ Σ∗;

• ε = x, ∀x ∈ Σ∗;

• x < y ⇔ ax < ay;

• x = y ⇔ xa = ya;

• le relazioni < e = sono riflessive, antisimmetriche e transitive.

Lemma 16.1 (Sovrapposizione dei suffissi). Siano x, y ∈ Σ∗ tali che x = z e y = z; allora:

1. |x| < |y| ⇒ x = y;

2. |x| > |y| ⇒ y = x;

3. |x| = |y| ⇒ x = y;

Proof.

x

z

y

x

y

z

x

z

y

I grafici riassumono quanto si voleva dimostrare: da sinistra verso destra, primo, secondo e terzocaso.

In maniera speculare si puo enunciare e dimostrare il lemma della sovrapposizione dei prefissi; alla lucedi quanto e stato appena dimostrato, possiamo ridefinire nuovamente il problema dello string matching:dato il pattern P [1..m] e il testo T [1..n], con m ≤ n, trovare tutti gli spostamenti s nell’intervallo0 ≤ s ≤ n−m tali che P = Ts+m.

Assumiamo l’esistenza di una primitiva di confronto tra stringhe, che restituisce true se due stringhex, y ∈ Σ∗ sono uguali e false altrimenti; se il controllo viene fatto da sinistra verso destra e z e il piulungo prefisso comune tra x e y, allora la complessita di tale funzione e Θ(|z|+ 1).

16.2 Algoritmo ingenuo

L’idea sulla quale si basa l’algoritmo e di trovare gli spostamenti validi in un ciclo che verifica se P [1..m] =T [s+ 1..s+m] per ogni s tale che 0 ≤ s ≤ n−m.

algoritmo stringMatcherIngenuo (testo T, pattern P) → void

1 n = length(T)

2 m = length(P)

3 for s = 0 to n - m do

4 if(P[1..m] = T[s + 1..s + m]) then

5 stampa ‘‘occorrenza del pattern con spostamento s’’

108

Page 109: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Complessita

Il ciclo viene fatto n−m+ 1 volte e ad ogni iterazione pago t, dove t e la lunghezza del piu lungo prefissocomune tra P e la parte di testo considerata; nel caso pessimo si ha, ogni volta, t = m, da cui segue unacomplessita di Θ((n−m) ·m):

• se m << n, si ha Θ(n);

• se m ≈ n, si ha Θ(n);

• se m ≈ n/2, si ha Θ(n2).

16.3 String matching con automa a stati finiti

La caratteristica degli algoritmi di questo tipo e che esaminano ogni carattere del testo esattamente unavolta sola, da cui segue un tempo di matching pari a O(n); e pero necessaria una fase di preelaborazionein cui viene esaminato il pattern per costruire l’automa, che risulta essere costosa se Σ e grande.

16.3.1 Automi a stati finiti

Definizione 16.3. Un automa a stati finiti e una quintupla M = (Q, q0, A,Σ, δ) con:

• Q insieme finito di stati;

• q0 ∈ Q stato iniziale;

• A ⊆ Q insieme finito degli stati accettanti;

• Σ alfabeto finito in input;

• δ : Q× Σ→ Q funzione di transizione.

L’automa:

• parte dallo stato q0;

• legge i caratteri (in Σ) della stringa di input, uno alla volta;

• se si trova nello stato q e legge il carattere a, passa allo stato δ(q, a).

Se lo stato corrente sta in A, allora si dice che la macchina ha accettato la stringa letta finora; se lo statocorrente non sta in A, allora l’input letto finora e rifiutato.

Un automa induce una funzione φ : Σ∗ → Q sulle stringhe di input detta funzione stato finale; siaw ∈ Σ∗: φ(w) e lo stato in cui finisce l’automa dopo aver letto w partendo dallo stato iniziale.

Definizione 16.4. Se φ(w) ∈ A, allora si dice che l’automa accetta la stringa w.

Esempio 16.1. Il seguente e un automa che accetta la stringa “abaa”, con alfabeto a, b.

a

b a a

aa

b

b

b

b

Definizione 16.5. Fissato il pattern P [1..m], definiamo la funzione suffisso σ : Σ∗ → 0, 1, ...,massociata a P come:

σ(w) = max k : Pk = w

Esempio 16.2. Consideriamo il pattern P = “aab′′:

σ(ε) = 0 σ(“ccaba′′) = 1 σ(“cabaa′′) = 2 σ(“cabaab′′) = 3

Proprieta 16.1. Dati il pattern P [1..m] e la funzione σ, valgono le seguenti proprieta:

109

Page 110: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

1. σ(w) = m se e solo se Pm = w;

2. se w < v, allora σ(w) ≤ σ(v);

3. σ(Pk) = max h : Ph < Pk = k.

Definizione 16.6. Dato il pattern P [1..m], il corrispondente automa di string matching e definito comesegue:

• Q = 0, 1, ...,m;

• q0 = 0;

• A = m;

• Σ e l’alfabeto su cui e costruito P ;

• δ(q, a) = σ(Pqa).

16.3.2 L’algoritmo

Sfruttiamo ora l’automa di string matching per eseguire la fase di matching: diamo la stringa T da leggereall’automa e, ogni volta che passiamo sullo stato m, segnaliamo un occorrenza del pattern; in pratica,calcoliamo φ(Ti) per ogni prefisso Ti del testo T e, quando si ha φ(Ti) = m, e stata trovata un’occorrenza.

algoritmo finiteAutomaMatcher (testo T, funzione δ, intero m) → void

1 n = length(T)

2 q = 0

3 for i = 1 to n do

4 q = δ(q, T[i])

5 if(q = m) then

6 stampa ’’occorrenza del pattern con spostamento i - m’’

Complessita: O(n).

Invariante del ciclo: q = φ(Ti).

Correttezza

Per provare la correttezza dell’algoritmo, dobbiamo dimostrare che φ(Ti) = σ(Ti).

Lemma 16.2 (Disuguaglianza della funzione suffisso). Per ogni w ∈ Σ∗ e per ogni a ∈ Σ, si ha σ(wa) ≤σ(w) + 1.

Proof. Sia r = σ(wa):

• se r = 0, σ(wa) = 0 ≤ σ(w)︸ ︷︷ ︸≥0

+1

• se r > 0, Pr = wa, dunque Pr = Pr−1a con Pr−1 = w; dalla proprieta 2 segue che σ(Pr−1) ≤ σ(w)e dalla proprieta 3 si ha σ(Pr−1) = r − 1. Unendo queste due relazioni, si ottiene r ≤ σ(w) + 1, dacui σ(wa) ≤ σ(w) + 1.

Lemma 16.3 (Ricorsione della funzione suffisso). Dati w ∈ Σ∗, a ∈ Σ e posto q = σ(w), si ha σ(wa) =σ(Pqa).

Proof. Per provare l’uguaglianza, dimostriamo prima che σ(wa) ≥ σ(Pqa) e poi che σ(wa) ≤ σ(Pqa).

Prima parte: σ(wa) ≥ σ(Pqa).

q = σ(w)⇒ Pq = w

⇒ Pqa = wa

⇒ σ(Pqa) ≤ σ(wa)

110

Page 111: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Seconda parte: σ(wa) ≤ σ(Pqa). Sia r = σ(wa):

1. per il lemma 16.2 si ha σ(wa) ≤ σ(w) + 1, ossia r ≤ q + 1;

2. per definizione, si ha Pr = wa;

3. Pqa = wa (prima parte della dimostrazione);

4. dal punto 1, poiche |Pr| = r e |Pqa| = |Pq|+ 1 = q + 1, si ottiene |Pr| ≤ |Pqa|.

Unendo tutti questi fatti, si ottiene Pr = Pqa; dalla proprieta 2:

σ(Pr)︸ ︷︷ ︸=σ(wa)

≤ σ(Pqa)

Poiche abbiamo provato σ(wa) ≥ σ(Pqa) e σ(wa) ≤ σ(Pqa), si ottiene σ(wa) = σ(Pqa).

Teorema 16.1 (Teorema fondamentale degli automi di string matching). Siano M l’automa di stringmatching associato al pattern P [1..m] e φ la funzione stato finale indotta da M ; dato il testo T [1..n]allora, per ogni i = 1..n, vale φ(Ti) = σ(Ti).

Proof. Procediamo per induzione su i.

Caso base: si ha i = 0, ossia T0 = ε: φ(ε) = σ(ε) = 0.

Ipotesi induttiva: supponiamo φ(Tk) = σ(Tk) per k < i.

Passo induttivo: sia i > 0; per ipotesi si ha φ(Ti−1) = σ(Ti−1). Poniamo q = φ(Ti−1) = σ(Ti−1):

φ(Ti) = δ(φ(Ti−1), a) per def. di φ, con a = T [i]

= δ(q, a)

= σ(Pqa) per def. di δ nell’automa

= σ(Pσ(Ti−1)a) per ipotesi e per def. di q

= σ(Ti−1a) per il lemma 16.3

= σ(Ti) poiche a = T [i]

16.3.3 Costruzione dell’automa

Osservazione: viene scelto il minimo tra m+ 1 e q + 2 per non sforare nell’array; inoltre, entrambi sonoincrementati di una unita perche usiamo il ciclo repeat until.

Complessita

• il ciclo repeat until ha complessita O(m2) (ciclo innestato “nascosto” dalla notazione);

• complessivamente, ogni iterazione del for each costa O(|Σ| ·m2);

• in totale, l’algoritmo ha complessita O(|Σ| ·m3).

111

Page 112: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

16.4 Algoritmo di Knuth - Morris - Pratt

L’idea che sta alla base dell’algoritmo e la seguente: sapendo che i caratteri P [1..q] coincidono conT [s+ 1..s+ q], ci interessa sapere qual e lo spostamento minimo s′ > s tale che P [1..k] = T [s′+ 1..s′+ k]con s′ + k = s+ q; in particolare, l’intero k e il massimo valore tale per cui Pk = Pq, con k < q.

Definizione 16.7. Dato il pattern P [1..m], la funzione prefisso π : 1, 2, ...,m → 0, 1, ...,m− 1 edefinita come:

π(q) = max k : k < q ∧ Pk = Pq

Esempio. Consideriamo il pattern P = “ababababca” e calcoliamone la funzione prefisso:

i 1 2 3 4 5 6 7 8 9 10P [i] a b a b a b a b c aπ(i) 0 0 1 2 3 4 5 6 0 1

Calcoliamo la funzione prefisso usando la programmazione dinamica. Supponiamo di voler ricavare ilvalore di π(q); sia k = π(q − 1):

• se P [q] = P [k + 1], allora π(q) = k + 1;

• altrimenti, sia k′ = π(k): se P [q] = P [k′ + 1], allora π(q) = k′ + 1;

• altrimenti, sia k′′ = π(k′) e continua con il ragionamento... se arrivi a 0, allora π(q) = 0.

L’algoritmo che calcola la funzione prefisso e il seguente:

algoritmo computePrefixFunction (pattern P) → funzione prefisso

1 m = length(P)

2 π[i] = 0

3 k = 0

4 for q = 2 to m do

5 while(k > 0 && P[k + 1] != P[q]) do

6 k = π[k]7 if(P[k + 1] == P[q]) then

8 k = k + 1

9 π[q] = k

10 return π

Complessita (analisi “classica”)

Nel caso pessimo, all’iterazione q-esima, k puo decrementare q−1 volte; in totale, q iterazioni costano∑mq=2 q = O(m2).

Complessita (analisi amortizzata)

Il ciclo for viene ripetuto m− 1 volte in totale; per i = 0, 1, ...,m− 1, sia ki il valore di k all’uscitadell’i-esima iterazione: definiamo come potenziale φ(i) = ki. Per verificare che φ e un buon potenziale,dobbiamo provare c he φ(i) ≥ φ(0),∀i = 0..m − 1: all’inizio del ciclo for si ha φ(0) = 0 e, all’internodel ciclo, k viene decrementato fintanto che k > 0 (dunque non scende mai sotto lo zero) e puo essereincrementato al piu di un’unita; da questo fatto, si ha φ(i) ≥ 0 = φ(0)∀i = 0..m− 1.

Ci + φ(i− 1) = Ci + φ(i)→ Ci = Ci + φ(i)− φ(i− 1)

= Ci + ki − ki−1

Nel ciclo while, ki−1 viene decrementato si volte (con si < ki−1), poi nell’if viene incrementato unavolta:

Ci ≤ si + 1 ≤ ki−1 + 1

Inoltre si ha:ki ≤ ki−1 − si + 1

da cui:Ci ≤ si + 1 + ki−1 − si + 1− ki−1 = 2

Scegliamo come costo amortizzato C = 2 = O(1): dunque m iterazioni ci vengono a costare O(m).

112

Page 113: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Correttezza

Prima di procedere con la dimostrazione, definiamo:

π(i)(q) =

q se i = 0

π(π(i−1)(q)) se i > 0

e sia:π∗(q) =

π(1)(q), π(2)(q), ..., π(t)(q) = 0

Lemma 16.4 (Iterazione della funzione prefisso). Sia P [1..m] il pattern e π la funzione prefisso; presoq = 1..m, π∗(q) = k : k < q ∧ Pk = Pq.

Proof. Suddividiamo la dimostrazione in due parti: prima proviamo che π∗(q) ⊆ k : k < q ∧ Pk = Pq epoi che π∗(q) ⊇ k : k < q ∧ Pk = Pq.

Prima parte. Per dimostrare che π∗(q) ⊆ k : k < q ∧ Pk = Pq ci basta provare che Pπ(i)(q) = Pqper ogni i = 1..t; procediamo per induzione su i.

Caso base: si ha i = 1:Pπ(1)(q) = Pq → Pπ(q) = Pq

La relazione e verificata per definizione di π.

Ipotesi induttiva: supponiamo la proprieta valida per i− 1, ossia Pπ(i−1)(q) = Pq.

Passo induttivo: sia i > 1:

Pπ(i)(q) = Pπ(π(i−1)(q)) =per def. di π Pπ(i−1)(q) = Pq

Seconda parte. Proviamo ora che π∗(q) ⊇ k : k < q ∧ Pk = Pq. Procediamo per assurdo, as-sumendo che k : k < q ∧ Pk = Pq − π∗(q) 6= ∅; sia j il piu grande valore presente in tale insieme: perdefinizione, π(q) = max k : k < q ∧ Pk = Pq, quindi j 6= π(q) poiche π(q) ∈ π∗(q) e j < π(q). Sia j′ ilpiu piccolo intero in π∗(q) tale che j < j′:

Pj

Pq

Pj'

j j' π(q) q

π*(q)

j ∈ k : k < q ∧ Pk = Pq ⇒ Pj = Pq

j′ ∈ π∗(q) ⊆ k : k < q ∧ Pk = Pq ⇒ Pj′ = Pq

dunque si ha:Pj = Pj′

Inoltre:

π(j′) = max k : k < q ∧ Pk = Pq ⇒ j ≤ π(j′)

e, da questa relazione:

j ≤ π(j′) < j

possiamo concludere che:j = π(j′)

in quanto π(j′) non puo essere maggiore di j per definizione di j′ e non si puo avere π(j′) < j; abbiamotrovato l’assurdo, poiche π(j′) = j ∈ π∗(q), contrariamente a quanto avevamo assunto.

Avendo dimostrato le due inclusioni, si ottiene l’uguaglianza desiderata.

Lemma 16.5. Siano P [1..m] pattern e π funzione prefisso: preso q = 1, 2, ...,m, se π(q) > 0, alloraπ(q)− 1 ∈ π∗(q − 1).

Proof. Sia r = π(q) > 0: allora si ha r < q e Pr = Pq; possiamo inoltre dire che r − 1 < q − 1 ePr−1 = Pq−1. Per il lemma 16.4 si ha r − 1 ∈ π∗(q − 1) e, per definizione di r, si ottiene la relazione chesi voleva dimostrare.

113

Page 114: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Definizione 16.8. Sia q = 1, 2, ...,m; definiamo Eq−1 ⊆ π∗(q−1), ossia l’insieme su cui lavora l’algoritmo,come segue:

Eq−1 = k ∈ π∗(q − 1) : P [k + 1] = P [q]= k : k < q − 1 ∧ Pk = Pq−1 ∧ P [k + 1] = P [q]= k : k + 1 < q ∧ Pk+1 = Pq

In altri termini, Eq−1 e composto dai valori k ∈ π∗(q − 1) per i quali e possibile estendere Pk a Pk+1

e ottenere un suffisso proprio di Pq.

Corollario 16.1. Siano P [1..m] pattern e π funzione prefisso: preso q = 2, ...,m vale

π(q) =

0 se Eq−1 = ∅1 + maxk ∈ Eq−1 altrimenti

Proof.

• Se Eq−1 = ∅, allora k : k < q ∧ Pk+1 = Pq = ∅ da cui si ottiene π(q) = 0.

• Se Eq−1 6= ∅:

– preso k ∈ Eq−1 si ha k + 1 < q e Pk+1 = Pq; quindi, se k′ = maxk ∈ Eq−1 si ottiene chek′ + 1 < q e Pk′+1 = Pq ovvero k′ ≤ π(q): utilizzando questa relazione, possiamo concludereche maxk ∈ Eq−1+ 1 ≤ π(q);

– sia r = π(q): abbiamo P [r] = P [q], che e equivalente a dire P [(r− 1) + 1] = P [q]; per il puntoprecedente si ha π(q) > 0, ovvero r > 0 e, per il lemma 16.5, si ha r− 1 ∈ π∗(q− 1). Da questidue fatti, si ricava che r − 1 ∈ Eq−1, ossia che r − 1 ≤ maxk ∈ Eq−1 e, per definizione di r,possiamo scrivere π(q) ≤ maxk ∈ Eq−1+ 1.

Da questi due punti si ottiene l’uguaglianza cercata.

Fase di matching

Lo pseudocodice dell’algoritmo che realizza la fase di matching e il seguente:

algoritmo kmpMatcher (testo T, pattern P)

1 n = length(T)

2 m = length(P)

3 π = computePrefixFunction(P)

4 q = 0

5 for i = 1 to n do

6 while(q > 0 && P[q + 1] != T[i]) do

7 q = π[q]8 if(P[q + 1] == T[i]) then

9 q = q + 1

10 if(q == m) then

11 stampa ‘‘Occorrenza di P con spostamento i - m’’

12 q = π[q]

Complessita (analisi “classica”)

Nel caso pessimo, il ciclo while (righe 6-7) costa O(m), dunque approssimiamo la complessita aO(m · n).

Complessita (analisi amortizzata)

Consideriamo il ciclo for alle righe 5 - 11; esso viene eseguito, in totale, n+ 1 volte. Definiamo comepotenziale:

φ(i) = valore di q all’uscita dell’i-esima iterazione.

Affinche φ sia un buon potenziale, si deve avere φ(i) ≥ φ(0),∀i = 0..n. All’inizio del ciclo si ha φ(0) = 0e, all’interno, q viene decrementato, ma non scende mai sotto lo zero, e poi puo essere incrementato alpiu di un’unita; da questo fatto, si ha φ(i) ≥ 0 = φ(0)∀i = 0..n, dunque φ e un buon potenziale.

114

Page 115: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

All’iterazione i-esima, nel ciclo while, qi−1 viene decrementato esattamente si volte (con si ≤ qi−1),poi alla riga 8 puo essere incrementato una volta, dunque otteniamo:

qi ≤ qi−1 − si + 1

L’iterazione i-esima costa:Ci ≤ si + 1

Calcoliamo il costo amortizzato:Ci + φ(i− 1) = Ci + φ(i)

ossia:Ci = Ci + φ(i)− φ(i− 1)

= Ci + qi − qi−1

≤ si + 1 + qi−1 − si + 1− qi−1 = 2

Il costo amortizzato dell’i-esima iterazione e C = 2 = O(1), dunque n iterazioni del ciclo for ci vengonoa costare O(n).

La complessita totale dell’algoritmo di Knuth-Morris-Pratt risulta essere O(n+m).

Relazione con gli automi a stati finiti

δ(q, T [i]) = 0 oppure δ(q, T [i])− 1 ∈ π∗(q)

Proof. Sia k = δ(q, T [i]); per definizione, σ(PqT [i]) = k, da cui Pk = PqT [i]. Se k = 0 ci troviamo nelprimo caso, altrimenti, se k > 0, si ha Pk−1 = Pq, dunque k − 1 ∈ π∗(q); dalla definizione di k si ottienela relazione cercata.

115

Page 116: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

116

Page 117: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Chapter 17

Geometria computazionale

Definizione 17.1. Una combinazione convessa di due punti p1 = (x1, y1) e p2 = (x2, y2) e un qualsiasipunto p3 = (x3, y3) tale che

x3 = α · x1 + (1− α) · x2

y3 = α · y1 + (1− α) · y2

con α ∈ [0, 1].

Definizione 17.2. Dati p1 e p2, il segmento di retta p1p2 e l’insieme delle combinazioni convesse tra p1

e p2. Se l’ordine di successione degli estremi e rilevante, si parla di segmento orientato ~p1p2. Se p1 el’origine del piano cartesiano, consideriamo il segmento orientato ~p1p2 con il vettore ~p2.

Prodotto vettoriale (in R2)

x

y

0 x1x2

y1

y2

αθ

~p1 × ~p2 = det

(x1 x2

y1 y2

)= x1 · y2 − x2 · y1

x1 = |~p1| · cosα y1 = |~p1| · sinαx2 = |~p2| · cos(α+ θ) y2 = |~p2| · sin(α+ θ)

Sostituendo nella formula per il calcolo del determinante:

det

(x1 x2

y1 y2

)= |~p1| · cosα · |~p2| · sin(α+ θ)− |~p2| · cos(α+ θ) · |~p1| · sinα

= |~p1| · |~p2| · (sin(α+ θ) · cosα− cos(α+ θ) · sinα) = |~p1| · |~p2| · sin θ

Il valore calcolato non e altro che l’area del parallelogramma compreso tra ~p1 e ~p2 di base |~p1| e altezza|~p2| · sin θ. Assumiamo che i due vettori siano non nulli; possono verificarsi tre casi:

• |~p1| · |~p2| · sin θ = 0: allora si ha sin θ = 0, ossia θ = 0, π, dunque ~p1 e ~p2 sono collineari (hanno lastessa direzione);

117

Page 118: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

• |~p1| · |~p2| · sin θ > 0: poiche i moduli sono non negativi per definizione, si ha sin θ > 0, ossia 0 < θ π:per sovrapporre ~p1 a ~p2 con rotazione minima, si deve ruotare ~p1 in senso antiorario (o ~p2 in sensoorario);

• |~p1| · |~p2| · sin θ < 0: si ha sin θ < 0, ossia π < θ 2 ·π: per sovrapporre ~p1 a ~p2 con rotazione minima,si deve ruotare ~p1 in senso orario (o ~p2 in senso antiorario).

In generale, se ~p1 e ~p2 non hanno inizio nell’origine degli assi bens in P0, indichiamo con

p1 − p0 = (x1 − x0, y1 − y0)

p2 − p0 = (x2 − x0, y2 − y0)

una tralsazione che porta l’origine in P0; ora e sufficiente calcolare il prodotto (p1 − p0) × (p2 − p0) eprocedere come sopra.

Il problema della svolta

Si vuole determinare se due segmenti consecutivi svoltano a destra oppure a sinistra.

θ

p0

p1

p2

θp0

p1

p2

sin θ > 0 sin θ < 0

Calcoliamo (p1 − p0)× (p2 − p0):

• se e positivo, la svolta e a sinistra;

• se e negativo, la svolta e a destra;

• se e nullo, vado dritto (o torno indietro).

17.1 Intersezione tra segmenti

Proprieta 17.1. Due segmenti si intersecano se e solo se una o entrambe le seguenti condizioni sonoverificate:

1. ogni segmento taglia la retta che contiene l’altro (questo succede se i due estremi non stanno nellostesso semipiano dei due individuati dalla retta);

2. un estremo di un segmento giace sull’altro segmento.

Consideriamo i segmenti p1p2 e p3p4:

• Per ogni punto pi, calcola di che e definita come la direzione di pi rispetto all’altro segmento:

d1 = (p1 − p3)× (p4 − p3)

d2 = (p2 − p3)× (p4 − p3)

d3 = (p3 − p1)× (p2 − p1)

d4 = (p4 − p1)× (p2 − p1)

• Se 0 /∈ d1, d2, d3, d4, d1 e d2 di segno opposto, d3 e d4 di segno opposto, allora i segmenti siintersecano (caso “normale”).

118

Page 119: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

• Se d1 = 0, x1 compreso tra x3 e x4 e y1 compreso tra y3 e y4, allora i segmenti si intersecano (p1

giace sull’altro segmento).

• Procedi in maniera analoga per d2, d3 e d4.

• Altrimenti i segmenti non si intersecano.

Complessita: O(1)

17.1.1 Ricerca di un’intersezione tra diversi segmenti

Dati n segmenti nel piano, si vuole determinare se almeno due si intersecano, sotto le seguenti ipotesisemplificative:

• nessun segmento e verticale;

• non esistono tre segmenti che si intersecano nello stesso punto.

Per risolvere il problema utilizziamo la tecnica di sweeping verticale: una retta immaginaria, detta rettadi sweeping, passa attraverso l’insieme degli oggetti geometrici da sinistra verso destra; in questo modo,essi vengono ordinati dal passaggio della retta. L’algoritmo considera tutti gli estremi dei segmentiordinatamente da sinistra a destra e, ogni volta che ne trova uno, verifica se c’e stata un’intersezione.

Ordinare i segmenti

La retta verticale scrorre e interseca i segmenti; poiche non ce ne sono di verticali, ciascuno interseca laretta di sweeping in un solo punto: possiamo ordinare i segmenti in funzione delle ordinate dei punti diintersezione.

Definizione 17.3. Data una retta verticale r e due segmenti s1 e s2:

• s1 e s2 sono confrontabili in r se r interseca sia s1 che s2;

• s1 e sopra s2 in r (s1 >r s2) se s1 e s2 sono confrontabili in r e l’intersezione di s1 con r sta sopral’intersezione di s2 con r.

Osservazione: >r definisce un ordine totale tra i segmenti che intersecano r.

Verificare l’ordine

Siano r retta verticale e p1p2, p3p4 segmenti: se questi non si intersecano, il loro ordine relativo e lo stessoper ogni retta di sweeping verticale. Poiche p1p2 e p3p4 non sono verticali, scegliamo p1 e p3 come gliestremi piu a sinistra; sia p1, tra i due, quello piu a sinistra:

(p3 − p1)× (p2 − p1)

> 0 se p1p2 >r p3p4

< 0 se p3p4 >r p1p2

0 non si verifica

p1

p3

p4

p2

r s

Se due segmenti si intersecano, quando la retta di sweep-ing supera il punto di intersezione, le posizioni dei segmentinell’ordine generato si invertono:

a >r b

b >s a

119

Page 120: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Poiche non ci possono essere tre segmenti che si intersecano in un punto, deve esistere qualche rettaverticale per la quale i due segmenti diventano consecutivi secondo l’ordine indetto.

Spostare la retta di sweeping

Gestiamo due insiemi di dati:

1. stato della retta di sweeping: relazioni tra gli oggetti intersecati dalla retta;

2. lista dei punti evento: insieme di coordinate x ordinate da sinistra a destra che definisce le posizionidi arresto della retta di sweeping.

Lo stato della retta di sweeping puo cambiare solo nei punti evento.

In questo caso fissiamo i punti evento in maniera statica:

• punti evento: ogni estremo di un segmento;

• ordine: ordiniamo gli estremi dei segmenti per coordinata x, da sinistra a destra. Se due estremisono sulla stessa verticale, mettiamo gli estremi sinistri prima di quelli destri: tra due estremientrambi sinistri (o entrambi destri) sulla stessa verticale, mettiamo prima quello con ordinataminore;

• inseriamo un segmento nella retta di sweeping quando questa incontra il suo estremo sinistro;

• togliamo un segmento dalla retta di sweeping quando questa incontra il suo estremo destro.

Quando due estremi diventano consecutivi nell’ordine indotto dalla retta di sweeping, verifichiamo se siintersecano.

Stato della retta di sweeping

Ordine totale T che supporta le seguenti operazioni:

insert(T, s) → voidInserisce il segmento s in T .

delete(T, s) → voidCancella il segmento s da T .

above(T, s) → segmentoRestituisce il segmento che si trova immediatamente sopra s.

below(T, s) → segmentoRestituisce il segmento che si trova immediatamente sotto s.

Implementando T con un albero AVL, tutte le operazioni hanno costo logaritmico al numero di nodidell’albero.

Confronto tra chiavi

Per eseguire il confronto tra le chiavi utilizziamo il prodotto vettoriale, avente complessita O(1).

Algoritmo

L’algoritmo che realizza la ricerca di un’intersezione all’interno di un’insieme di segmenti utilizzando laretta di sweeping e il seguente:

120

Page 121: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

algoritmo anySegmentsIntersect (insieme dei segmenti S ) → boolean

1 T = ∅2 Ordina gli estremi dei segmenti in S da sinistra a destra (risolvi i conflitti

come gi\‘a detto)

3 foreach p ∈ lista ordinata degli estremi do

4 if(p \‘e estremo sinistro di un segmento s) then

5 insert(T, s)

6 if(above(T, s) esiste ed interseca s || below(T, s) esiste ed interseca s)

then

7 return true

8 if(p \‘e estremo sinistro di un segmento s) then

9 if(esiste t = above(T, s) e u = below(T, s) e t interseca u) then

10 return true

11 delete(T, s)

12 return false

Correttezza

Teorema 17.1. La chiamata anySegmentsIntersect(S) restituisce true se e solo se esiste un’intersezionetra i segmenti di S.

Proof. Procediamo dimostrando i due versi dell’implicazione.

Prima parte: ⇒

Ovvio: l’algoritmo restituisce true quando trova effettivamente l’intersezione.

Seconda parte: ⇐

Supponiamo ci sia un’intersezione e sia p il punto di intersezione piu a sinistra (per risolvere eventualiuguaglianze sulla coordinata x, scegliamo il punto con ordinata minore); siano inoltre a e b i segmentiche si intersecano in p. Prima di p non ci sono intersezioni, quindi l’ordine dato da T e corretto; poichenon ci sono tre segmenti che si incontrano in p, esiste una retta di sweeping k per la quale a e b diventanoconsecutivi. La retta k sta a sinistra di p o passa per p: sia q l’evento corrispondente alla retta k. Cipossono essere due possibilita per le azioni intraprese per il punto d’arresto q:

• se a o b viene inserito in T , l’altro segmento si trova effettivamente sopra o sotto a quello inseritoe l’intersezione viene rilevata al primo controllo;

• se a e b sono gia presenti in T e viene cancellato un segmento tra essi nell’ordine totale, a e bdiventano consecutivi e l’intersezione viene trovata al secondo controllo.

Complessita

Sia |S| = n:

1. O(1)

2. O(n · log n)

3-11. ogni iterazione costa O(log n), per un totale di O(n · log n)

12. O(1)

Totale: O(n · log n)

17.2 Inviluppo convesso

Definizione 17.4. Un poligono e una regione del piano delimitata da una successione ordinata di puntip1, ..., pn detti vertici e segmenti p1p2, ..., pnp1 detti lati, con la proprieta che due lati consecutivi siintersecano solo in corrispondenza del vertice comune.

121

Page 122: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Definizione 17.5. Un poligono e semplice se ogni coppia di lati non consecutivi ha intersezione vuota(ossia non ci sono lati non consecutivi che si incrociano).

Teorema 17.2 (Teorema della curva di Jordan). Un poligono semplice partiziona il piano in due regionidistinte:

• interna (limitata);

• esterna (illimitata).

Percorrendo la frontiera del poligono in senso antiorario, l’interno rimane sempre a sinistra.

Rappresentiamo un poligono con la sequenza dei suoi vertici p1, ..., pn ordinata in senso antiorario.

Definizione 17.6. Un poligono semplice e convesso se la regione interna e convessa ovvero, presi duedei suoi punti interni, il segmento che li congiunge e tutto contenuto nella regione interna.

Definizione 17.7. Dato un insieme di punti P, l’involucro convesso di P (indicato con CH(P)) e il piupiccolo poligono convesso C tale che ogni punto di P si trova sulla frontiera o all’interno di C.

Proprieta 17.2. I vertici di CH(P) sono punti di P.

Usiamo questa proprieta per costruire l’algoritmo; definiamo P = p1, p2, ..., pn.

17.2.1 Algoritmo “brute force”

Si basa sull’idea che la retta che passa per due punti consecutivi del perimetro dell’inviluppo convessolascia tutti gli altri punti del poligono dalla stessa parte:

• per ogni coppia di punti (pi, pj), se pipj × pipk e sempre maggiore o minore di zero, per ogni kdiverso da i e j, allora pipj ∈ CH(P);

• se ci sono piu punti allineati, tengo solo quelli piu distanti;

• ordino i punti per coordinata polare rispetto a un punto fissato.

Complessita

Ci sono(n2

)coppie possibili e, per ogni coppia, occorre eseguire n − 2 confronti: la complessita totale e

O(n3).

17.2.2 Algoritmo di Jarvis

1

2 3

4

5

Si tratta di un algoritmo di complessita O(n · h), dove n e la car-dinalita di P e h il numero di punti che faranno parte dei verticidell’involucro convesso.

Si basa su rotazioni con fulcro variabile, a partire da un punto chesicuramente fara parte dell’inviluppo (quello piu a sinistra o piu adestra, piu in alto o piu in basso).

122

Page 123: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

17.2.3 Algoritmo di Graham

L’algoritmo utilizza la tecnica di sweeping di rotazione: elabora i vertici nell’ordine degli angoli polariche formano con un vertice di riferimento. Mantiene una pila S dei punti candidati a stare nell’involucroconvesso: ogni punto di P viene inserito una ed una sola volta in S e i vertici che non stanno in CH(P)vengono rimossi da S; al termine si ha S = CH(P) e contiene i vertici in ordine antiorario (se letta dalbasso verso l’alto).

La pila S, oltre alle operazioni tradizionali, deve offrire una funzione nextToTop che restituiscel’elemento della pila che sta “sotto” il top.

Come primo punto p0 scegliamo quello con ordinata minima (se ci sono piu punti con la stessaordinata, prendiamo quello piu a sinistra); allora p0 ∈ CH(P) in quanto non ha punti ne sotto, ne asinistra. Ordiniamo poi i punti in P − p0 in funzione degli angoli polari rispetto a p0 (confronto travettori con il prodotto vettoriale): nel caso siano presenti piu punti con lo stesso angolo polare, considerosolo quello piu distante da p0.

Siano p1, p2, ..., pm, con m ≤ n, i punti della sequenza ordinata ottenuta secondo l’ordine polare:osserviamo che p1 e pm appartengono sicuramente all’inviluppo convesso di P.

L’algoritmo che calcola l’inviluppo convesso di un insieme di punti P, di cardinalita maggiore o ugualea 3, e il seguente:

algoritmo grahamScan (insieme di punti P) → inviluppo convesso

1 Sia p0 il punto di P con ordinata minima (se pi\‘u punti hanno la stessa

ordinata minima , prendi quello pi\‘u a sinistra)

2 Siano p1, p2, ..., pm i restanti punti di P ordinati come detto precedentemente

3 push(p0, S)

4 push(p1, S)

5 push(p2, S)

6 for i = 3 to m do

7 while(l’angolo formato da nextToTop(S), top(S) e pi effettua una svolta non a

sinistra) do

8 pop(S)

9 push(pi, S)

10 return S

Correttezza

Teorema 17.3. Se grahamScan viene eseguito su un insieme di punti P, con |P| ≥ 3, alla fine Scontiene, dal basso verso l’alto, esattamente i vertici di CH(P) in ordine antiorario.

Proof. Dopo l’esecuzione della riga 2 abbiamo la sequenza p1, ..., pm; definiamo Pi = p0, p1, ..., pi:P − Pm e l’insieme dei punti rimossi perche avevano la stessa angolazione polare di un punto di Pm e,tra tutti, Pm contiene il piu distante, dunque si ha CH(P) = CH(Pm).

Dobbiamo provare che, al termine, S contiene tutti i vertici di CH(Pm) disposti in senso antiorario.Osserviamo inoltre che, per ogni i compresa tra 2 e m vale la seguente proprieta:

p0, p1, pi ∈ CH(Pi)

Per la dimostrazione, proviamo il seguente invariante del ciclo for:

All’inizio di ogni iterazione i, S contiene, dal basso verso l’alto, esattamente i vertici diCH(Pi−1) in ordine antiorario.

Inizializzazione: si ha i = 3: Pi−1 = p0, p1, p2 = CH(P2) e appaiono in ordine antiorario dalbasso verso l’alto.

Mantenimento: sia i > 3; all’inizio dell’iterazione, il punto in cima alla pila e pi−1. Sia pj il primopunto che da una svolta a sinistra: dopo il ciclo while, la pila contiene esattamente gli stessi elementiche conteneva dopo l’iterazione j del ciclo for, ossia contiene i vertici di CH(Pj) in ordine antiorariodal basso verso l’alto. Dopo l’inserimento di pi, S contiene esattamente i vertici di CH(Pj ∪ pi) in

123

Page 124: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

senso antiorario: dobbiamo provare che CH(Pj ∪ pi) = CH(Pi). Sia pt un punto che e stato rimossodurante l’iterazione i-esima del ciclo for: quando pt e stato rimosso, si trovava nella parte interna di

p04pr pi, dunque CH(Pi − pt) = CH(Pi). Ripetendo il ragionamento per tutti i vertici tolti, si ha

CH(Pi − vertici tolti) = CH(Pi), dunque S = CH(Pj ∪ pi) = CH(Pi).

Terminazione: al termine i = m+ 1, dunque S = CH(Pm) = CH(P) in ordine antiorario.

Complessita

Sia |P| = n:

1. O(1)

2. O(n · log n)

3-5. O(1)

6-9. per ogni iterazione si esegue una push, quindi in totale si fanno al massimo n pop, dunque lacomplessita del ciclo e O(n)

10. O(1)

Totale: O(n · log n)

17.2.4 Algoritmo Quick Hull

• Si considerano i punti p1 e pn che hanno l’ascissa minima e massima: la retta che li congiungepartiziona l’insieme dei punti in due insiemi che consideriamo uno alla volta.

• Sia S l’insieme dei punti che stanno sopra la retta che congiunge p1 e pn.

• Sia ph il punto di massima distanza dalla retta p1pn (ph appartiene all’inviluppo convesso).

• Consideriamo le due rette orientate ~p1ph e ~phpn:

– non ci sono punti a sinistra di entrambe;

– i punti a destra di entrambe sono interni a p14ph pn e possono non essere considerati;

– i punti che giacciono a destra di una retta e a sinistra dell’altra costituiscono i due insiemi S1

e S2 che sono esterni rispetto l’attuale involucro.

• La procedura si attiva ricorsivamente prendendo S1 e S2 separatamente come S.

Complessita

Caso pessimo: O(n2)

Caso medio: O(n · log n)

124

Page 125: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Chapter 18

Teoria della NP-completezza

18.1 Complessita di problemi decisionali

In generale, possiamo pensare ad un problema P come a una relazione P ⊆ I × S, dove I e l’insiemedelle istanze di ingresso e S quello delle soluzioni ; possiamo inoltre immaginare di avere un predicatoche, presa un’istanza x ∈ I ed una soluzione s ∈ S, restituisca 1 se (x, s) ∈ P (ovvero s e soluzione di Psull’istanza x), 0 altrimenti. Usando questa terminologia, possiamo definire una prima classificazione deiproblemi:

Problemi di decisione: sono problemi che richiedono una risposta binaria, dunque S = 0, 1; inparticolare, richiedono di verificare se l’istanza x soddisfa una certa proprieta.

Problemi di ricerca: data un’istanza x, questi problemi chiedono di restituire una soluzione s tale che(x, s) ∈ P .

Problemi di ottimizzazione: data un’istanza x, si vuole trovare la migliore soluzione s∗ tra tutte lepossibili soluzioni s per cui (x, s) ∈ P ; la bonta della soluzione e valutata secondo un criteriospecificato dal problema stesso.

I principali concetti della teoria della complessita computazionale sono stati definiti in termini deiproblemi di decisione: si osservi, comunque, che e possibile esprimere problemi di altre categorie informa decisionale (e la difficolta della forma decisionale e al piu pari a quella del problema iniziale),quindi caratterizzare la complessita di quest’ultimo permette di dare almeno una limitazione inferiorealla complessita del primo.

necessario fissare un po’ di notazione; dopo aver stabilito una codifica binaria efficiente dell’input,definiamo un problema decisionale P come una funzione, nel seguente modo:

P : 0, 1∗ → 0, 1

Inoltre, dato un problema decisionale P , definiamo il suo linguaggio come:

L =x ∈ 0, 1∗ : P (x) = 1

18.1.1 Classi di complessita

Dati un problema di decisione P ed un algoritmo A, diciamo che A risolve P se A restituisce 1 suun’istanza x se e solo se (x, 1) ∈ P . Inoltre, diciamo che A risolve P in tempo t(n) e spazio s(n) se iltempo di esecuzione e l’occupazione di memoria di A sono, rispettivamente, t(n) e s(n).

Definizione 18.1. Data una qualunque funzione f(n), chiamiamo Time(f(n)) e Space(f(n)) gli insiemidei problemi decisionali che possono essere risolti, rispettivamente, in tempo e spazio O(f(n)).

Definizione 18.2. La classe P e la classe dei problemi risolvibili in tempo polinomiale nella dimensionen dell’istanza di ingresso:

125

Page 126: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

P =

∞⋃c=0

Time(nc)

La classe PSpace e la classe dei problemi risolvibili in spazio polinomiale nella dimensione n dell’istanzadi ingresso:

PSpace =

∞⋃c=0

Space(nc)

La classe ExpTime e la classe dei problemi risolvibili in tempo esponenziale nella dimensione ndell’istanza di ingresso:

ExpTime =

∞⋃c=0

Time(2nc

)

Si hanno le seguenti relazioni tra le classi: P ⊆ PSpace ⊆ ExpTime; non e noto se le inclusioni sianoproprie o meno, in quanto sono quesiti di teoria della complessita ancora aperti.Inoltre, la classe P e considerata come una classe soglia tra problemi trattabili e intrattabili.

18.2 La classe NP

Spesso, in caso di risposta affermativa ad un problema di decisione, si richiede anche di fornire un qualcheoggetto y, dipendente dall’istanza x e dal problema specifico, che possa certificare il fatto che x soddisfila proprieta richiesta: tale oggetto e noto come certificato. Un certificato e definito come una stringabinaria y ed una funzione verificatrice

g : 0, 1∗ × 0, 1∗ → 0, 1

tale che x ∈ L se e solo se esiste y tale per cui g(x, y) = 1.Se g lavora in tempo polinomiale e y e di lunghezza polinomiale rispetto alla lunghezza di x, allora L everificabile in tempo polinomiale e per questo definiamo la classe di complessita NP: informalmente, essae la classe dei problemi decisionali che ammettono certificati verificabili in tempo polinomiale.

18.2.1 Non determinismo

Negli algoritmi visti finora, il passo successivo e sempre univocamente determinato dallo stato dellacomputazione: per tale motivo, sono detti deterministici ; un algoritmo non deterministico, invece, oltrealle normali istruzioni, puo eseguirne alcune del tipo indovina z ∈ 0, 1, ovvero puo ”‘indovinare”’ unvalore binario per z facendo proseguire la computazione in una ”‘giusta”’ direzione.

Definizione 18.3. Data una qualunque funzione f(n), chiamiamo NTime(f(n)) l’insieme dei problemidecisionali che possono essere risolti da un algoritmo non deterministico in tempo O(f(n)). La classe NPe la classe dei problemi risolvibili in tempo polinomiale non deterministico nella dimensione n dell’istanzadi ingresso:

NP =

∞⋃c=0

NTime(nc)

Un algoritmo non deterministico puo essere suddiviso in due fasi:

Fase non deterministica di costruzione: sfruttando la funzione indovina, l’algoritmo costruisce uncertificato per l’istanza del problema.

Fase deterministica di verifica: l’algoritmo verifica che il certificato prodotto sia effettivamente unasoluzione del problema per l’istanza data.

126

Page 127: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

18.2.2 La gerarchia

facile osservare che P ⊆ NP, poiche un algoritmo deterministico e un caso particolare di uno nondeterministico, in cui la funzione indovina non viene mai utilizzata. Inoltre, la fase deterministica diverifica puo essere condotta in tempo polinomiale solo se il certificato ha dimensione polinomiale, da cuiNP ⊆ PSpace; si congettura, ma nessuno e ancora riuscito a dimostrarlo, che entrambe le inclusionisiano proprie, ovvero:

P ⊂ NP ⊂ PSpace ⊂ ExpTime

P

NP

PSpaceExpTime

Si osservi che la gerarchia abbozzata, in realta, e ben piu complessa e vasta: infatti, esistono an-che problemi indecidibili, ovvero non risolubili indipendentemente dalla quantita di tempo e memoria adisposizione, come il problema della fermata.

18.3 Riducibilita polinomiale

Un linguaggio L1 e riducibile in tempo polinomiale a L2 se esiste una funzione calcolabile in tempopolinomiale

r : 0, 1∗ → 0, 1∗

tale che, per ogni x ∈ 0, 1∗, x ∈ L1 se e solo se r(x) ∈ L2. r e detta funzione di riduzione e scriviamoL1 ≤p L2.

Lemma 18.1. Siano L1, L2 ⊂ 0, 1∗ linguaggi tali che L1 ≤p L2: allora L2 ∈ P implica L1 ∈ P .

Proof. Visto che la funzione di riduzione lavora in tempo polinomiale, r(x) ha lunghezza polinomialerispetto alla lunghezza di x; ma un polinomio di un polinomio e ancora un polinomio, per cui r(x) ∈ L2

viene deciso in tempo polinomiale rispetto alla lunghezza di x.

18.4 Problemi NP-completi

Definizione 18.4. Un problema si dice NP-completo se:

• L ∈ NP;

• L′ ≤p L per ogni L′ ∈ NP.

Se vale solo la seconda condizione, L si dice essere NP-difficile; la classe dei problemi NP-completi sichiama NPC.

Consideriamo i seguenti problemi:

127

Page 128: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Satisfiability: una formula booleana in forma congiuntiva consiste in una serie di clausole congiunte,in cui ogni clausola e una serie di disgiunzioni di variabili, possibilmente negate; se ogni clausolacontiene meno di k variabili si dice k−CNF . Il problema e trovare un assegnamento booleano cherenda vera la formula: definiamo 3-SAT = x : x e una formula in forma 3-CNF che ha almeno unassegna mento che la rende vera.

Clique: e un sottinsieme di vertici di un grafo per cui ognuno e connesso ad ogni altro del sottinsieme.Ovviamente le coppie di vertici connesse for- mano delle clique, ma potrebbero esserci insiemi piugrandi a cui siamo interessati. Il linguaggio corrispondente e CLIQUE = 〈G, k〉 : G e un grafo conalmeno una clique di dimensione k.

Independent set: e un sottinsieme di vertici che non sono collegati l’uno con l’altro. Definiamo INDE-PENDENT SET = 〈G, k〉 : G e un grafo con almeno un independent set di dimensione k.

Assumiamo che 3-SAT sia NP-completo e vediamo come si puo ridurre il problema in tempo polino-miale a CLIQUE, e quest’ultimo ridurlo in tempo polinomiale a INDIPENDENT SET.

Prima parte: 3-SAT ≤p CLIQUE.

Presa una formula in forma 3-CNF con m clausole, costruiamo un grafo G che abbia un vertice per ognivariabile (o variabile negata) all’interno di ogni clausola, quindi un grafo con 3 ·m vertici. Colleghiamotra loro due vertici se e solo se appartengono a clausole diverse e non rappresentano la stessa variabilenegata, ossia non sono una coppia della forma (x, x). La funzione r(φ) restituisce una coppia 〈G,m〉lavora in tempo polinomiale, e ci chiediamo se φ ∈ 3-SAT se e solo se 〈G,m〉 ∈ CLIQUE.Se G contenesse una clique di dimensione m, questa avrebbe un vertice in ogni clausola e ci consentirebbedi trovare un’assegnazione che soddisfa φ senza incappare in una contraddizione. Viceversa se avessimoun’assegnazione che soddisfa φ, potremmo scegliere da ogni clausola una variabile con valore ”‘vero”’, dalmomento che le m variabili scelte hanno tutte lo stesso valore, quindi dovrebbero essere collegate l’unacon l’altra nel grafo, formando una clique.

Seconda parte: CLIQUE ≤p INDEPENDENT SET.

Dato un grafo G, consideriamo il suo complementare G: e sufficiente osservare che un sottoinsieme divertici e una clique in G se e solo se e un independent set in G.

18.5 La classe coNP e la relazione tra P e NP

Definizione 18.5. Il complemento di un linguaggio L ⊂ 0, 1∗ e l’insieme delle stringhe x /∈ L.

Definizione 18.6. La classe coNP consiste di linguaggi il cui complemento appartiene a NP:

coNP =L : L ∈ NP

Si ha P ⊆ coNP e P = coP , da cui P ⊆ NP ∩ coNP ; questo, a sua volta, implica P = NP ⇒ coP =

coNP ⇒ NP = coNP . Quindi NP 6= coNP ⇒ P 6= NP . Ci sono quattro possibilita:

• P = NP = coNP ;

• P ⊂ NP = coNP ;

• P = coNP ∩NP, coNP ∩NP 6= NP,NP 6= coNP ;

• P ⊂ coNP ∩NP, coNP ∩NP 6= NP,NP 6= coNP .

Nonostante la ricerca sia ancora aperta, generalmente si ritiene che P 6= NP , in quanto si ritienestrano che cercare una risposta sia tanto facile quanto riconoscerla.

128

Page 129: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Chapter 19

Appendice

19.1 Serie aritmetica

Lemma 19.1. La somma dei primi n numeri consecutivi ha il seguente valore:

n∑i=1

i =n · (n+ 1)

2

Proof. Definiamo

Sn =

n∑i=1

i

Possiamo scrivere:

Sn = 1 + 2 + ...+ n

Sn = n+ (n− 1) + ...+ 1

Sommando membro a membro, si ottiene 2·Sn = n·(n+1), da cui segue quanto si vuole dimostrare.

19.2 Serie geometrica

Lemma 19.2. La serie geometrica di ragione q, i cui addendi sono caratterizzati dall’avere una basecostante q 6= 1 ed un esponente variabile, ha il seguente valore:

k∑i=0

qi =qk+1 − 1

q − 1

Proof. Sia

Sk(q) =

k∑i=0

qi

Moltiplicando ambo i membri per q, si ha:

q · Sk(q) =

k+1∑i=1

qi

Sottraendo Sk(q) ad entrambi i membri, si ottiene:

(q − 1) · Sk(q) =

k+1∑i=1

qi −k∑i=0

qi = qk+1 − 1

da cui

129

Page 130: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Sk(q) =qk+1 − 1

q − 1

come volevamo dimostrare.

19.3 Calcolo di somme per integrazione

Sono valide le seguenti disuguaglianze:

• se f(x) e una funzione non decrescente:∫ b

a−1

f(x)dx ≤b∑i=a

f(i) ≤∫ b+1

a

f(x)dx

• se f(x) e una funzione non crescente:∫ b+1

a

f(x)dx ≤b∑i=a

f(i) ≤∫ b

a−1

f(x)dx

19.4 Goniometria e trigonometria

Ricordiamo alcune relazioni goniometriche utili per il capitolo di geometria computazionale:

sin(x+ y) = sinx · cos y + sin y · cosx

sin(x− y) = sinx · cos y − sin y · cosx

cos(x+ y) = cosx · cos y − sinx · sin ycos(x− y) = cosx · cos y + sinx · sin y

e un paio di equazioni di trigonometria:

ac

b

α

β

a = c · sinα = c · cosβ

b = c · cosα = c · sinβ

130

Page 131: Appunti di Algoritmi e Strutture Datiacarraro/Tutorato-ASD-Carraro-2014.pdf · Chapter 1 Introduzione informale agli algoritmi De nizione 1.1. Un algoritmo e un insieme di istruzioni,

Bibliography

[1] C. Demetrescu, I. Finocchi, G.F. Italiano, Algoritmi e strutture dati 2/ed. McGraw-Hill, 2008.

[2] T.H. Cormen, C.E. Leiserson, R.L. Rivest, C. Stein, Introduzione agli algoritmi e strutture dati 3/ed,McGraw-Hill, 2010.

131