Algoritmi di ordinamento Capitolo 9 Leonora Bianchi IDSIA-DTI-SUPSI 11-04 Leonora Bianchi 1 terminologia • Algoritmo di ordinamento: metodo per ordinare un insieme di elementi o record(s) -- chiave • Record -- dato 1 -- dato 2 -- …. • insieme ordinato 11-04 1 2 3 Leonora Bianchi 4 4 2 Caratteristiche Casuale (vettori) Tipo di accesso ai dati Sequenziale (liste, files, dischi) stabile Tipo di ordine instabile ausiliaria (alg. esterni) memoria oppure no (alg. Interni) Risorse tempo di calcolo 11-04 Leonora Bianchi F(n) 3 i n t e r n i e s t e r n i 11-04 ordinamento per inserimento ordinamento per selezione diretta ordinamento per scambio diretto o `a bolle’ ordinamento mediante heap Insertion sort ordinamento rapido Quick sort ordinamentoper conta distribuita Distribution counting Leonora Bianchi Selection sort Bubble sort Heap sort 4 Con chi devono fare i conti Strutture dati Risorse • accesso sequenziale • accesso ‘casuale’ • alberi •… • memoria • velocita’ CPUs • velocita’ di realizzazione •… Algoritmi ordinamento 11-04 Leonora Bianchi 5 Carta d’identita` • Nome: insertion sort • Tipo di accesso ai dati: sequenziale • Stabilita`: SI • Risorse: memoria ausiliaria: NO tempo di calcolo: caso peggiore: O(n2) caso medio: O(n2) caso migliore: O(n) •Segni particolari: ok per vett. quasi ordinati 11-04 Leonora Bianchi 6 Insertion sort • esempio • algoritmo • complessita` Smin = 2(n-1) per vettori ordinati ! Smax = 1/2 (n2 + 3n - 4) Smed = 1/2 (Smin + Smax) = 1/2 (n2 + 7n - 8) C < (n-1) log2n 11-04 Leonora Bianchi 7 Insertion sort - algoritmo For ( i = 2, …, n ) x = a(i); s=1; d=i-1 while ( s <= d) m = (s+d)/2 if( x < a(m) ) d = m-1 else s = m+1 end if end while For (j = i-1, i-2, …, s) a(j+1) = a(j) end For a(s) = x End for 11-04 Leonora Bianchi 8 Selection sort • esempio • algoritmo • complessita` S =3(n-1) C = 1/2 (n2 - n) per qualsiasi vettore! 11-04 Leonora Bianchi 9 Selection sort - algoritmo (≠ dispense) For ( i = 1 .. n-1 ) min := i for ( j = i+1 .. n) if ( a(j) < a(min) ) min = j end if end for t = a(min) a(min) = a(i) a(i) = t End for 11-04 Leonora Bianchi 10 • Nome: insertion sort • Tipo di accesso ai dati: sequenziale • Stabilita`: SI • Risorse: memoria ausiliaria: NO tempo di calcolo: caso peggiore: O(n2) caso medio: O(n2) caso migliore: O(n) 11-04 •Segni particolari: ok per vett. quasi ordinati Leonora Bianchi 11 • Nome: selection sort • Tipo di accesso ai dati: sequenziale • Stabilita`: SI • Risorse: memoria ausiliaria: NO tempo di calcolo: sempre: O(n2) •Segni particolari: performance quasi indipendente dall’input 11-04 Leonora Bianchi 12 Bubble sort 1 (fig. 9.3) For ( s = 2, ... n ) for ( j = n, n-1,…,s ) if ( a(j-1) > a(j) ) x = a(j-1), a(j-1) = a(j), a(j) = x //scambio end if end for End for → esempio dispense 11-04 Leonora Bianchi 13 Bubble sort 2 (fig. 9.4) S=2 Flag = TRUE While ( flag ) Flag = FALSE // scambio no for ( j = n, n-1,…,s ) if ( a(j-1) > a(j) ) flag = TRUE //scambio si x = a(j-1), a(j-1) = a(j), a(j) = x //scambio k=j //posizione scambio end if end for if ( flag == TRUE ) s = k +1 End while 11-04 → esempio Leonora Bianchi 14 Bubble sort 3 (fig. 9.5) (≠ dispense) S = 2, d = n, k =n While ( s <= d ) for ( j = d, d-1,…,s ) if ( a(j-1) > a(j) ) x = a(j-1), a(j-1) = a(j), a(j) = x //scambio k=j //posizione scambio end if end for s = k+1 for ( j = s, s+1,…,d ) if ( a(j-1) > a(j) ) x = a(j-1), a(j-1) = a(j), a(j) = x //scambio k=j //posizione scambio end if end for d = d-1 11-04 End while → esempio Leonora Bianchi 15 Bubble sort - versioni 1. Scansione da DX a SX (o viceversa) fig. 9.3 2. Tiene conto della parte ordinata e quindi risparmia confronti se possibile fig. 9.4 3. Scansione alternata da DX a SX e viceversa fig. 9.5 4. Versione 1 modificata fig. 9.6 11-04 Leonora Bianchi 16 Bubble sort - complessita’ Versione 1 (piu’ semplice) C = 1/2 n (n-1) Smax = 3/2 n (n-1) Smin = 0 Versione 2 (piu’ semplice) Cmin = n Smin = 0 → dipende dall’input, simile a insertion sort 11-04 Leonora Bianchi 17 Heap a 1 2 3 a(i) genitore a(2i) figlio SX a(2i +1) figlio DX 11-04 4 5 6 7 8 9 a(i).chiave ≤ a(2i).chiave a(i).chiave ≤ a(2i +1).chiave Leonora Bianchi 18 “heapifizzare” Perché? Metodo per estrarre la chiave più piccola, dato che radice.chiave ≤ discendenti.chiave “heapifizzare” a(s),…,a(n) = inserimento_in_heap(s,n,a) = trovare la chiave più piccola tra a(s), a(s+1),…,a(n) 11-04 Leonora Bianchi 19 Come sfruttare la heap Considero a(1,2,…n) non ordinato Heapifizzo a(1,2,…,n) Estraggo a(1), scambio a(1) con a(n) Heapifizzo a(1,2,…,n-1) Estraggo a(1), scambio a(1) con a(n-1) . Heapifizzo a(1,2) Estraggo a(1), scambio a(1) con a(2) ⇒ Ho un vettore ordinato dal più grande al più piccolo Se in Heapifizzo uso “≥” anziché “≤” ⇒ Ho un vettore ordinato dal più piccolo al più grande 11-04 Leonora Bianchi 20 Pseudocodice per heap sort For (s = n/2, n/2 -1, …, 1) inserimento_in_heap(s,n,a) End for For (d = n, n -1, …, 2) scambio a(1) con a(d) inserimento_in_heap(1,d-1,a) End for Heapifizzo a una prima volta Scambio e heapifizzo solo la parte disordinata, per n-1 volte → esempio 11-04 Leonora Bianchi 21 Complessità For (s = n/2, n/2 -1, …, 1) inserimento_in_heap(s,n,a) End for For (d = n, n -1, …, 2) scambio a(1) con a(d) S≤ (n/2 +n-1)* (scambi inserimento_in_heap) + n-1 ≤ (n/2 +n-1)* log2n + n-1 inserimento_in_heap(1,d-1,a) End for S ≤ O(n log2n) C ≤ 2* (scambi inserimento_in_heap) * (n/2 +n-1) C ≤ O(n log2n) 11-04 Leonora Bianchi 22 Tabella riassuntiva Nome Caso peggiore Insertion O(n2) Caso medio Caso migliore Interno/esterno O(n2) O(n) interno vettori quasi ordinati Selection O(n2) O(n2) indipendente dall’input Bubble O(n2) O(n2) interno indipendente dall’input O(n2) O(n) interno vettori quasi ordinati Heap 11-04 O(n logn) O(n logn) O(n logn) interno Leonora Bianchi 23 Quicksort - l’idea principale Separa(s, d, a) x s d 1 2 3 4 5 6 7 8 44 55 12 12* 93 16 5 60 i j 44 55 12 12* 93 16 5 60 5 i j 55 12 12* 93 16 44 60 ij 5 12* 12 55 93 16 44 60 j i 5 12* 12 55 93 16 44 60 11-04 Leonora Bianchi 24 Separa(s,d,a) i=s, j=d, x = a((s+d)/2) While ( i <= j ) while ( a(i) <= x ) i=i+1 end while while ( a(j) > x ) j=j-1 end while if( i < j ) scambio a(i) con a(j) else if (i == j) i = i+1 End while If( s < j ) separa(s, j, a) end if If( i < d ) separa(i, d, a) end if Quicksort(a) Separa(1, n, a) 11-04 Leonora Bianchi 25 Quicksort iterativo h = 1, stack(h).s = 1, stack(h).d = n While ( h > 0 ) while(s < d ) s = stack(h).s, d = stack(h).d, h = h-1 separa(s, d, a) //ma senza chiamata ricorsiva a separa //ora considero le due metà: (s,….,j) e (i,…., d) // la metà DX (i,…., d) va nello stack if( i<d ) h = h+1, stack(h).s = i, stack(h).d = d end if // la metà SX (s,….,j) viene elaborata subito d=j end while end while 11-04 Leonora Bianchi 26 Quicksort - complessità Caso migliore: la separazione divide il vettore in due metà di lunghezza uguale → C ≈ n log n Caso peggiore: c’è sempre una parte lunga → C ≈ n2 Caso medio → C ≈ n log n 11-04 Leonora Bianchi 27 Ordinamento per conta distribuita • Il più veloce: →S≈n • Però occupa memoria esterna: → memoria > 2n • Inoltre: assunzioni particolari 11-04 Leonora Bianchi 28 Assunzioni Chiave dei record: • numero intero • Compreso tra MIN e MAX • MIN e MAX noti Vettori ausiliari: • b = vettore lungo come quello da ordinare (a) • c = vettore con MAX-MIN+1 elementi 11-04 Leonora Bianchi 29 Passaggi preliminari i= 1 a= 7 2 2 3 1 4 4 5 6 6 7 8 4* 3 2* MAX = 7 Calcolo frequenze: Valore in a = MIN = 1 1 2 3 4 5 6 7 c= 1 2 1 2 0 1 1 Calcolo frequenze accumulate: c(i) = c(i-1) +1 Valore in a = 1 2 3 4 5 6 7 c= 1 3 4 6 6 7 8 Frequenza accumulata ----> posizione nel vettore ordinato (b) 11-04 Leonora Bianchi 30 Pseudocodice // inizializzazione di c For( j = MIN, MIN+1, …, MAX) c(j) = 0 End for // memorizzo in c le frequenze delle chiavi di a For( i = 1,…, n ) c( a(i) ) = c( a(i) ) +1 End for // modifico c in modo che contenga le frequenze accumulate For( j = MIN+1, …, MAX) c( j ) = c( j-1 ) + c( j ) End for // Costruisco il vettore ordinato b For( i = n, n-1, …, 1 ) k = a(i), b( c(k) ) = a(i), c(k) = c(k) -1 End for 11-04 Leonora Bianchi 31 Complessità // inizializzazione di c m = MAX-MIN +1 For( j = MIN, MIN+1, …, MAX) c(j) = 0 End for // memorizzo in c le frequenze delle chiavi di a For( i = 1,…, n ) n c( a(i) ) = c( a(i) ) +1 End for // modifico c in modo che contenga le frequenze accumulate For( j = MIN+1, …, MAX) c( j ) = c( j-1 ) + c( j ) m-1 End for // Costruisco il vettore ordinato b For( i = n, n-1, …, 1 ) k = a(i), b( c(k) ) = a(i), c(k) = c(k) -1 3n End for 11-04 Leonora Bianchi 32 …premessa: il quicksort va male quando la separazione non divide il vettore in due metà equivalenti…. Mergesort d (s+d)/2 s Ordino ricorsivamente con mergesort Ordino ricorsivamente con mergesort ordinato ordinato Merge (fusione) 11-04 Leonora Bianchi 33 Esempio 44 55 12 12* 93 16 5 60 Ordino ricorsivamente due metà 44 93 16 55 5 12 12* 60 Coppie ordinate 5 12 44 93 12* 16 55 60 2 metà ordinate fusione 5 12 12* 16 44 55 60 93 11-04 Leonora Bianchi 34 …Esempio - complessità 44 55 12 12* 93 16 5 60 n/2 * Fusione(1,1) 44 93 16 55 5 12 12* 60 n/4 * Fusione(2,2) 5 12 44 93 12* 16 55 60 n/8 * Fusione(4,4) 5 12 12* 16 44 55 60 93 11-04 Leonora Bianchi 35 Fusione di due insiemi già ordinati a(m) b(m) i c(m+m) j k i =1, j=1 For(k=1,2,…,2m) if(i <=n and j<= m) if( a(i) < b(j) ) c(k) = a(i), i=i+1 else c(k) = b(j), j = j+1 end if else if ( i>n ) c(k) = b(j), j = j+1 else c(k) = a(i), i = i+1 End for Fusione(m+m) ≈ 2m confronti + 2m memoria 11-04 Leonora Bianchi 36 …Esempio - complessità 44 55 12 12* 93 16 5 60 n/2 * Fusione(1,1) =n 44 93 16 55 5 12 12* 60 n/4 * Fusione(2,2) =n n/8 * Fusione(4,4) =n 5 12 44 93 12* 16 55 60 5 12 12* 16 44 55 60 93 Confronti e Ass. Mergesort ≈ n * numero fusioni = n * log2n Memoria aggiuntiva Mergesort ≈ n 11-04 Leonora Bianchi 37 Complessità O(n logn) anche nel caso peggiore Però necessita memoria aggiuntiva O(n) 11-04 Leonora Bianchi 38 Mergesort con accesso sequenziale an an+1 a1 prelevo a2n deposito i j k l 44 55 12 12* 93 16 5 60 44 60 i j 55 12 12* 93 16 5 j i 12 12* 93 16 i j 12* 93 11-04 k l 44 60 55 5 k 44 60 12 16 l 55 5 l k 44 60 12 16 93 12* 55 5 Leonora Bianchi 39 prelevo deposito k l 5 j i 44 60 12 16 93 12* 55 5 k j i 44 60 12 16 93 12* 55 5 44 j i 60 12 16 93 12* 55 k 5 44 55 k 5 44 55 60 11-04 l i j 60 12 16 93 12* Leonora Bianchi 40 riassunto Nome Caso peggiore Caso medio Caso migliore Interno/esterno Insertion O(n2) O(n2) O(n) vettori quasi ordinati interno Selection O(n2) O(n2) indipendente dall’input O(n2) interno Bubble O(n2) O(n2) O(n) vettori quasi ordinati interno Heap O(n logn) O(n logn) più lento di quicksort O(n logn) interno Quicksort O(n2) O(n logn) O(n logn) esterno Conta distribuita O(n) O(n) O(n) Esterno O(n+range) Mergesort O(n logn) O(n logn) indipendente Leonora Bianchi dall’input O(n logn) Esterno O(n) 11-04 41