Docsity
Docsity

Prepara i tuoi esami
Prepara i tuoi esami

Studia grazie alle numerose risorse presenti su Docsity


Ottieni i punti per scaricare
Ottieni i punti per scaricare

Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium


Guide e consigli
Guide e consigli


Algoritmi di ordinamento quadratici: Insertion-Sort e Selection-Sort, Dispense di Algoritmi E Strutture Di Dati

E dimostra la correttezza degli algoritmi di ordinamento quadratici insertion-sort e selection-sort, analizzandone la complessità computazionale nel caso peggiore e nel caso migliore. Vengono inoltre introdotti i concetti di invariante e di analisi di complessità.

Tipologia: Dispense

2018/2019

Caricato il 08/05/2019

alessandro-bacci
alessandro-bacci 🇮🇹

5 documenti

1 / 5

Toggle sidebar

Questa pagina non è visibile nell’anteprima

Non perderti parti importanti!

bg1
Ordinamento (algoritmi quadratici)
March 7, 2018
Obiettivi:
attraverso lo studio degli algoritmi di ordinamento quadratici, applicare la nozione di invariante
e introdurre l'analisi di complessità.
Argomenti:
problema dell'ordinamento, insertion-sort e selection-sort con analisi di correttezza e comp-
lessità.
1 Problema dell'ordinamento (sorting)
La ricerca in un vettore di
n
elementi richiede
n
confronti nel caso peggiore.
Se il vettore è ordinato, si può applicare la ricerca binaria (ricerca dicotomica) che richiede al più
log2n
confronti:
BinSearch-Ric
(
x, A, i, j
)
.
Pre:
A[i..j]
ordinato
.
Post:
true
se
xA[i..j]
if
i>j
then
. A[i..j] =
return
false
else
m b(i+j)/2c
if
x=A[m]
then
return
true
else
if
x<A[m]
then
return
BinSearch-Ric
(x, A, i, m 1)
else
. A[m]< x
return
BinSearch-Ric
(x, A, m + 1, j )
end if
end if
end if
Per ordinare un vettore, si potrebbe pensare di generare tutte le permutazioni e scegliere quella nella quale
gli elementi sono ordinati:
Sorted
(
A[1..n]
)
for
i2
to
n
do
if
A[i1] > A[i]
then
return
false
end if
end for
return
true
1
pf3
pf4
pf5

Anteprima parziale del testo

Scarica Algoritmi di ordinamento quadratici: Insertion-Sort e Selection-Sort e più Dispense in PDF di Algoritmi E Strutture Di Dati solo su Docsity!

Ordinamento (algoritmi quadratici)

March 7, 2018

Obiettivi: attraverso lo studio degli algoritmi di ordinamento quadratici, applicare la nozione di invariante e introdurre l'analisi di complessità. Argomenti: problema dell'ordinamento, insertion-sort e selection-sort con analisi di correttezza e comp- lessità.

1 Problema dell'ordinamento (sorting)

La ricerca in un vettore di n elementi richiede n confronti nel caso peggiore.

Se il vettore è ordinato, si può applicare la ricerca binaria (ricerca dicotomica) che richiede al più log 2 n confronti:

BinSearch-Ric(x, A, i, j)

. Pre: A[i..j] ordinato . Post: true se x ∈ A[i..j] if i > j then. A[i..j] = ∅ return f alse else m ← b(i + j)/ 2 c if x = A[m] then return true else if x < A[m] then return BinSearch-Ric(x, A, i, m − 1) else. A[m] < x return BinSearch-Ric(x, A, m + 1, j) end if end if end if

Per ordinare un vettore, si potrebbe pensare di generare tutte le permutazioni e scegliere quella nella quale gli elementi sono ordinati:

Sorted(A[1..n]) for i ← 2 to n do if A[i − 1] > A[i] then return false end if end for return true

Trivial-Sort(A) for all A′^ permutazione di A do if Sorted(A′) then return A′ end if end for

Ma il numero di permutazioni è n! che cresce più velocemente di 2 n. Non è praticabile.

2 Insertion-sort

L'idea generale: data un vettore con la parte sinistra, A[1..i − 1], ordinata, è facile inserirci l'elemento A[i] in modo tale che il sottovettore A[1..i] risulti ordinata (aumentando così la parte ordinata). Punto di partenza: i = 2 (così la parte a sinistra di A[i] contiene un singolo elemento e quindi è ordinata).

0: Insertion-Sort(A[1..n]) 1: for i ← 2 to n do 2: j ← i 3: while j > 1 and A[j − 1] > A[j] do 4: scambia A[j − 1] con A[j] 5: j ← j − 1 6: end while 7: end for

Simulazione con A = (2, 6 , 3 , 1 , 5 , 4). La parte ordinata del vettore viene scritto in grassetto. Il numero che deve essere inserito al posto giusto viene scritto in corsivo. i = 2, j = 2 : ( 2 , 6 ,3,1,5,4) i = 3, j = 3 : (2,6, 3 ,1,5,4) i = 3, j = 2 : ( 2 , 3 , 6 ,1,5,4) i = 4, j = 4 : ( 2 , 3 , 6 , 1 ,5,4) i = 4, j = 3 : ( 2 , 3 , 1 , 6 ,5,4) i = 4, j = 2 : ( 2 , 1 , 3 , 6 ,5,4) i = 4, j = 1 : ( 1 , 2 , 3 , 6 ,5,4) i = 5, j = 5 : ( 1 , 2 , 3 , 6 , 5 ,4) i = 5, j = 4 : ( 1 , 2 , 3 , 5 , 6 ,4) i = 6, j = 6 : ( 1 , 2 , 3 , 5 , 6 , 4 ) i = 6, j = 5 : ( 1 , 2 , 3 , 5 , 4 , 6 ) i = 6, j = 4 : ( 1 , 2 , 3 , 4 , 5 , 6 ) i = 7 : ( 1 , 2 , 3 , 4 , 5 , 6 )

2.1 Dimostrazione della correttezza con invarianti

Invariante del ciclo esterno:

il sottovettore A[1..i − 1] è ordinato.

Inizializzazione: con i = 2 è vero (fa riferimento ad un vettore di un singolo elemento). Mantenimento: assumendo che il ciclo interno inserisci al posto giusto A[i] (la dimostreremo di seguito) l'invariante viene mantenuta. All'uscita: con i = n + 1 l'invariante implica che il vettore è ordinato.

Invariante del ciclo interno:

il vettore composto da A[1..j − 1] e A[j + 1..i] è ordinato ∧ ∀k, j + 1 ≤ k ≤ i.A[j] < A[k]

Di conseguenza, per valori grandi di n, Tcp(n) ≈ an

e quindi il tempo di esecuzione nel caso migliore è proporzionale al numero di elementi del vettore. Nel caso migliore l'algoritmo è lineare.

3 Selection-sort

L'idea generale: data un vettore in cui la parte sinistra, A[1..i − 1], è ordinata e contiene gli i − 1 numeri più piccoli del vettore, si cerca il minimo della parte A[i..n] e si mette nella posizione i (aumentando così la parte ordinata). Punto di partenza: i = 1 (così la parte a sinistra di A[i] è un vettore vuoto).

0: Selection-Sort(A[1..n]) 1: for i ← 1 to n − 1 do 2: k ← i 3: for j ← i + 1 to n do 4: if A[k] > A[j] then 5: k ← j 6: end if 7: end for 8: scambia A[i] con A[k] 9: end for

3.1 Dimostrazione della correttezza con invarianti

Invariante del ciclo esterno:

il sottovettore A[1..i − 1] è ordinato ∧ ∀k, l, 1 ≤ k ≤ i − 1 , i ≤ l ≤ n.A[k] ≤ A[l]

Inizializzazione: con i = 1 la proposizione è vuota e quindi vale. Mantenimento: assumendo che il ciclo interno selezioni il minimo del A[i..n] correttamente (la discuteremo di seguito) l'invariante viene mantenuta. All'uscita: con n = 1 l'invariante implica

il sottovettore A[1..n − 1] è ordinato ∧ A[n − 1] ≤ A[n]

e quindi il vettore è ordinato.

Invariante del ciclo interno: A[k] è il minimo in A[i..j − 1]

Inizializzazione: con k = i e j = i + 1 è triviale. Mantenimento: come ipotesi induttiva assumiamo che l'invariante vale prima di eseguire il ciclo; il corpo del ciclo aggiorna la posizione del massimo se A[k] > A[j] e poi in ogni caso incrementa j; quindi l'invariante viene mantenuta. All'uscita: con j = n + 1 l'invariante implica che A[k] è il minimo in A[i..n] e quindi il ciclo interno funziona correttamente.

Quindi l'algoritmo Selection-Sort è corretto.

3.2 Tempo di esecuzione del Selection-Sort

Deriviamo il tempo di esecuzione calcolando quante volte vengono eseguite le righe 1,2,3,4,5 e 8. Associamo con ognuna di queste righe un tempo di esecuzione uguale a 1 unità di tempo, cioè c 1 = c 2 = c 3 = c 4 = c 5 = c 8 = 1. Questa scelta non cambia in che modo il tempo di esecuzione dipende dal numero di elementi del vettore.

Nel caso peggiore l'indice del minimo in A[i..n] viene aggiornato ogni volta (cioè la condizione della riga 4 risulta sempre true):

Tcp(n) = (^) ︸︷︷︸n riga 1

  • n ︸ ︷︷ ︸ − 1 riga 2

n∑− 1

i=

(n − (i + 1) + 1 + 1) ︸ ︷︷ ︸ riga 3

n∑− 1

i=

(n − (i + 1) + 1) ︸ ︷︷ ︸ riga 4

n∑− 1

i=

(n − (i + 1) + 1) ︸ ︷︷ ︸ riga 5

  • n ︸ ︷︷ ︸ − 1 riga 8

︸︷︷︸^ n riga 1

  • n ︸ ︷︷ ︸ − 1 riga 2

n∑− 1

i=

(n − i + 1) ︸ ︷︷ ︸ riga 3

n∑− 1

i=

(n − i) ︸ ︷︷ ︸ riga 4

n∑− 1

i=

(n − i) ︸ ︷︷ ︸ riga 5

  • n ︸ ︷︷ ︸ − 1 riga 8

︸︷︷︸^ n riga 1

  • n ︸ ︷︷ ︸ − 1 riga 2

n∑− 1

i=

(i + 1) ︸ ︷︷ ︸ riga 3

n∑− 1

i=

i ︸ ︷︷ ︸ riga 4

n∑− 1

i=

i ︸ ︷︷ ︸ riga 5

  • n ︸ ︷︷ ︸ − 1 riga 8

La precedente è un polinomio di secondo grado in n. Per grandi valori di n, il tempo di esecuzione è proporzionale al quadrato del numero di elementi. Quindi nel caso peggiore l'algoritmo è quadratico.

Nel caso migliore il termine associato con la riga 5 è 0 (non viene mai aggiornato la posizione del minimo). Nonostante ciò, il tempo di esecuzione, Tcm(n), è un polinomio di secondo grado in n. Quindi anche nel caso migliore l'algoritmo è quadratico.

4 Minimo numero di confronti per ordinare un vettore

I confronti che si devono fare per ordinare un vettore si possono rappresentare con alberi binari di decisione in cui i nodi interni rappresentano i confronti e le foglie i possibili ordini nali. Il seguente albero rappresenta i confronti necessari per ordinare un vettore di tre elementi.

Tale albero, per un vettore di n elementi, ha n! foglie (tutte le possibili permutazioni devono esserci).

Con n! foglie, il ramo più lungo contiene almeno dlog 2 n!e nodi interni. (Nel caso di n = 3, abbiamo dlog 2 3!e = 3.)

Ciò signica che un algoritmo di ordinamento per confronti deve fare nel caso peggiore almeno dlog 2 n!e confronti.

Secondo la formula di Stirling, per grandi valori di n, si può approssimare n! con

n! ≈

2 πn

( (^) n e

)n

Dopo qualche algebra segue che, per grandi valori di n, il numero di confronti che un algoritmo di ordinamento per confronti deve fare nel caso peggiore è proporzionale a

n log 2 n