Concetti di base di complessità degli algoritmi
|
|
- Annunziata Gagliardi
- 5 anni fa
- Visualizzazioni
Transcript
1 Concetti di base di complessità degli algoritmi
2 Problemi, algoritmi, programmi Problema: il compito da svolgere quali output vogliamo ottenere a fronte di certi input cioè quale funzione vogliamo realizzare Algoritmo: i passi (il processo) da seguire per risolvere un problema un algoritmo prende gli input in ingresso ad un problema e li trasforma in opportuni output Come al solito, un problema può essere risolto da tanti algoritmi Un algoritmo è una sequenza di operazioni concrete deve essere eseguibile da una macchina Un algoritmo deve essere corretto deve calcolare la funzione giusta sappiamo che determinare la correttezza di un algoritmo è un problema indecidibile questo però non vuole dire che non si possa fare niente per cercare di capire se un algoritmo è corretto o no
3 Linguaggi di programmazione Un algoritmo può essere descritto in diversi linguaggi se usiamo un linguaggio di programmazione (C, C++, Java, C#, ecc.) abbiamo un programma Come linguaggio noi usiamo... lo pseudocodice non è un vero linguaggio di programmazione, ma ci assomiglia molto facile da tradurre in codice di un linguaggio di programmazione quale C o Java (o Python) il particolare linguaggio di programmazione con cui un algoritmo è implementato è, dal punto di vista della complessità, un po come l'hardware: ci cambia solo le costanti moltiplicative
4 Primo esempio di algoritmo Problema: ordinamento Input: una sequenza A di n numeri [a 1, a 2,... a n ] Output: una permutazione [b 1, b 2,... b n ] della sequenza di input tale che b 1 b 2... b n Algoritmo: insertion sort INSERTION-SORT(A) 1 for j := 2 to A.length 2 key := A[j] 3 //Inserisce A[j] nella sequenza ordinata A[1..j 1] 4 i := j 1 5 while i > 0 and A[i] > key 6 A[i + 1] := A[i] 7 i := i 1 8 A[i + 1] := key
5 Pseudocodice assegnamento: i := j assegnamento multiplo: i := j := e applicato da destra a sinistra cioè è la stessa cosa che scrivere j := e; i := j come in C: while, for, if-then-else // inizia un commento, che termina alla fine della riga la struttura a blocchi è data dall indentazione while i > 0 and A[i] > key A[i + 1] := A[i] i := i 1 A[i + 1] := key = while (i > 0 and A[i] > key) { A[i + 1] := A[i] i := i 1 } A[i + 1] := key
6 Variabili e array Le variabili sono locali alla procedura Agli elementi degli array si accede come in C A[j] è l'elemento di indice j dell'array A il primo elemento può avere un indice diverso da 0 C'è una nozione di sotto-array (slice) A[i..j] è il sotto-array che inizia dall'elemento i- esimo e termina all'elemento j-esimo e.g. A[1..5] è il sotto-array con i primi 5 elementi dell'array A
7 Oggetti e puntatori Dati composti sono organizzati in oggetti Gli oggetti hanno degli attributi (detti anche campi) per indicare il valore di un attributo attr di un oggetto x, scriviamo x.attr gli array rappresentano dati composti, quindi sono oggetti ogni array ha un attributo length, che contiene la lunghezza dell'array A.length è la lunghezza dell'array A Una variabile che corrisponde ad un oggetto (es. un array) è un puntatore all'oggetto molto simile ai puntatori in C e, soprattutto, al concetto di reference in Java per esempio, se abbiamo due variabili x e y, e x punta ad un oggetto con un attributo f, dopo le seguenti istruzioni y := x x.f := 3 si ha che x.f = y.f = 3, in quanto, grazie all'assegnamento y := x, x e y puntano allo stesso oggetto Un puntatore che non fa riferimento ad alcun oggetto ha valore NIL
8 Passaggio parametri I parametri sono passati per valore la procedura invocata riceve una copia dei parametri passati se una procedura PROC ha un parametro x e dentro PROC il parametro x riceve il valore di y (x := y), la modifica non è visibile al di fuori della procedura (per esempio al chiamante) Quando un oggetto è passato come parametro, ciò che viene passato è il puntatore all'oggetto degli attributi non viene fatta una copia, e modifiche a questi sono visibili al chiamante se x è un parametro che è un oggetto con attributo f, gli effetti dell'assegnamento x.f:=3 (il fatto che l'attributo f valga 3) sono visibili al di fuori della procedura questo è il funzionamento di Java...
9 Modello di computazione Quale è la macchina sulla quale vengono eseguiti gli algoritmi scritti in pseudocodice? La macchina RAM! Assunzione di base: ogni istruzione semplice di pseudocodice è tradotta in un numero finito di istruzioni RAM per esempio x := y diventa, se a x e a y sono gli l'indirizzi in memoria delle variabili x e y (a x e a y sono delle costanti): LOAD a y STORE a x
10 Criteri di costo Da ora in poi adottiamo il criterio di costo costante adatto per gli algoritmi che scriveremo, che non manipoleranno mai numeri né richiederanno quantità di memoria molto più grandi della dimensione dei dati in ingresso In conseguenza di ciò abbiamo che ogni istruzione i di pseudocodice viene eseguita in un tempo costante c i Grazie a questa assunzione, da adesso in poi possiamo dimenticarci che il modello computazionale dello pseudocodice è la macchina RAM Inoltre, da ora in poi ci concentriamo sulla complessità temporale, più che su quella spaziale
11 Costo di esecuzione per INSERTION-SORT INSERTION-SORT(A) costo numero di volte 1 for j := 2 to A.length c 1 n 2 key := A[j] c 2 n // Pone A[j] in A[1..j 1] 0 n i := j 1 c 4 n - 1 % 5 while i > 0 and A[i] > key c 5! & " "#$ % 6 A[i + 1] := A[i] c 6! "#$ % 7 i := i 1 c 7! 8 A[i + 1] := key c 8 "#$ n - 1 & " 1 & " 1
12 Caso ottimo e caso pessimo Note: n = A.length = dimensione dei dati in ingresso t 2, t 3... t n = numero di volte che la condizione del ciclo while viene eseguita quando j = 2, 3,... n Tempo di esecuzione di INSERTION-SORT:! " = $ % " + $ ' " 1 + $ * " 1 + $ +, / ' / +$ 1, -.' $ 2, / -.' (0-1) + $ 5 (" 1) Se l'array A è già ordinato, t 2 =... = t n = 1 T(n) = an+b, cioè T(n) = Θ(n) questo è il caso ottimo Se A è ordinato, ma in ordine decrescente, t 2 =2, t 3 =3,... t n =n T(n) = an 2 +bn+c, cioè T(n) = Θ(n 2 ) questo è il caso pessimo
13 Un classico problema: l'ordinamento L'ordinamento degli elementi di una sequenza è un esempio classico di problema risolto mediante algoritmi C'è un gran numero di algoritmi di ordinamento disponibili: insertion sort, bubblesort, quicksort, merge sort, counting sort,... Ne abbiamo appena visto uno di essi: insertion sort Abbiamo visto che nel caso pessimo T INSERTION-SORT (n) è Θ(n 2 ) possiamo anche scrivere che T INSERTION-SORT (n) = O(n 2 ) (usando la notazione O, senza specificare nel caso pessimo ), in quanto il limite superiore (che è raggiunto nel caso pessimo) è una funzione in Θ(n 2 ) è anche T INSERTION-SORT (n)=ω(n), in quanto il limite inferiore (raggiunto nel caso ottimo) è Θ(n) Possiamo fare di meglio? possiamo cioè scrivere un algoritmo con un limite superiore migliore? Sì!
14 Merge sort Idea dell'algoritmo: se l'array da ordinare ha meno di 2 elementi, è ordinato per definizione altrimenti: si divide l'array in 2 sotto-array, ognuno con la metà degli elementi di quello originario si ordinano i 2 sotto-array ri-applicando l'algoritmo si fondono (merge) i 2 sotto-array (che ora sono ordinati) MERGE-SORT è un algoritmo ricorsivo Un esempio di funzionamento:
15 Pseudocodice di MERGE-SORT MERGE-SORT(A, p, r) 1 if p < r 2 q := (p + r)/2 3 MERGE-SORT(A, p, q) 4 MERGE-SORT(A, q+1, r) 5 MERGE(A, p, q, r) Per ordinare un array A = [A[1], A[2],... A[n]] invochiamo MERGE-SORT(A, 1, A.length)
16 Divide et impera MERGE-SORT adotta una tecnica algoritmica classica: divide et impera Se il problema da risolvere è grosso: dividilo in problemi più piccoli della stessa natura risolvi (domina) i problemi più piccoli combina le soluzioni Dopo un po' che dividiamo il problema in altri più piccoli, ad un certo punto arriviamo ad ottenere problemi piccoli a sufficienza per poterli risolvere senza dividerli ulteriormente è una tecnica naturalmente ricorsiva in quanto, per risolvere i problemi più piccoli, applichiamo lo stesso algoritmo del problema più grosso Per completare l'algoritmo dobbiamo definire un sotto-algoritmo MERGE che "combina" le soluzioni dei problemi più piccoli
17 Fusione (merge) di sotto-array ordinati Definizione del problema (input/output) Input: 2 array ordinati A[p..q] e A[q+1..r] di un array A Output: l'array ordinato A[p..r] ottenuto dalla fusione degli elementi dei 2 array iniziali Idea dell'algoritmo: 1. si va all'inizio dei 2 sotto-array 2. si prende il minimo dei 2 elementi correnti 3. si inserisce tale minimo alla fine dell'array da restituire 4. si avanza di uno nell'array da cui si è preso il minimo 5. si ripete dal passo 2
18 Pseudocodice di MERGE MERGE (A, p, q, r) 1 n 1 := q p n 2 := r q 3 crea (alloca) 2 nuovi array L[1..n 1 +1] e R[1..n 2 +1] 4 for i := 1 to n 1 5 L[i] := A[p + i - 1] 6 for j := 1 to n 2 7 R[j] := A[q + j] 8 L[n 1 + 1] := 9 R[n 2 + 1] := 10 i := 1 11 j := 1 12 for k := p to r 13 if L[i] R[j] 14 A[k] := L[i] 15 i := i else A[k] := R[j] 17 j := j + 1
19 Analisi dell'algoritmo MERGE Nell'algoritmo MERGE prima si copiano gli elementi dei 2 sottoarray A[p..q] e A[q+1..r] in 2 array temporanei L e R, quindi si fondono L e R in A[p..r] Escamotage: per non dover controllare se L e R sono vuoti si usa una sentinella, un valore particolare ( ), più grande di ogni possibile valore, messo in fondo agli array (linee 8-9) Dimensione dei dati in input: n = r p + 1 L'algoritmo è fatto di 3 cicli for: 2 cicli di inizializzazione (l. 4-7), per assegnare i valori a L e R il primo è eseguito n 1 volte, il secondo n 2 volte, con Θ(n 1 ) = Θ(q-p+1) = Θ(n/2) = Θ(n) Θ(n 2 ) = Θ(r-q) = Θ(n/2) = Θ(n) si poteva giungere allo stesso risultato notando che n 1 + n 2 = n, quindi Θ(n 1 + n 2 ) = Θ(n) Il ciclo principale (l ) è eseguito n volte, e ogni linea ha costo costante In totale T MERGE (n) = Θ(n)
20 MERGE (A, p, q, r) costo 1 n 1 := q p + 1 c 2 n 2 := r q c 3 crea 2 nuovi array L[1..n 1 +1] e R[1..n 2 +1] Θ(n) 4 for i := 1 to n 1 5 L[i] := A[p + i - 1] Θ(n 1 ) per tutto il ciclo 6 for j := 1 to n 2 7 R[j] := A[q + j] Θ(n 2 ) = Θ(n/2) = Θ(n) 8 L[n 1 + 1] := c 9 R[n 2 + 1] := c 10 i := 1 c 11 j := 1 c 12 for k := p to r Θ(n) per il ciclo 13 if L[i] R[j] c 14 A[k] := L[i] c 15 i := i + 1 c 16 else A[k] := R[j] c 17 j := j + 1 c
21 Complessità di un algoritmo divide et impera In generale, un algoritmo divide et impera ha le caratteristiche seguenti: si divide il problema in a sottoproblemi, ognuno di dimensione 1/b di quello originale se il sottoproblema ha dimensione n piccola a sufficienza (n<c, con c una costante caratteristica del problema), esso può essere risolto in tempo costante (cioè Θ(1)) indichiamo con D(n) il costo di dividere il problema, e C(n) il costo di ricombinare i sottoproblemi T(n) è il costo per risolvere il problema totale Possiamo esprimere il costo T(n) tramite la seguente equazione di ricorrenza (o ricorrenza): Θ 1 se " < * T " = $ D " + -T " / + C " altrimenti
22 Ricorrenza per l'algoritmo MERGE-SORT a = b = c = 2, D(n) = Θ(1), C(n) = Θ(n) Θ 1 se & < 2 T & = ( 2T & 2 + Θ & altrimenti in realtà dovrebbe essere T( n/2 )+T( n/2 ) invece di 2T(n/2), ma l'approssimazione non influisce sul comportamento asintotico della funzione T(n) Come risolviamo le ricorrenze? Vedremo tra poco!
23 Complessità di MERGE-SORT Riscriviamo la ricorrenza di MERGE-SORT:! se " < 2 T " = - 2T " 2 +!" altrimenti Possiamo disegnare l'albero di ricorsione (consideriamo per semplicità il caso in cui la lunghezza n dell'array è una potenza di 2)!"!"!"/2!"/2!" log ) " +1!"/4!"/4!"/4!"/4!"!!!!!!!!!!!!!!" Sommando i costi dei vari livelli otteniamo T(n) = cn log(n) + cn, cioè T MERGE-SORT (n) = Θ(n log(n)) Totale:!"log " +!"
24 Risoluzione di ricorrenze Tre tecniche principali: sostituzione albero di ricorsione teorema dell'esperto (master theorem) Metodo della sostituzione: formulare un'ipotesi di soluzione sostituire la soluzione nella ricorrenza, e dimostrare (per induzione) che è in effetti una soluzione
25 Esempio di sostituzione Cerchiamo un limite superiore per la seguente T(n): T(n) = 2T( n/2 ) + n supponiamo T(n) = O(n log 2 (n)) dobbiamo mostrare che T(n) cn log 2 (n) per una opportuna costante c>0 supponiamo che ciò valga per T( n/2 ), cioè T( n/2 ) c n/2 log 2 ( n/2 ) sostituendo in T(n) abbiamo: T(n) 2c n/2 log 2 ( n/2 ) + n cn log 2 (n/2) + n = = cn log 2 (n) - cn log 2 (2) + n = cn log 2 (n) -cn + n cn log 2 (n) basta che c 1 dobbiamo però mostrare che la disuguaglianza vale per n = 1 (condizione al contorno); supponiamo che sia T(1) = 1, allora T(1) =1 c1 log 2 (1) = 0? No! però T(n) cn log 2 (n) deve valere solo da un certo n 0 in poi, che possiamo scegliere arbitrariamente; prendiamo n 0 = 2, e notiamo che, se T(1) = 1, allora, dalla ricorrenza, T(2) = 4 e T(3) = 5 inoltre, per n > 3 la ricorrenza non dipende più dal problematico T(1) ci basta determinare una costante c tale che T(2) = 4 c2 log 2 (2) e T(3) = 5 c3 log 2 (3) per ciò basta prendere c 2
26 Osservazioni sul metodo di sostituzione Consideriamo il seguente caso: T(n) = T( n/2 )+T( n/2 )+1 Proviamo a vedere se T(n) = O(n), ovvero se T(n) cn Per ipotesi induttiva abbiamo T(n/2) cn/2, quindi T(n) c n/2 +c n/2 +1 = cn+1 basta prendere c=1 e siamo a posto? No! perché non abbiamo dimostrato la forma esatta della disuguaglianza! dobbiamo derivare che il tutto è cn, ma cn+1 non è cn Potremmo prendere un limite più alto, e dimostrare che T(n) è O(n 2 ) (cosa che è vera), ma in effetti si può anche dimostrare che T(n) = O(n), dobbiamo solo fare un piccolo aggiustamento. Mostriamo allora che T(n) cn-b, dove b è un opportuna costante se fosse così, allora T(n) = O(n) T(n) c n/2 -b+c n/2 -b+1 = cn-2b+1 cn - b basta prendere b 1
27 Altri esempi di sostituzione Attenzione però: T(n) = 2T( n/2 ) + n è O(n)? Ossia T(n) cn? Per ipotesi induttiva, T( n/2 ) c n/2 cn/2, quindi T(n) 2cn/2 + n = cn + n = (c+1)n = O(n), quindi C.V.D.? No! Dobbiamo mostrare la forma esatta della disuguaglianza, e non è vero che (c+1)n cn Altro esempio: # $ = 2# $ + log + $ poniamo m = log 2 (n), quindi n = 2 m, otteniamo T(2 m ) = 2T(2 m/2 ) + m Ponendo S(m) = T(2 m ) abbiamo S(m) = 2S(m/2) + m quindi S(m) = O(m log 2 (m)) Quindi, sostituendo all'indietro: T(n) = O(log 2 (n) log 2 log 2 (n))
28 Metodo dell albero di ricorsione Un metodo non molto preciso, ma utile per fare una congettura da verificare poi con il metodo di sostituzione Idea: a partire dalla ricorrenza, sviluppiamo l'albero delle chiamate, indicando per ogni chiamata la sua complessità Esempio: T(n) = T( n/3 ) + T( 2n/3 ) + O(n) Prima chiamata: #$ % $/3 % 2n/3 Espandiamo: #$ #$ 3 2cn 3 % $ 9 % 2n 9 % 2n 9 % 4n 9
29 fino in fondo:!"!"!"/3 2cn/3!" log -/. "!"/9 2cn/9 2cn/9 4cn/9!" Se l'albero fosse completo, sommando i costi livello per livello, a ogni livello avremmo un costo cn Il ramo più a destra si esaurisce al livello k, dove k è tale che n(2/3) k =1, cioè k = log 3/2 n Quello più a sinistra però si esaurisce prima, dopo solo log 3 n livelli!
30 Verifica del limite superiore Questo ci consente di congetturare che T(n) = Θ(n log 2 n) (anche se l'albero non è completo) Cominciamo con il limite superiore, ovvero T(n)=O(n log 2 n) Verifichiamo la congettura, mostrando che T(n) dn log 2 n: T(n) T(n/3) + T(2n/3) + cn, quindi, sfruttando l ipotesi induttiva: T(n) d(n/3) log 2 (n/3) + d(2n/3) log 2 (2n/3) +cn = d(n/3) log 2 (n) - d(n/3) log 2 (3) + d(2n/3) + d(2n/3) log 2 (n) - d(2n/3) log 2 (3) + cn = dn log 2 n - dn log d(2n/3) + cn = dn log 2 n - dn(log 2 3-2/3) + cn dn log 2 n se d c/(log 2 3-2/3)
31 Verifica del limite inferiore Il ramo più a sinistra si esaurisce dopo k livelli, dove k è tale che n(1/3) k' =1, cioè k' = log 3 n Verifichiamo che che T(n)=Ω(n log 2 n) Si mostra che T(n) dn log 2 n procedendo come prima T(n) T(n/3) + T(2n/3) + cn, quindi, sfruttando l ipotesi induttiva: T(n) d(n/3) log 2 (n/3) + d(2n/3) log 2 (2n/3) +cn = dn log 2 n - dn(log 2 3-2/3) + cn dn log 2 n se 0 < d c/(log 2 3-2/3) In definitiva T(n) = Θ(n log 2 n) Nota: in entrambe le sostituzioni andrebbe verificato anche il caso base
32 Teorema dell esperto (master theorem) Data la ricorrenza: T(n) = at(n/b) + f(n) (in cui a 1, b >1, e n/b è o n/b o n/b ) 1. se f(n) = O(n log b a-ε ) per qualche ε > 0, allora T(n) = Θ(n log b a ) 2. se f(n) = Θ(n log b a ), allora T(n) = Θ(n log b a log(n)) 3. se f(n) = Ω(n log b a+ε ) per qualche ε > 0, e af(n/b) cf(n) per qualche c < 1 e per tutti gli n grandi a sufficienza, allora T(n) = Θ(f(n)) La condizione af(n/b) cf(n) è detta di regolarità
33 Alcune osservazioni La soluzione è data dal più grande tra n log b a e f(n) se n log b a è il più grande, T(n) è Θ(n log b a ) se f(n) è il più grande, T(n) è Θ(f(n)) se sono nella stessa classe secondo la relazione Θ, T(n) è Θ(f(n)log(n)) Più grande o più piccolo in effetti significa "polinomialmente più grande" e "polinomialmente più piccolo" n è polinomialmente più piccolo di n 2 n log(n) è polinomialmente più grande di n ½ Il teorema dell'esperto non copre tutti i casi! se una delle due funzioni è più grande, ma non polinomialmente più grande... n log(n) è più grande di n, ma non polinomialmente più grande
34 Teorema dell esperto e MERGE- SORT T(n) = 2T(n/2) + Θ(n) a = b = 2 f(n) = n n log ba = n 1 = n Siamo nel caso 2: T MERGE-SORT (n) = Θ(n log(n))
35 Un caso particolare Notiamo che l'enunciato del teorema dell'esperto si semplifica un po' se f(n) è una funzione Θ(n k ), per una qualche costante k: 1. se k < log b a, allora T(n) = Θ(n log b a ) 2. se k = log b a, allora T(n) = Θ(n k log(n)) 3. se k > log b a, allora T(n) = Θ(n k ) nel caso 3 la condizione aggiuntiva di regolarità è automaticamente verificata
36 Condizione di regolarità Sia T(n) = T(n/2) + n (2 cos n), quindi a=1, b=2 f(n) = n(2-cos n) = Ω(n) > n log ba = Θ(1) Siamo nel caso 3? No! La regolarità richiede che: n/2 (2 cos (n/2)) c n (2 cos n), per n grande e c<1 Ma le curve oscillano e si intersecano sempre quindi a maggior ragione la relazione non vale moltiplicando f(n) per c<1 ( - ( )) ( - ( ))
37 Un ulteriore risultato Data la ricorrenza (in cui i coefficienti a i sono interi 0) in cui poniamo T " = 0 = +,-.-/ +,-.-/ 0. Θ 1 allora abbiamo che: se a = 1, allora T(n)=O(n k+1 ) se a 2, allora T(n)=O(a n n k ) se " ) h 0. 1 " 3 + 5" 6 se " > ) Per esempio, data la ricorrenza T(n) = T(n-1) + Θ(n), otteniamo che T(n)=O(n 2 ) questa è la ricorrenza che otterremmo con una versione ricorsiva di INSERTION-SORT
38 Grafi (richiamo) Un grafo è una coppia (V, E) in cui V è un insieme finito di nodi (detti anche vertici), e E V V è una relazione binaria su V che rappresenta gli archi del grafo se u e v sono nodi del grafo, la coppia (u,v) è un arco, ed è rappresentata graficamente come: u v in questo caso l'arco è orientato, in quanto c'è un ordine tra i vertici, prima u, poi v se non c'è un ordine tra i nodi (che quindi sono solo un insieme, {u,v}) allora diciamo che l'arco è non orientato: u v
39 Tipi di grafo Un grafo è orientato se i suoi archi lo sono, non orientato altrimenti Un cammino è una sequenza di nodi v 0, v 1, v 2,, v n tali che tra ogni coppia di nodi della sequenza (v i, v i+1 ) c'è un arco i nodi v 0,, v n appartengono al cammino la lunghezza del cammino è data da n (numero di vertici -1) In un grafo non orientato, il cammino forma un ciclo se v 0 = v n Un grafo che non ha cicli è aciclico Un grafo non orientato è connesso se tra ogni coppia di vertici esiste un cammino
40 Alberi (richiamo) Un albero è un grafo connesso, aciclico, non orientato un albero è radicato se un nodo viene indicato come la radice profondità 0 profondità 1 radice nodi interni altezza = 3 profondità 2 profondità 3 foglie Ogni nodo dell'albero è raggiungibile dalla radice tramite un cammino (che è unico, in quanto il grafo è aciclico). Chiamiamo foglie gli ultimi nodi dei cammini dalla radice.
41 Nodi Ogni nodo ha un padre (a parte la radice) e uno o più figli (a parte le foglie). Chiamiamo: nodi interni: tutti i nodi dei cammini tra la radice e le foglie profondità (di un nodo N): la distanza di N dalla radice altezza (dell'albero): la distanza massima tra la radice e una foglia antenato (di un nodo N): ogni nodo che precede N sul cammino dalla radice a N padre (di un nodo N): il nodo che immediatamente precede N lungo il cammino dalla radice a N figlio (di un nodo N): ogni nodo di cui N è padre fratelli (di un nodo N): i nodi che hanno lo stesso padre di N Un albero è binario se ogni nodo ha al più 2 figli
42 HEAPSORT MERGE-SORT è efficiente dal punto di vista del tempo di esecuzione, ma non è ottimale dal punto di vista dell'uso della memoria ogni MERGE richiede di allocare 2 array, di lunghezza Θ(n) usa una quantità di memoria aggiuntiva rispetto all'array da ordinare che non è costante, cioè non ordina sul posto HEAPSORT, invece, non solo è efficiente (ordina in tempo Θ(n log(n))), ma ordina sul posto L'idea alla base di HEAPSORT è che un array può essere visto come un albero binario: A[1] è la radice per ogni elemento A[i], A[2i] e A[2i+1] sono i suoi figli, e A[ i/2 ] è il padre
43 Esempio a 1 a 2 a 3 a 4 a 5 a 6 a 7 a 8 a 9 a 10 a 11 a 12 1 a 1 2 a 2 3 a 3 4 a 4 5 a 5 6 a 6 7 a 7 a 8 a 9 a 10 a 11 a
44 Gli heap (mucchi) Uno heap binario è un albero binario quasi completo quasi completo = tutti i livelli sono completi, tranne al più l'ultimo, che potrebbe essere completo solo fino a un certo punto da sinistra l'albero binario che deriva dall'interpretazione di un array come albero è quasi completo Un max-heap è uno heap tale che, per ogni nodo x dell'albero, il valore contenuto nel padre di x è del contenuto di x usando la corrispondenza albero-heap, questo vuole dire che A[ i/2 ] A[i]
45 Esempio di max-heap Si noti che in un max-heap l'elemento massimo è nella radice dove è il minimo?
46 Alcune operazioni sugli heap Operazioni di base: PARENT(i) 1 return i/2 LEFT(i) RIGHT(i) 1 return 2*i 1 return 2*i + 1 Quindi, in un max-heap abbiamo che A[PARENT(i)] A[i] esistono anche i min-heap, per i quali A[PARENT(i)] A[i] Per realizzare l'ordinamento usiamo i max-heap Ogni array A che rappresenta uno heap ha 2 attributi: A.length, che rappresenta il numero totale di elementi dell'array A.heap-size, che rappresenta il numero di elementi dello heap A.heap-size A.length, e solo gli elementi fino a A.heap-size hanno la proprietà dello heap però l'array potrebbe contenere elementi dopo l'indice A.heap-size, se A.heapsize<A.length
47 Algoritmi di supporto Un algoritmo che, dato un elemento di un array tale che i suoi figli sinistro e destro sono dei max-heap, ma in cui A[i] (la radice del sottoalbero) potrebbe essere < dei suoi figli, modifica l'array in modo che tutto l'albero di radice A[i] sia un max-heap MAX-HEAPIFY(A, i) 1 l := LEFT(i) 2 r := RIGHT(i) 3 if l A.heap-size and A[l] > A[i] 4 max := l 5 else max := i 6 if r A.heap-size and A[r] > A[max] 7 max := r 8 if max i then 9 swap A[i] A[max] 10 MAX-HEAPIFY(A, max)
48 Complessità di MAX-HEAPIFY T MAX-HEAPIFY = O(h), dove h è l'altezza dell'albero, che è O(log(n)), poiché l'albero è quasi completo quindi, T MAX-HEAPIFY = O(log(n)) Questo si sarebbe anche potuto mostrare usando il teorema dell'esperto per la seguente ricorrenza, che rappresenta il tempo di esecuzione di MAX-HEAPIFY nel caso pessimo: T(n) = T(2n/3) + Θ(1) nel caso pessimo l'ultimo livello dell'albero è esattamente pieno a metà, e l'algoritmo viene applicato ricorsivamente sul sottoalbero sinistro, che contiene 2n/3 nodi, detto n il numero di nodi totali
49 Da array a max-heap Costruiamo il max-heap bottom-up, dalle foglie, fino alla radice osservazione fondamentale: tutti gli elementi oltre l'indice A.length/2 sono delle foglie, gli altri sono dei nodi interni i sottoalberi fatti di solo foglie sono, presi singolarmente, già degli heap, in quanto sono fatti ciascuno di un unico elemento BUILD-MAX-HEAP(A) 1 A.heap-size := A.length 2 for i := A.length/2 downto 1 3 MAX-HEAPIFY(A, i) Costo di BUILD-MAX-HEAP? ad occhio, ogni chiamata a MAX-HEAPIFY costa O(log(n)), e vengono fatte O(n) chiamate (con n che è A.length), quindi il costo è O(n log(n)) ma in realtà questo limite non è stretto...
50 Complessità di BUILD-MAX- HEAP Osserviamo che: l'altezza di un albero quasi completo di n nodi è log 2 (n) se definiamo come altezza di un nodo di uno heap la lunghezza del cammino più lungo che porta ad una foglia, il costo di MAX-HEAPIFY invocato su un nodo di altezza h è O(h) il numero massimo di nodi di altezza h di uno heap è n/2 h+1 Quindi MAX-HEAPIFY viene invocato n/2 h+1 volte ad ogni altezza h, quindi il costo di BUILD-MAX-HEAP è log, - log, -. h % 2 &01 2(h)= 2. % 2 & &'( &'( cioè O(n), in quanto è noto che 7 h % 2 & = 1 2 :1 1 2) < = 2 &'(
51 HEAPSORT Possiamo a questo punto scrivere l'algoritmo di HEAPSORT: HEAPSORT(A) 1 BUILD-MAX-HEAP(A) 2 for i := A.length downto 2 3 swap A[1] A[i] 4 A.heap-size := A.heap-size 1 5 MAX-HEAPIFY(A,1) A ogni ciclo piazziamo l'elemento più grande (che è il primo dell'array, in quanto questo è un max-heap) in fondo alla parte di array ancora da ordinare (che è quella corrispondente allo heap) fatto ciò, lo heap si decrementa di 1, e si ricostruisce il max-heap mettendo come radice l'ultima foglia a destra dell'ultimo livello, e invocando MAX-HEAPIFY La complessità di HEAPSORT è O(n log(n)), in quanto BUILD-MAX-HEAP ha costo O(n) MAX-HEAPIFY è invocato n-1 volte, e ogni sua chiamata ha costo O(log(n))
52 HEAPSORT: esempio A = [4,1,3,2,16,9,10,14,8,7] heap A ad ogni passo dopo MAX-HEAPIFY: A: [16, 14, 10, 8, 7, 9, 3, 2, 4, 1] (max-heap) A: [14, 8, 10, 4, 7, 9, 3, 2, 1, 16] A: [10, 8, 9, 4, 7, 1, 3, 2, 14, 16] A: [9, 8, 3, 4, 7, 1, 2, 10, 14, 16] A: [8, 7, 3, 4, 2, 1, 9, 10, 14, 16] A: [7, 4, 3, 1, 2, 8, 9, 10, 14, 16] A: [4, 2, 3, 1, 7, 8, 9, 10, 14, 16] A: [3, 2, 1, 4, 7, 8, 9, 10, 14, 16] A: [2, 1, 3, 4, 7, 8, 9, 10, 14, 16] A: [1, 2, 3, 4, 7, 8, 9, 10, 14, 16]
53 QUICKSORT QUICKSORT è un algoritmo in stile divide-et-impera ordina sul posto Nel caso pessimo (vedremo) ha complessità Θ(n 2 ) Però in media funziona molto bene (in media ha complessità Θ(nlog(n))) inoltre ha ottime costanti Idea di base del QUICKSORT: dato un sottoarray A[p..r] da ordinare: (dividi) riorganizza in A[p..r] 2 sottoarray A[p..q-1] e A[q+1..r] tali che tutti gli elementi di A[p..q-1] siano A[q] e tutti gli elementi di A[q+1..r] siano A[q] (domina) ordina i sottoarray A[p..q-1] e A[q+1..r] riutilizzando QUICKSORT (combina) nulla! L'array A[p..r] è già ordinato
54 Codice di QUICKSORT QUICKSORT(A, p, r) 1 if p < r 2 q := PARTITION(A, p, r) 3 QUICKSORT(A, p, q 1) 4 QUICKSORT(A, q+1, r) Per ordinare un array A: QUICKSORT(A,1,A.length)
55 PARTITION La cosa difficile di QUICKSORT è partizionare l'array in 2 parti: PARTITION(A, p, r) 1 x := A[r] 2 i := p 1 3 for j := p to r 1 4 if A[j] x 5 i := i swap A[i] A[j] 7 swap A[i+1] A[r] 8 return i + 1 l'elemento x (cioè A[r] in questa implementazione) è il pivot da p a i (inclusi): partizione con elementi x da i+1 a j-1: partizione con elementi > x Complessità di PARTITION: Θ(n), con n = r-p+1
56 Esempio di funzionamento Quicksort su 99, 4, 88, 7, 5, -3, 1, 34, 11 partition: [99, 4, 88, 7, 5, -3, 1, 34, 11] p: 1, q: 6, r: 9 partition: [4, 7, 5, -3, 1, 11, 88, 34, 99] p: 1, q: 2, r: 5 partition: [-3, 1, 5, 4, 7, 11, 88, 34, 99] p: 3, q: 5, r: 5 partition: [-3, 1, 5, 4, 7, 11, 88, 34, 99] p: 3, q: 3, r: 4 partition: [-3, 1, 4, 5, 7, 11, 88, 34, 99] p: 7, q: 9, r: 9 partition: [-3, 1, 4, 5, 7, 11, 88, 34, 99] p: 7, q: 7, r: 8
57 Complessità di QUICKSORT Il tempo di esecuzione di QUICKSORT dipende da come viene partizionato l'array Se ogni volta uno dei 2 sottoarray è vuoto e l'altro contiene n-1 elementi si ha il caso pessimo la ricorrenza in questo caso è: T(n) = T(n-1) + Θ(n) abbiamo visto che la soluzione di questa ricorrenza è O(n 2 ) si può anche dimostrare (per esempio per sostituzione) che è anche Θ(n 2 ) un caso in cui si ha sempre questa situazione completamente sbilanciata è quando l'array è già ordinato Nel caso ottimo, invece, i 2 array in cui il problema viene suddiviso hanno esattamente la stessa dimensione n/2 la ricorrenza in questo caso è: T(n) = 2T(n/2) + Θ(n) è la stessa ricorrenza di MERGE-SORT, ed ha quindi la stessa soluzione Θ(n log(n)) Notiamo che se la proporzione di divisione, invece che essere n/2 ed n/2, fosse n/10 e 9n/10, comunque la complessità sarebbe Θ(n log(n)) solo, la costante nascosta dalla notazione Θ sarebbe più grande abbiamo già visto qualcosa di molto simile per la suddivisione n/3 e 2n/3
58 QUICKSORT nel caso medio (intuizione) In media ci va un po' bene ed un po' male bene = partizione ben bilanciata male = partizione molto sbilanciata Qualche semplificazione: ci va una volta bene ed una volta male quando va bene => ottimo n/2 e n/2 quando va male => pessimo n-1 e 0
59 Albero di ricorsione per il caso medio Albero di ricorsione in questo caso (ogni divisione costa n): n Θ(n) 0 n-1 (n-1)/2-1 (n-1)/2 costo di una divisione cattiva + una divisione buona = Θ(n) è lo stesso costo di una singola divisione buona dopo una coppia divisione cattiva divisione buona il risultato è una divisione buona quindi alla fine il costo di una coppia cattiva buona è lo stesso di una divisione buona, ed il costo di una catena di tali divisioni è la stessa quindi Θ(n log(n)) le costanti moltiplicative peggiorano un po', ma l'ordine di grandezza non cambia!
60 Limite inferiore per l ordinamento Quanto veloce può andare un algoritmo di ordinamento? Possiamo far meglio di n lg n? Partiamo col concetto di ordinamento per confronto: supponiamo di poter ordinare esclusivamente confrontando il valore di coppie di elementi (quello che abbiamo sempre fatto) Limiti inferiori: W(n) per forza dobbiamo leggere gli elementi! Per ora tutti gli ordinamenti che abbiamo visto sono W(n lg n)
61 Conteggio dei confronti Otteniamo un albero di decisione (esempio InsertSort): (1,2,3) 1:3 (1,3,2) 1:2 <= > 2:3 1:3 (3,1,2) (2,1,3) 2:3 (2,3,1) (3,2,1) confronta A[1] con A[2]: - sinistra: ok, - destra: scambio i due elementi arrivati alle foglie, A è ordinato quante foglie ci sono? Tutte le permutazioni sono n!, però la stessa permutazione potrebbe apparire più volte... ergo: > n!
62 Altezza dell albero di decisione Posso costruire, dato un n, un albero simile per qualsiasi ordinamento per confronto si confrontano x e y solo due possibilità: x y (siamo già a posto) oppure x > y Qual è la lunghezza massima dalla radice a una foglia? Dipende dall'algoritmo di ordinamento: INSERTION-SORT: Q(n 2 ) MERGE-SORT: Q(n lg n) Sfrutto il seguente Lemma: L1: Ogni albero binario di altezza h ha un numero di foglie al più 2 h (dim banale - per induzione)
63 Limite inferiore dimostrato Teorema: Ogni albero di decisione di ordinamento di n elementi ha altezza W(n lg n). Dim: Sia f il numero di foglie. Abbiamo visto prima che f n! Per L1: n! f 2 h, cioè 2 h n! Quindi: h lg(n!) lg((n/2) n/2 ) = n/2 lg(n/2) = W(n lg n) c.v.d. Si anche può mostrare mediante l'approssimazione di Stirling: n! > (n/e) n Ne segue: h lg((n/e) n ) = n lg(n/e) = n lg n n lg e = W(n lg n)
64 COUNTING-SORT Ipotesi fondamentale: i valori da ordinare sono tutti numeri naturali compresi tra 0 e una certa costante k Idea di base: se nell'array ci sono m e valori più piccoli di un certo elemento e (il cui valore è v e ) nell'array ordinato l'elemento e sarà in posizione m e +1 quindi, basta contare quante "copie" dello stesso valore v e sono contenute nell'array usiamo questa informazione per determinare, per ogni elemento e (con valore v e tale che 0 v e k), quanti elementi ci sono più piccoli di e dobbiamo anche tenere conto del fatto che nell'array ci possono essere elementi ripetuti es. [2, 7, 2, 5, 1, 1, 9]
65 Pseudocodice di COUNTING- SORT parametri: A è l'array di input (disordinato), B conterrà gli elementi ordinati (cioè è l'output), e k è il massimo tra i valori di A A e B devono essere della stessa lunghezza n COUNTING-SORT (A, B, k) 1 for i := 0 to k 2 C[i] := 0 3 for j := 1 to A.length 4 C[A[j]] := C[A[j]] //C[i] ora contiene il numero di elementi uguali a i 6 for i := 1 to k 7 C[i] := C[i] + C[i - 1] 8 //C[i] ora contiene il numero di elementi i 9 for j := A.length downto 1 10 B[C[A[j]]] := A[j] 11 C[A[j]] := C[A[j]] - 1
66 Esempio di COUNTING-SORT Se A = [ 2,5,3,0,2,3,0,3 ] A.length = 8 B deve avere lunghezza 8 Se eseguiamo COUNTING-SORT(A, B, 5) prima di eseguire la linea 5 (cioè alla fine del loop 3-4) C = [2,0,2,3,0,1] prima di eseguire la linea 8, C = [2,2,4,7,7,8] dopo le prime 3 iterazioni del ciclo 9-11 abbiamo 1. B = [ _,_,_,_,_,_,3,_ ], C = [ 2,2,4,6,7,8 ] 2. B = [ _,0,_,_,_,_,3,_ ], C = [ 1,2,4,6,7,8 ] 3. B = [ _,0,_,_,_,3,3,_ ], C = [ 1,2,4,5,7,8 ] alla fine dell'algoritmo B = [ 0,0,2,2,3,3,3,5 ], C = [ 0,2,2,4,7,7 ]
67 Complessità di COUNTING- SORT La complessità di COUNTING-SORT è data dai 4 cicli for: il ciclo for delle linee 1-2 ha complessità Q(k) il ciclo for delle linee 3-4 ha complessità Q(n) il ciclo for delle linee 6-7 ha complessità Q(k) il ciclo for delle linee 9-11 ha complessità Q(n) La complessità globale è Q(n + k) Se k è O(n), allora il tempo di esecuzione è O(n) lineare! COUNTING-SORT è "più veloce" (cioè ha complessità inferiore) di MERGE-SORT e HEAPSORT (se k è O(n)) perché fa delle assunzioni sulla distribuzione dei valori da ordinare (assume che siano tutti k) Sfrutta l'assunzione: è veloce se k è O(n), altrimenti ha complessità maggiore (anche di molto) di MERGE-SORT e HEAPSORT
68 Osservazioni su COUNTING- SORT Si può ottenere una versione più semplice dell'algoritmo senza usare l'array B (come?) La versione che abbiamo appena visto è però stabile Questo vuol dire che, se nell'array da ordinare ci sono più elementi con lo stesso valore, questi appariranno nell'array ordinato mantenendo il loro ordine relativo iniziale Es: supponiamo che in A ci siano due 35, il primo lo chiamiamo 35 a e il secondo 35 b. Dopo l'ordinamento 35 a apparirà sicuramente prima di 35 b. Questa proprietà non è particolarmente interessante se ci limitiamo ad ordinare numeri. Lo diviene se stiamo ordinando dei dati complessi (oggetti), utilizzando un valore per es. dei loro attributi come chiave.
Concetti di base di complessità degli algoritmi
Concetti di base di complessità degli algoritmi 1 Problemi, algoritmi, programmi Problema: il compito da svolgere quali output vogliamo ottenere a fronte di certi input cioè quale funzione vogliamo realizzare
Concetti di base di complessità degli algoritmi
Concetti di base di complessità degli algoritmi 1 Problemi, algoritmi, programmi Problema: il compito da svolgere quali output vogliamo ottenere a fronte di certi input cioè quale funzione vogliamo realizzare
Problemi di ordinamento
Problemi di ordinamento Input: una sequenza di n numeri a 1, a 2,..., a n ; Output: una permutazione a 1, a 2,..., a n di a 1, a 2,..., a n tale che a 1 a 2... a n. Generalmente, la sequenza è rappresentata
Per regnare occorre tenere divisi i nemici e trarne vantaggio. fai ad ogni passo la scelta più conveniente
Progetto di algoritmi sequenziali (un solo esecutore ) Divide et Impera Per regnare occorre tenere divisi i nemici e trarne vantaggio Greedy fai ad ogni passo la scelta più conveniente Buoni risultati
Algoritmi e Strutture di Dati I 1. Algoritmi e Strutture di Dati I Massimo Franceschet francesc
Algoritmi e Strutture di Dati I 1 Algoritmi e Strutture di Dati I Massimo Franceschet http://www.sci.unich.it/ francesc m.franceschet@unich.it Algoritmi e Strutture di Dati I 2 Problema dell ordinamento
In questa lezione: correttezza del mergesort Analisi del mergesort: relazioni di ricorrenza e alberi della ricorsione
In questa lezione: correttezza del mergesort Analisi del mergesort: relazioni di ricorrenza e alberi della ricorsione Prof E Fachini - Intr Alg 1 MergeSort: correttezza MergeSort (A,p,r) if p < r then
Algoritmi e Strutture Dati
Heap Maria Rita Di Berardini, Emanuela Merelli 1 1 Dipartimento di Matematica e Informatica Università di Camerino A.A. 2006/07 Heap Heap binari: definizione Un heap binario è una struttura dati composta
In questa lezione. Heap binario heapsort. [CLRS10] cap. 6, par Prof. E. Fachini - Intr. Alg.
In questa lezione Heap binario heapsort [CLRS10] cap. 6, par. 6.1-6.4!1 Heap binari Un heap binario è una struttura dati consistente di un array visto come un albero binario. A= 5 60 65 30 50 18 40 25
Algoritmi e Strutture Dati
Algoritmi e Strutture Dati Modelli di calcolo e metodologie di analisi Domenico Fabio Savo 1 Notazione asintotica f(n) = tempo di esecuzione / occupazione di memoria di un algoritmo su input di dimensione
Algoritmi e Strutture Dati
Heap Maria Rita Di Berardini, Emanuela Merelli 1 1 Dipartimento di Matematica e Informatica Università di Camerino 6 novembre 2008 Heap binari: definizione Un heap binario è una albero binario quasi completo
Tecniche Algoritmiche: divide et impera
Tecniche Algoritmiche: divide et impera Una breve presentazione F. Damiani - Alg. & Lab. 04/05 Divide et impera (o Divide and conquer) Per regnare occorre tenere divisi i nemici e trarne vantaggio F. Damiani
Algoritmi e Strutture Dati
Algoritmi di Ordinamento Maria Rita Di Berardini, Emanuela Merelli 1 1 Dipartimento di Matematica e Informatica Università di Camerino Il problema dell ordinamento Il problema dell ordinamento di un insieme
Esercitazione 3. Heapsort
Esercitazione Heapsort Heapsort Algoritmo di ordinamento che utilizza una struttura dati detta heap per la gestione delle informazioni Tempo di esecuzione O(n lg n) Heap (binario) = struttura dati composta
In questa lezione. Costruire un max-heap. [CLRS01] cap. 6 par Prof. E. Fachini - Intr. Alg.
In questa lezione Costruire un max-heap [CLRS01] cap. 6 par. 6.3!1 Heapsort: analisi Heapsort(A) Build-Max-Heap(A) for i = A.length downto 2 do scambia A[1] e A[i] A.heap-size = A.heap-size - 1 Max-Heapify
Algoritmi e Strutture Dati
Algoritmi di Ordinamento Maria Rita Di Berardini, Emanuela Merelli 1 1 Dipartimento di Matematica e Informatica Università di Camerino 13 novembre 2008 Il problema dell ordinamento Il problema dell ordinamento
Introduzione agli algoritmi Prova di esame del 19/9/2016 Prof.sse E. Fachini - R. Petreschi. Parte prima
Introduzione agli algoritmi Prova di esame del 19/9/2016 Prof.sse E. Fachini - R. Petreschi Parte prima 1) Si dimostri il teorema sulla limitazione inferiore per il tempo asintotico di esecuzione nel caso
Algoritmo di ordinamento sul posto che ha tempo di esecuzione :
QuickSort Algoritmo di ordinamento sul posto che ha tempo di esecuzione : - O(n 2 ) nel caso peggiore - O(n log n) nel caso medio Nonostante le cattive prestazioni nel caso peggiore, rimane il miglior
In questa lezione. Heapsort. ordinamento con complessità, nel caso peggiore, O(nlogn) [CLRS01] cap. 6 da pag. 106 a pag. 114
In questa lezione Heapsort ordinamento con complessità, nel caso peggiore, O(nlogn) [CLRS01] cap. 6 da pag. 106 a pag. 11 1 Paternità L heapsort è stato pubblicato da J. W. J. Williams nel 106. Pochi mesi
Albero di Riscorsione
Albero di Riscorsione Albero di ricorsione Un albero di ricorsione è un modo di visualizzare cosa accade in un algoritmo divide et impera L etichetta della radice rappresenta il costo non ricorsivo della
Quick Sort. PARTITION(A,p,r) risistema il sottoarray A[p...r] e riporta l indice q:
Quick Sort - Ordinamento in loco - Tempo di esecuzione nel caso peggiore: Θ(n 2 ) - Tempo di esecuzione nel caso medio: Θ(n lg n) - I fattori costanti nascosti nella notazione Θ sono abbastanza piccoli
Esercizi per il corso di Algoritmi, anno accademico 2011/12
Esercizi per il corso di Algoritmi, anno accademico 2011/12 Esercizi sulla Tecnica Divide et Impera N.B. Tutti gli algoritmi vanno scritti in pseudocodice (non in Java, nè in C++, etc. ). Di tutti gli
Dato un insieme S di n elementi totalmente ordinato, l'algoritmo di ordinamento detto HeapSort ha le seguenti caratteristiche:
Heapsort Dato un insieme S di n elementi totalmente ordinato, l'algoritmo di ordinamento detto HeapSort ha le seguenti caratteristiche: T(n) = O(n log(n)) Alg. Ordinamento ottimale Ordina in loco (niente
Algoritmi di Ordinamento
Algoritmi di Ordinamento 1 Algoritmi di ordinamento Selection Sort Quick Sort Lower bound alla complessità degli algoritmi di ordinamento Statistiche di ordine 2 Selection Sort SelectionSort(dati[]) {
Ordinamenti. Grafo : definizione. Un grafo G = (V,E)è composto da: V: insieme di vertici E V V: insieme di archi (edge) che connettono i vertici
Ordinamenti 1 Vittorio Maniezzo Università di Bologna Grafo : definizione Un grafo G = (V,E)è composto da: V: insieme di vertici E V V: insieme di archi (edge) che connettono i vertici Un arco a= {u,v}
In questa lezione. Il Mergesort: primo esempio di applicazione della tecnica divide et impera analisi tempo di esecuzione del Mergesort
In questa lezione Il Mergesort: primo esempio di applicazione della tecnica divide et impera analisi tempo di esecuzione del Mergesort [CLRS] par. 2.3. Prof. E. Fachini - Intr. Alg.!1 Progettazione di
Dipartimento di Elettronica, Informazione e Bioingegneria API 2013/4
Dipartimento di Elettronica, Informazione e Bioingegneria API 2013/4 Equazioni alle ricorrenze @ G. Gini 2013 divide et impera - ricorsione Esempio: ordinamento di array Dimensione dei sottoinsiemi n/2,n/2
QUICKSORT. Basato sul paradigma divide-et-impera (come MERGE-SORT)
QUICKSORT Basato sul paradigma divide-et-impera (come MERGE-SORT) Divide: stabilisce un valore di q tale da dividere l array A[p.. r] in due sottoarray non vuoti A[p.. q] e A[q+1.. r], dove ogni elemento
ESERCITAZIONI DI INTRODUZIONE AGLI ALGORITMI (A.A. 08/09)
ESERCITAZIONI DI INTRODUZIONE AGLI ALGORITMI (A.A. 08/09) DISPENSA N. 4 1. Ricerca Binaria Ricorsiva L algoritmo Ricerca Binaria risolve il problema della ricerca di una chiave in un vettore. È un esempio
Algoritmi e Strutture Dati
Algoritmi Ricorsivi e Maria Rita Di Berardini, Emanuela Merelli 1 1 Dipartimento di Matematica e Informatica Università di Camerino A.A. 2006/07 I conigli di Fibonacci Ricerca Binaria L isola dei conigli
Ordinamenti. Vittorio Maniezzo Università di Bologna
Ordinamenti 1 Vittorio Maniezzo Università di Bologna Grafo : definizione Un grafo G = (V,E)è composto da: V: insieme di vertici E V V: insieme di archi (edge) che connettono i vertici Un arco a= {u,v}
Notazione asintotica. notazione Ω. notazione O. notazione o notazione ω. Marina Zanella Algoritmi e strutture dati Richiami matematici 1
Notazione asintotica Sebbene si possa talvolta determinare il tempo esatto di esecuzione di un algoritmo, l estrema precisione non giustifica lo sforzo del calcolo; infatti, per input sufficientemente
Algoritmi e Strutture Dati
Algoritmi Ricorsivi e Ricorrenze Maria Rita Di Berardini 2, Emanuela Merelli 1 1 Dipartimento di Matematica e Informatica Università di Camerino 2 Polo di Scienze Università di Camerino ad Ascoli Piceno
Ordinamento per inserzione e per fusione
Ordinamento per inserzione e per fusione Alessio Orlandi 15 marzo 2010 Fusione: problema Problema Siano A e B due array di n A e n B interi rispettivamente. Si supponga che A e B siano ordinati in modo
Algoritmi e Strutture Dati
Algoritmi di Ordinamento Maria Rita Di Berardini, Emanuela Merelli 1 1 Dipartimento di Matematica e Informatica Università di Camerino Il problema dell ordinamento Il problema dell ordinamento di un insieme
Nozioni di base (II Parte)
Nozioni di base (II Parte) 1 Ricorsione [GTG14, Par. 5.1-5.4 and 13.1] Algoritmo Ricorsivo: algoritmo che invoca se stesso (su istanze sempre più piccole) sfruttando la nozione di induzione. La soluzione
Moltiplicazione veloce di interi
Moltiplicazione veloce di interi Ogni numero intero w di n cifre può essere scritto come 10 n/2 w s + w d w s indica il numero formato dalle n/2 cifre più significative di w w d denota il numero formato
Algoritmi e Strutture Dati. HeapSort
Algoritmi e Strutture Dati HeapSort Selection Sort: intuizioni L algoritmo Selection-Sort scandisce tutti gli elementi dell array a partire dall ultimo elemento fino all inizio e ad ogni iterazione: Viene
Laboratorio di Algoritmi e Strutture Dati. Aniello Murano. people.na.infn.it/~murano/ Murano Aniello - Lab. di ASD Terza Lezione
Laboratorio di Algoritmi e Strutture Dati Aniello Murano http://people.na.infn.it people.na.infn.it/~murano/ Heap e Heapsort Algoritmi di ordinamento Insertion Sort Quicksort Heapsort Insertion Sort L
Albero binario: Ogni nodo ha zero, uno, o due successori (ordinati)
Heap 1 Vittorio Maniezzo - Università di Bologna Alberi binari Albero binario: Ogni nodo ha zero, uno, o due successori (ordinati) Albero binario completo: Tutte le foglie hanno la stessa profondità e
Algoritmi e Strutture Dati
Algoritmi Ricorsivi e Maria Rita Di Berardini, Emanuela Merelli 1 1 Dipartimento di Matematica e Informatica Università di Camerino I conigli di Fibonacci Ricerca Binaria L isola dei conigli Leonardo da
ADT Coda con priorità
Code con priorità ADT Coda con priorità Una coda con priorità è una struttura dati dinamica che permette di gestire una collezione di dati con chiave numerica. Una coda con priorità offre le operazioni
Gli algoritmi ricorsivi di ordinamento. Paolo Camurati Dip. Automatica e Informatica Politecnico di Torino
ordinamento Paolo Camurati Dip. Automatica e Informatica Politecnico di Torino Merge Sort Ricorsivo, divide et impera Stabile Divisione: due sottovettori SX e DX rispetto al centro del vettore. p r A.A.
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano. Usa la tecnica del divide et impera:
MergeSort Usa la tecnica del divide et impera: 1 Divide: dividi l array a metà 2 Risolvi i due sottoproblemi ricorsivamente 3 Impera: fondi le due sottosequenze ordinate 1 Esempio di esecuzione 7 2 4 5
Università degli Studi di Camerino Laurea in Informatica Prima Prova Parziale del corso di Algoritmi e Strutture Dati
Università degli Studi di Camerino Laurea in Informatica Prima Prova Parziale del corso di Algoritmi e Strutture Dati Docente: Maria Rita Di Berardini 19 dicembre 2007 Nome: Cognome: N.Matricola: Note:
Esercizi su ABR. Prof. E. Fachini - Intr. Alg.!1
Esercizi su ABR Confronto proprietà ABR e Max-Heap. Proprietà del cammino radice-foglia individuato da una ricerca. Fusione di due ABR. Il successivo calcolato dalla radice Costruzione di un ABR bilanciato
Algoritmi e Strutture Dati. HeapSort
Algoritmi e Strutture Dati HeapSort Selection Sort: intuizioni L algoritmo Selection-Sort scandisce tutti gli elementi dell array a partire dall ultimo elemento fino all inizio e ad ogni iterazione: Viene
Esercizio. 2 i=i*2) j=j*2)
Esercizio 1 Esercizio 2 i=i*2) j=j*2) Soluzione Il frammento è composto da due parti quasi identiche. L unica differenza è il modo in cui crescono i contatori. Nella prima parte la crescita è lineare mentre
Algoritmi di ordinamento: Array e ricorsione
Laboratorio di Algoritmi e Strutture Dati Aniello Murano http://people.na.infn.it people.na.infn.it/~murano/ 1 Algoritmi di ordinamento: Array e ricorsione 2 1 Insertion Sort Quicksort Heapsort Indice
CAPITOLO 2. Divide et Impera
CAPITOLO 2 Divide et Impera In questo capitolo discuteremo alcuni algoritmi progettati mediante la tecnica di progettazione del Divide et Impera. Algoritmi progettati usando questa tecnica consistono di
Algoritmi e Strutture Dati. Capitolo 4 Ordinamento: Selection e Insertion Sort
Algoritmi e Strutture Dati Capitolo 4 Ordinamento: Selection e Insertion Sort Ordinamento Dato un insieme S di n elementi presi da un dominio totalmente ordinato, ordinare S in ordine non crescente o non
In questa lezione. Alberi binari: [CLRS09] cap. 12 per la visita inorder. visite e esercizi su alberi binari. Prof. E. Fachini - Intr. Alg.
In questa lezione Alberi binari: visite e esercizi su alberi binari [CLRS09] cap. 12 per la visita inorder!1 Visita inordine di un albero binario visita inordine(x) se l albero x non è nullo allora visita
Algoritmi e strutture dati
Algoritmi e Strutture Dati Capitolo 4 Ordinamento Ordinamento Dato un insieme S di n oggetti presi da un dominio totalmente ordinato, ordinare S Esempi: ordinare alfabeticamente lista di nomi, o insieme
Informatica Generale Andrea Corradini Algoritmi: ordinamento per inserimento e ricorsione
Informatica Generale Andrea Corradini 14 - Algoritmi: ordinamento per inserimento e ricorsione Sommario Un algoritmo iterativo: l'ordinamento per inserimento (insertion sort) La ricorsione: i numeri triangolari
QuickSort Università degli Studi di Milano
QuickSort Algoritmo di ordinamento sul posto che ha tempo di esecuzione : - O(n 2 ) nel caso peggiore - O(n log n) nel caso medio Nonostante le cattive prestazioni nel caso peggiore, rimane il miglior
Gli heap. Sommario. Algoritmi e Programmazione Avanzata. Fulvio CORNO - Matteo SONZA REORDA Dip. Automatica e Informatica Politecnico di Torino
Gli heap Fulvio CORNO - Matteo SONZA REORDA Dip. Automatica e Informatica Politecnico di Torino 1 a.a. 2001/2002 Sommario Gli heap L algoritmo Heapsort Le code con priorità. 2 a.a. 2001/2002 Politecnico
Definizioni di base. Algoritmo: procedura computazionale ben definita che prende valori in input e produce valori in output.
ANALISI DELLA COMPLESSITÀ DEGLI ALGORITMI Definizioni di base Algoritmo: procedura computazionale ben definita che prende valori in input e produce valori in output. Un algoritmo è uno strumento per risolvere
Prova di Algoritmi e s.d. (1o anno) 17 Settembre TESTO e RISPOSTE
Prova di Algoritmi e s.d. (1o anno) 17 Settembre 2002 TESTO e RISPOSTE Esercizio 1 (punti 7 in prima approssimazione) Consideriamo alberi binari con insieme dei nodi NODI = N (l'insieme dei naturali).
Esercitazione 2. Quicksort
Esercitazione 2 Quicksort Caratteristiche Algoritmo di ordinamento mediamente molto efficiente Vantaggio: ordinamento sul posto Basato sul paradigma divide et impera (come merge sort) Elemento chiave:
COMPLESSITÀ COMPUTAZIONALE DEGLI ALGORITMI
COMPLESSITÀ COMPUTAZIONALE DEGLI ALGORITMI Fondamenti di Informatica a.a.200.2005/06 Prof. V.L. Plantamura Dott.ssa A. Angelini Ω (grande omega) Diciamo che T(n) = Ω (f(n)), - leggiamo T(n) ha complessità
Algoritmi e Strutture di Dati
Algoritmi e Strutture di Dati Code di priorità (Heap e heap_sort) m.patrignani Nota di copyright queste slides sono protette dalle leggi sul copyright il titolo ed il copyright relativi alle slides (inclusi,
Complessità degli algoritmi
Complessità degli algoritmi Dipartimento di Elettronica, Informazione e Bioingegneria Politecnico di Milano 21 luglio 2017 Complessità di un algoritmo Quanto efficientemente risolviamo un problema? Dato
Selezione per distribuzione
Selezione per distribuzione Problema: selezione dell elemento con rango r in un array a di n elementi distinti. Si vuole evitare di ordinare a NB: Il problema diventa quello di trovare il minimo quando
Analisi algoritmi ricorsivi e relazioni di ricorrenza
Analisi algoritmi ricorsivi e relazioni di ricorrenza Punto della situazione Finora abbiamo affrontato: il tempo di esecuzione di un algoritmo, l analisi asintotica con le notazioni asintotiche e la tecnica
Algoritmi di ordinamento
Algoritmi di ordinamento! Selection Sort! Quick Sort! Lower bound alla complessità degli algoritmi di ordinamento Ordinamento 1 Selection Sort SelectionSort(dati[]) { for (i=0; idati.length-1; i++) { min
Note per la Lezione 4 Ugo Vaccaro
Progettazione di Algoritmi Anno Accademico 2016 2017 Note per la Lezione 4 Ugo Vaccaro Ripasso di nozioni su Alberi Ricordiamo che gli alberi rappresentano una generalizzazione delle liste, nel senso che
Algoritmi di ordinamento
Algoritmi di ordinamento Il problema Vogliamo ordinare un array monodimensionale in modo crescente per il caso decrescente valgono le stesse considerazioni Vari algoritmi possibili Diverse caratteristiche
Algoritmi e Strutture Dati & Laboratorio di Algoritmi e Programmazione
Algoritmi e Strutture Dati & Laboratorio di Algoritmi e Programmazione Appello del 24 Gennaio 2007 Esercizio 1 (ASD) 1. Sia T (n) = T (n/6) + T (n/3) + Θ(n). Considerare ciascuna delle seguenti affermazioni
Si imposti la relazione di ricorrenza che ne descrive la complessità e la si risolva utilizzando il metodo della sostituzione.
parte II - A 2 Si consideri la seguente funzione: analizzami(int n) c = 1 k = n*n while k > 1 do k = k/2 for i = 0 to 3 do if n >1 then analizzami(n/4) Si imposti la relazione di ricorrenza che ne descrive
Algoritmi e strutture di dati 2
Algoritmi e strutture di dati 2 Paola Vocca Lezione 1: Divide et Impera 1 Paradigma del divide et impera Strutturato in tre fasi. Sia Π() istanza di dimensione di un problema computazionale Π (dove è immediato
Esercizi di Algoritmi e Strutture Dati
Esercizi di Algoritmi e Strutture Dati Moreno Marzolla marzolla@cs.unibo.it Ultimo aggiornamento: 3 novembre 2010 1 Trova la somma/1 Scrivere un algoritmo che dati in input un array A[1... n] di n interi
Algoritmi (9 CFU) (A.A ) Heap e Algoritmo HeapSort. Prof. V. Cutello Algoritmi 1
Algoritmi (9 CFU) (A.A. 2009-10) Heap e Algoritmo HeapSort. Prof. V. Cutello Algoritmi 1 Overview Definiamo la struttura dati heap Operazioni di costruzione e gestione di un heap Algoritmo Heapsort Code
Algoritmi e Strutture di Dati I 1. Algoritmi e Strutture di Dati I Massimo Franceschet
Algoritmi e Strutture di Dati I 1 Algoritmi e Strutture di Dati I Massimo Franceschet Algoritmi e Strutture di Dati I 2 Problemi Un problema specifica in termini generali una relazione che intercorrere
Esercizi Capitolo 10 - Code con priorità e insiemi disgiunti
Esercizi Capitolo 10 - Code con priorità e insiemi disgiunti Alberto Montresor 19 Agosto, 2014 Alcuni degli esercizi che seguono sono associati alle rispettive soluzioni. Se il vostro lettore PDF lo consente,
Esercizi Capitolo 10 - Code con priorità e insiemi disgiunti
Esercizi Capitolo 10 - Code con priorità e insiemi disgiunti Alberto Montresor 27 marzo 2012 Alcuni degli esercizi che seguono sono associati alle rispettive soluzioni. Se il vostro lettore PDF lo consente,
Esercizi su alberi binari
Esercizi su alberi binari Esercizi svolti: Determinazione nodi contenti verifica completezza verifica quasi completezza lunghezza del cammino interno determinazione ultima foglia in un quasi completo verifica
Esercizio 1. E vero che in un AVL il minimo si trova in una foglia o nel penultimo livello? FB = -1. livello 0 FB = -1. livello 1 FB = -1.
Esercizio 1 E vero che in un AVL il minimo si trova in una foglia o nel penultimo livello? FB = -1 livello 0 FB = -1 FB = -1 livello 1 FB = -1 livello 2 livello 3 L altezza è 3, il minimo si trova nel
Progetto Corda. Alberto Ferrari. Alberto Ferrari Ingegneria dell'informazione, UniPR. 18/12/2017 Progetto Corda
Progetto Corda Alberto Ferrari Alberto Ferrari Ingegneria dell'informazione, UniPR file:///e:/cordanoweb/lez/array.html#3 1/33 Array (ordinamento) 2/33 file:///e:/cordanoweb/lez/array.html#3 2/33 Sort
Heap e code di priorità
Heap e code di priorità Violetta Lonati Università degli studi di Milano Dipartimento di Scienze dell Informazione Laboratorio di algoritmi e strutture dati Corso di laurea in Informatica AA 2009/2010
Alberi binari: definizione e alcune proprietà
Alberi binari: definizione e alcune proprietà Alberi binari Un albero binario è un albero con radice in cui ogni nodo ha al più due figli. In maniera più formale: Definizione. (Alberi binari) Un albero
Cammini minimi fra tutte le coppie
Capitolo 12 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)
Algoritmi e Strutture Dati. Capitolo 1 Un introduzione informale agli algoritmi
Algoritmi e Strutture Dati Capitolo Un introduzione informale agli algoritmi Ancora un esempio di problema e soluzioni algoritmiche: i numeri di Fibonacci verso un modello di calcolo più simile a un computer
Divide et impera. Vittorio Maniezzo Università di Bologna
Divide et impera 1 Vittorio Maniezzo Università di Bologna Divide et Impera Divide et impera: Dividi: se l istanza del problema da risolvere è troppo complicata per essere risolta direttamente, dividila
Algoritmi e strutture dati. Analisi di algoritmi Funzioni di costo, notazione asintotica
Algoritmi e strutture dati Analisi di algoritmi Funzioni di costo, notazione asintotica Alberto Montresor Università di Trento 2016/09/11 This work is licensed under a Creative Commons Attribution-ShareAlike
Dati e Algoritmi I (Pietracaprina) Esercizi sulle Nozioni di Base
Dati e Algoritmi I (Pietracaprina) Esercizi sulle Nozioni di Base Dati e Algoritmi I (Pietracaprina): Esercizi 1 Problema 1. Sia T una stringa arbitraria di lunghezza n 1 su un alfabeto Σ. È sempre possibile
Algoritmi e Strutture Dati
Algoritmi e Strutture Dati Esercitazione 7 Domenico Fabio Savo 1 Esercitazione: heap Abbiamo visto come utilizzare i MAX-HEAP nell'algoritmo di ordinamento heapsort che permette di ordinare un array di
Problemi, istanze, soluzioni
lgoritmi e Strutture di Dati II 2 Problemi, istanze, soluzioni Un problema specifica una relazione matematica tra dati di ingresso e dati di uscita. Una istanza di un problema è formata dai dati di un
Problem Set 2 docente: Luciano Gualà
Problem Set 2 docente: Luciano Gualà Esercizio 1 (equazioni di ricorrenza) Si risolvano le seguenti equazioni di ricorrenza. Si assuma sempre T (costante) = O(1). (a) T (n) = T (n 10) + 10. (b) T (n) =
Algoritmi e Strutture Dati
Algoritmi e Strutture Dati Capitolo 4 Ordinamento: Quicksort (*) e metodi di ordinamento lineari Punto della situazione Problema dell ordinamento: Lower bound (n log n) Upper bound O(n log n) Algoritmi
Dati e Algoritmi I (Pietracaprina) Esercizi sulle Nozioni di Base
Dati e Algoritmi I (Pietracaprina) Esercizi sulle Nozioni di Base Dati e Algoritmi I (Pietracaprina): Esercizi 1 Problema 1. Sia T una stringa arbitraria di lunghezza n 1 su un alfabeto Σ. È sempre possibile
Complementi di Algoritmi e Strutture Dati. Soluzioni prova scritta 7 giugno 2017
Complementi di Algoritmi e Strutture Dati (III anno Laurea Triennale - a.a. 2016/17) Soluzioni prova scritta 7 giugno 2017 Esercizio Union find (punti 6) Considerare la foresta union-find sottostante e
Divide et impera. Divide et impera. Divide et impera. Divide et impera
Divide et impera Divide et impera La tecnica detta divide et impera è una strategia generale per impostare algoritmi (par. 9.4). Consideriamo un problema P e sia n la dimensione dei dati, la strategia
Algoritmi di ordinamento
Algoritmi di ordinamento Il problema Vogliamo ordinare un array monodimensionale in modo crescente per il caso decrescente valgono le stesse considerazioni Vari algoritmi possibili Diverse caratteristiche
In questa lezione. Code di priorità. [CLRS01] cap. 6 da pag. 114 a pag Prof. E. Fachini - Intr. Alg. lunedì 17 settembre 2012
In questa lezione Code di priorità [CLRS01] cap. 6 da pag. 114 a pag. 117 1 Coda di priorità: cos è? Una coda di priorità è una struttura dati dinamica che permette di gestire dei dati con chiave numerica,
Informatica Generale Andrea Corradini Gli algoritmi e la risoluzione di problemi
Informatica Generale Andrea Corradini 13 - Gli algoritmi e la risoluzione di problemi Sommario Passi per la risoluzione di problemi Problemi di ricerca e ordinamento Algoritmi iterativi: la ricerca lineare
Calcolare x n = x x x (n volte)
Calcolare x n = x x x (n volte) Abbiamo bisogno di: una variabile ris in cui ad ogni iterazione del ciclo si ha un risultato parziale, e che dopo l ultima iterazione contiene il risultato finale; una variabile
Programmazione I - corso B a.a prof. Viviana Bono
Università di Torino Facoltà di Scienze MFN Corso di Studi in Informatica Programmazione I - corso B a.a. 2009-10 prof. Viviana Bono Blocco 15 Algoritmi su array: selection sort, insertion sort, fusione
Progettazione di algoritmi
Progettazione di algoritmi Discussione dell'esercizio [vincoli] Prima di tutto rappresentiamo il problema con un grafo G: i nodi sono le n lavorazioni L 1, L 2,, L n, e tra due nodi L h, L k c'è un arco