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