Sommario della lezione
Ulteriori applicazioni della tecnica Divide et Impera:
Derivazione dell’algoritmo di ordinamento Quicksort
1. Analisi del suo caso peggiore – O(n2 )
2. Analisi del suo caso medio – O(n log n)
Varie ed interessanti considerazioni sull’utilitá di
effettuare "scelte casuali" all’interno di algoritmi
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 1/37
Ricordiamo MergeSort...
M ERGE S ORT(A[1 . . . n])
if
n = 1 then return A else
A1 ← M ERGE S ORT(A[1 . . . ⌊n/2⌋])
A2 ← M ERGE S ORT(A[⌊n/2⌋ + 1 . . . n])
return M ERGE (A1 , A2 )
Una parte dispendiosa dell’algoritmo é certamente la fase
M ERGE (A1 , A2 ) (richiede tempo Θ(n)). Certo che se tutti gli
elementi in A1 fossero piú piccoli di tutti gli elementi di A2 ,
potremmo risparmiarci tale fase, basterebbe semplicemente
scrivere gli elementi di A2 dopo quelli di A1 .
E se non lo sono? Potremmo far precedere il tutto da un algoritmo
che riorganizza gli elementi di A in modo tale che a "sinistra"
compaiano gli elementi "piccoli", ed a "destra" compaiano quelli
"grandi."
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 2/37
Ció ci conduce alla idea di base di Quicksort
Sia un array A[1 . . . n] di numeri distinti, che vogliamo
ordinare. L’algoritmo Quicksort(A) procede secondo la
tecnica di Divide et Impera nel modo seguente:
1. Preso un elemento a di A, dividi l’array A in tre sottoarray
A1 , A2 , A3 , dove A1 contiene tutti gli elementi di A che sono
< a, A2 contiene tutti gli elementi di A che sono = a, A3
contiene tutti gli elementi di A che sono > a (ció puó essere
fatto confrontando uno ad uno gli elementi di A con a)
2. Applica ricorsivamente Quicksort su A1 e A3
3. La versione ordinata di A sará quindi uguale a
(Quicksort(A1 ), A2 , Quicksort(A3 ))
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 3/37
Quicksort: Idea
Un pó piú formalmente
Quicksort(A)
1. if |A| ≤ 1
2.
then return(A)
3.
else
4.
Scegli un elemento a da A e DIVIDI l’array A in
A1 , A2 ed A3 , dove A1 = {x ∈ A : x < a},
A2 = {x ∈ A : x = a}, e A3 = {x ∈ A : x > a},
5.
return(Quicksort(A1 ), A2 , Quicksort(A3 ))
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 4/37
Quicksort: Idea
Partiamo da
A=
a
⇓
dividiamo A:
A1 =tutti x < a
a
A3 = tutti x > a
a
A3 ordinato
⇓
ricorriamo in A1 e A3
A1 ordinato
Per come é fatto Quicksort, la fase di composizione di
sottosoluzioni di sottoproblemi in soluzioni a problemi piú
grandi é inesistente
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 5/37
Esempio: Quicksort(5 3 1 9 8 2 4 7)
5
3
1
3
1
2
1
2
3
9
4
4
8
5
5
2
7
7
4
8
8
7
9
9
a=7
Quicksort(7 8 9)
..
.
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 6/37
Analisi della complessitá di Quicksort
Dato l’array A[1 . . . n] da ordinare, per ogni elemento x in A,
definiamo il rango di x come il numero di elementi in A che
sono ≤ x
Ad esempio, l’elemento MINIMO di A ha rango 1,
l’elemento MASSIMO di A ha rango n.
In generale, un elemento x ha rango i ⇐⇒ nella versione
ordinata di A l’elemento x occupa la posizione i
Notiamo che se in Quicksort dividessimo l’array A usando
un elemento a di rango i, allora avremmo che
|A1 | = |{x : x < a}| = i − 1
|A3 | = |{x : x > a}| = n − i
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 7/37
Analisi della complessitá di Quicksort
Quicksort(A)
1. if |A| ≤ 1
2.
then return(A)
else
3.
Scegli un elemento a da A e DIVIDI l’array A in
A1 , A2 ed A3 , dove A1 = {x ∈ A : x < a},
A2 = {x ∈ A : x = a}, e A3 = {x ∈ A : x > a},
4.
return(Quicksort(A1 ), A2 , Quicksort(A3 ))
T (n)=tempo di esecuzione di Quicksort(A) = tempo per dividere A
in A1 , A2 e A3 + (tempo per eseguire Quicksort(A1 ) + tempo per
eseguire Quicksort(A3 )) = Θ(n) +T (i − 1) +T (n − i) (se
l’elemento a scelto al passo 3. ha rango i)
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 8/37
Analisi della complessitá di Quicksort
Quindi, se abbiamo scelto un elemento di rango i come Pivot,
abbiamo la seguente equazione di ricorrenza per la
complessitá di Quicksort
T (n) = T (i − 1) + T (n − i) + Θ(n)
Tale equazione di ricorrenza ha diverse soluzioni a seconda
del valore di i. Ad esempio, se scegliessimo sempre un Pivot
di rango i = n (cioé sempre il massimo del (sotto)array da
ordinare), avremmo
T (n) = T (n − 1) + Θ(n)
che ha soluzione T (n) = Θ(n2 ) (peggio di Mergesort!)
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 9/37
Analisi della complessitá di Quicksort
Infatti
T (n) = T (n − 1) + Θ(n) = T (n − 2) + Θ(n − 1) + Θ(n)
= T (n − 3) + Θ(n − 2) + Θ(n − 1) + Θ(n)
= . . . = T (0) + Θ(1) + Θ(2) + . . . + Θ(n − 1) + Θ(n)
!
n
n
X
X
k = Θ(n2 )
Θ(k) = Θ
=
k=1
(ricordando che
n
X
k=1
k = Θ(n2 ))
k=1
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 10/37
ritornando a Quicksort...
abbiamo che la complessitá di Quicksort, nell’ipotesi di
scegliere ad ogni passo, come Pivot, l’elemento di rango n
nel relativo sottoarray da ordinare, é
T (n) = Θ
n
X
k=1
k
!
= Θ(n2 )
É una situazione che puó effettivamente capitare?
Si. Ad esempio se il vettore é ordinato in senso decrescente,
e decidessimo di scegliere come Pivot sempre il primo
elemento a sinistra dell’array.
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 11/37
Esempio: Quicksort(8 7 6 5 4 3 2 1)
8
7
6
5
7
6
5
4
6
5
4
3
5
4
3
2
4
3
2
1
3
2
1
6
2
1
7
7
1
8
8
8
... e cosí via. Quindi, ad ogni passo avremmo una partizione
dell’array su cui stiamo correntemente ricorrendo con tutti
meno 1 (il Pivot) gli elementi a sinistra, ed un solo elemento a
destra. Ció dá origine alla ricorrenza
T (n) = T (n − 1) + Θ(n)
ed alla relativa soluzione T (n) = Θ(n2 )
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 12/37
Vediamo un’altro caso
Che succederebbe invece se ad ogni iterazione di Quicksort
scegliessimo come Pivot un elemento di rango i = n/2?
(Ovvero un elemento che ha n/2 altri elementi ≤ di esso e
n/2 altri elementi > di esso) Succederebbe che avremmo
una equazione di ricorrenza del tipo
T (n) = T (i − 1) + T (n − i) + Θ(n) = 2T (n/2) + Θ(n)
che é la stessa di Mergesort, e che ha soluzione
T (n) = O(n log n)
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 13/37
Cosa abbiamo appreso?
Esistono dei casi in cui Quicksort ha complessitá
..
O(n log n)
⌣
Esistono dei casi in cui Quicksort ha complessitá
..
Θ(n2 )
⌢
Protremmo rientrare sempre nel caso "buono" O(n log n)
se fossimo in grado di scegliere, ad ogni iterazione di
Quicksort, un elemento di rango pari alla metá del
numero di elementi del (sotto)array che stiamo
correntemente ordinando.
Purtroppo scegliere un elemento siffatto é difficile...
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 14/37
Ma é proprio necessario un Pivot di rango n/2?
Che succederebbe invece se ad ogni iterazione di Quicksort
scegliessimo come Pivot un elemento di rango i = n/100?
(Ovvero un elemento che ha n/100 altri elementi ≤ di esso e
(99n)/100 altri elementi > di esso) Succederebbe che
avremmo una equazione di ricorrenza del tipo
T (n) = T (i−1)+T (n−i)+Θ(n) = T (n/100)+T ((99n)/100)+Θ(n)
che ha ancora soluzione
T (n) = O(n log n)
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 15/37
Vediamolo
n 99n
T (n) = T
+T
+ Θ(n)
100
100
n n 99n
=T
+T
+Θ
2
2
100
100
100
2 99n
99 n
99n
+T
+ Θ(n)
+
T
+
Θ
2
2
100
100
100
2 n 99n
99n
99 n
+T
+T
+T
+ Θ(n) + Θ(n)
=T
2
2
2
2
100
100
100
100
2 h 99 n
99 n
h
≤ 22 T
+
2Θ(n)
≤
.
.
.
≤
2
T
+ hΘ(n)
2
h
100
100
h 99 n
= 1, per h = log100/99 n, da cui otteniamo T (n) = O(n log n)
100h
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 16/37
Ricapitoliamo...
Sembra pertanto che esistano "molte" possibili scelte del
Pivot in Quicksort che portano ad una complessitá
O(n log n), (non solo i Pivot di rango n/2 ma anche quelli
di rango αn, ∀α costante < 1) e che quindi ci vanno bene
Peró resta sempre difficile scegliere Pivot siffatti in
maniera che ci vada bene...
Sembra altresí che le scelte del Pivot che ci vanno "male"
(ovvero che portano a complessitá O(n2 )) siano "poche"
Tali scelte corrispondono infatti a Pivot di rango "molto
grande" o "molto piccolo"
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 17/37
Che si fá allora?
visto che non sappiamo come metterci nel caso "buono",
cerchiamo almeno di evitare le situazioni "cattive, ovvero
quelle che portavano ad una complessitá Θ(n2 )
E quali erano?
Ad esempio, quelle corrispondenti alla sfortunata
situazione in cui si sceglieva come Pivot sempre
l’elemento di valore massimo (o minimo) del (sotto)array
da ordinare, che portavano ad equazioni di ricorrenza per
il tempo di esecuzione di Quicksort del tipo
T (n) = T (n − 1) + Θ(n) , con soluzione T (n) = Θ(n2 )
Come si puó fare ad evitare queste situazioni in maniera
efficiente?
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 18/37
Procediamo a caso!
Visto che le situazioni "favorevoli" sembrano essere
"molte" e quelle "sfavorevoli" sembrano essere poche, se
scegliessimo a caso il Pivot, allora ragionevolmente con
probabilitá "grande" andremmo in una situazione
favorevole, e con probabilitá "bassa" andremmo a
ricadere in una situazione "sfavorevole"
Ovvero, in "media" dovremmo capitare in una situazione
favorevole
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 19/37
Procediamo quindi a caso...
Quicksort(A)
1. if |A| ≤ 1
2.
then return(A)
else
3.
Scegli a caso (=equiprobabilmente) un elemento a
da A e DIVIDI l’array A in
A1 , A2 ed A3 , dove A1 = {x ∈ A : x < a},
A2 = {x ∈ A : x = a}, e A3 = {x ∈ A : x > a},
4.
return(Quicksort(A1 ), A2 , Quicksort(A3 ))
questo algoritmo impiegherá un certo tempo
T (i − 1) + T (n − i) + Θ(n) (dove i =rango di a) con
probabilitá 1/n(= alla probabilitá di scegliere un Pivot a di
rango i). Queste probabilitá sono infatti tutte uguali, per la 3.
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 20/37
Ci troviamo quindi di fronte ad una quantitá (il tempo di
esecuzione di Quicksort) che assume differenti valori con
certe probabilitá. Non ha piú quindi senso parlare di tempo di
esecuzione nel caso peggiore, ma occorrerá valutare il tempo
di esecuzione nel caso medio.
Ricordiamo che se abbiamo una "quantitá" T che puó
assumere differenti valori t1 , t2 , . . . , tn , con rispettive
probabilitá P r{T = ti } = pi , per i = 1, . . . , n, allora il Valore
Medio di T é
n
X
ti × pi .
E[T ] =
i=1
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 21/37
ritornando a Quicksort...
Occorre quindi valutare la seguente quantitá per Quicksort
X
T (n) =
(tempo di esecuzione)×P r{di avere quel tempo di esec.}
tempo di esec.
che rappresenterá il Tempo Medio di esecuzione di Quicksort
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 22/37
Valutiamolo, quindi
Sia T (n) = Tempo Medio di esecuzione di Quicksort, e ricordiamo
che Quicksort impiega tempo T (i − 1) + T (n − i) + Θ(n) con
probabilitá 1/n
X
T (n) =
tempo di esecuzione × P r{di avere quel tempo di esec.}
tempo di esec.
= (T (0) + T (n − 1) + Θ(n)) × P r{di aver scelto un Pivot di rango 1}
+(T (1) + T (n − 2) + Θ(n)) × P r{di aver scelto un Pivot di rango 2}
+(T (2) + T (n − 3) + Θ(n)) × P r{di aver scelto un Pivot di rango 3}
...
+(T (n − 1) + T (0) + Θ(n)) × P r{di aver scelto un Pivot di rango n}
n
1X
=
(T (i − 1) + T (n − i)) + Θ(n)
n
i=1
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 23/37
Valutazione di T (n) =
1
n
Innanzitutto
n
X
Pn
i=1 (T (i
− 1) + T (n − i)) + Θ(n)
(T (i − 1) + T (n − i))
i=1
=
n
X
T (i − 1) +
=
T (i) +
n−1
X
n−1
X
T (i)
i=0
i=0
=2
T (n − i)
i=1
i=1
n−1
X
n
X
T (i) = 2
i=0
2
⇒ T (n) =
n
n−1
X
T (i)
(T (0) = 0)
i=1
n−1
X
T (i) + Θ(n)
i=1
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 24/37
Risoluzione di T (n) =
2
n
Pn−1
i=1
T (i) + Θ(n)
Vorremmo provare che T (n) = O(n log n). Lo faremo per
induzione. Assumeremo cioé che per tutti gli i < n sia
possibile scegliere costanti a e b tali che T (i) ≤ ai log i + b, e
poi proveremo che lo stesso vale anche per i = n.
n−1
n−1
X
X
2
2
T (i) + Θ(n) ≤
(ai log i + b) + Θ(n)
T (n) =
n i=1
n i=1
=
n−1
X
2a
n
i=1
n−1
X
2
i log i +
b + Θ(n)
n i=1
n−1
2a X
2b(n − 1)
=
i log i +
+ Θ(n)
n i=1
n
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 25/37
Supponiamo che
Pn−1
i=1
i log i ≤ 21 n2 log n − 81 n2
n−1
2a X
2b(n − 1)
T (n) =
i log i +
+ Θ(n)
n i=1
n
2a 1 2
1 2
2b(n − 1)
≤
n log n − n +
+ Θ(n)
n 2
8
n
a
a
≤ an log n − n + 2b + Θ(n) = an log n + b + Θ(n) − n + b
4
4
a
≤ an log n + b + (cn − n + b) (per qualche c opportuna)
4
≤ an log n + b
(purché si siano scelti a ed n tali che a > (4c + 1) ed n > b)
⇒ T (n) = O(n log n)
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 26/37
Pn−1
Proviamo ora che
n−1
X
i=1
⌈n/2⌉−1
i log i =
X
i log i +
i=1
i=1
⌈n/2⌉−1
≤
X
i=1
n−1
X
i log i
i=⌈n/2⌉
n
i log +
2
= (log n − 1)
i log i ≤ 21 n2 log n − 81 n2
n−1
X
i log n
i=⌈n/2⌉
⌈n/2⌉−1
X
i=1
i + log n
n−1
X
i=⌈n/2⌉
i= log n
n−1
X
i=1
⌈n/2⌉−1
i−
X
i=1
m
1
1 l n m l n
= n(n − 1) log n −
−1
2
2 2
2
1
1 n n
1 2
1
2
− 1 ≤ n log n − n
≤ n(n − 1) log n −
2
22 2
2
8
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 27/37
i
Ricordiamo:
abbiamo piú volte usato la formula
t
X
k=1
t(t + 1)
k=
2
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 28/37
Pausa di riflessione
(Riflettiamo...) Cosa abbiamo fatto?
Abbiamo preso un algoritmo (Quicksort) che ha un tempo
di esecuzione O(n2 ) nel caso peggiore, e introducendo
scelte casuali al suo interno, lo abbiamo trasformato in un
algoritmo con tempo di esecuzione medio O(n log n)
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 29/37
Pausa di riflessione
(Riflettiamo...) Come lo abbiamo fatto?
Analizzando attentamente le situazioni che conducevano
al caso peggiore O(n2 ), abbiamo appreso che esse erano
causate dalla scelta di un Pivot di rango i o "troppo
piccolo" o "troppo grande" (ricordate la equazione di
ricorrenza T (n) = (T (i − 1) + T (n − i)) + Θ(n))
Tali situazioni sfavorevoli erano "poche", pertanto
scegliendo il Pivot a caso, é "piccola" la probabilitá di
ricadervi
ergo é "grande" la probabilitá di ricadere in una
situazione favorevole, ovvero in una scelta di Pivot che
implica una complessitá per Quicksort di tipo O(n log n)
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 30/37
e quindi...
(Concludiamo ...) visto che la probabilitá di andar "male"
é piccola e quella di andar "bene" é grande, il tempo di
esecuzione medio di Quicksort é piú vicino al caso
"buono" O(n log n) che al caso "cattivo" O(n2 )
L’idea appena illustrata ha ovviamente validitá generale, e
puó essere in linea di principio applicata a molte altre
situazioni ...
un altro esempio in cui essa puó essere fruttuosamente
applicata lo vedremo nella prossima lezione
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 31/37
Ritorniamo per un momento a Quicksort
Quicksort(A)
1. if |A| ≤ 1
2.
then return(A)
else
3.
Scegli un elemento a da A e DIVIDI l’array A in
A1 , A2 ed A3 , dove A1 = {x ∈ A : x < a},
A2 = {x ∈ A : x = a}, e A3 = {x ∈ A : x > a},
4.
return(Quicksort(A1 ), A2 , Quicksort(A3 ))
Una implementazione "ingenua" della istruzione 3.
richiederebbe l’uso di un array ausiliare, oltre A, in cui
posizionare gli elementi via via confrontati con il Pivot a.
In pratica, di questo array ausiliario se ne puó fare a meno
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 32/37
"Vero" Quicksort
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Quicksort(ℓ, r) % Ordina A[ℓ . . . r]
i = ℓ, j = r
a = qualche elemento di A[ℓ . . . r]
repeat
A[i] < a do i = i + 1
while A[j] > a do j = j − 1
if i ≤ j then
scambia tra di loro A[i] e A[j]
i = i + 1, j = j − 1
until i > j
if ℓ < j then Quicksort(ℓ, j)
if i < r then Quicksort(i, r)
while
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 33/37
Come procede l’algoritmo?
A=
.... < a < a < a
↑
i
> a > a > a ....
↑
j
.... e cosí via procedendo.
Invariante dell’algoritmo: dopo ogni scambio, e relativo
incremento di i e decremento di j, vale che tutti gli elementi a
sinistra dell’array fino all’indice i sono ≤ a e tutti gli elementi a
destra dell’array a partire dall’indice j sono ≥ a
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 34/37
Esempio: Quicksort(5 3 1 9 8 2 4 7)
1
2
3
4
5
6
7
8
5
3
1
9
8
2
4
7
a = 5, ℓ = 1, r = 8, i = ℓ, j = r
5
3
1
9
8
2
4
7
(A[i] = a usciamo dal while 5.)
5
3
1
9
8
2
4
7
(A[j] > a poniamo j = j − 1 = 7)
5
3
1
9
8
2
4
7
(A[j] < a usciamo dal while 6.)
4
3
1
9
8
2
5
7
(scambia A[i] con A[j], i = 2, j = 6)
4
3
1
9
8
2
5
7
(A[i] < a poniamo i = i + 1 = 3)
4
3
1
9
8
2
5
7
(A[i] < a poniamo i = i + 1 = 4)
4
3
1
9
8
2
5
7
(A[i] > a usciamo dal while 5.)
4
3
1
9
8
2
5
7
(A[j] < a usciamo dal while 6.)
4
3
1
2
8
9
5
7
(scambia A[i] con A[j], i = 5, j = 5)
4
3
1
2
8
9
5
7
(A[i] > a usciamo dal while 5.)
4 3 1 2 8 9 5 7
(A[j] > a poniamo j = j − 1 = 4)
i = 5 > j = 4 ⇒ QuickS.(ℓ = 1, j = 4) e QuickS.(i = 5, r = 8)
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 35/37
Sulla scelta del Pivot
Abbiamo detto che per ottenere un tempo di esecuzione
medio O(n log n) per Quicksort occorre scegliere il Pivot a
caso tra tutti gli elementi del (sotto)array A[ℓ . . . r]
correntemente da ordinare.
Ció puó essere fatto usando un generatore di numeri
casuali, che ci restituisca ad ogni sua chiamata un
numero x ∈ {ℓ, ℓ + 1, . . . , r}, con probabilitá 1/(r − ℓ + 1).
Il Pivot sará quindi A[x]
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 36/37
Sulla scelta del Pivot
In pratica, il Pivot viene scelto speso come l’elemento
"mediano" di 5 elementi scelti a caso in A[ℓ . . . r]
Per la sua semplicitá di implementazione, Quicksort é
l’algoritmo di ordinamento piú veloce (e quindi piú usato
in pratica), qualora si debbano ordinare numeri.
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 37/37