Input: Array A[1...n] di n numeri distinti ed un intero i, . Output: l

Di cosa parlamo oggi: Problema della Selezione
Input: Array A[1 . . . n] di n numeri distinti ed un intero i,
con i ∈ {1, . . . , n}.
Output: l’elemento di rango i in A
Ricordiamo: rango di un elemento x = numero di elementi
che sono ≤ di x nel vettore A
Esempi:
Elemento di valore minimo in A = elemento di rango 1
Elemento di valore massimo in A = elemento di rango n
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 1/34
Problema della Selezione: soluzione "semplice"
Input: Array A[1 . . . n] di n numeri distinti ed un intero i, con
i ∈ {1, . . . , n}.
Output: l’elemento di rango i in A
A LGORITMO -S EMPLICE(A, i)
1. Ordina il vettore A
2. Output A[i]
Complessitá O(n log n)
Si puó far meglio?
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 2/34
Vediamo qualche caso particolare...
Ricerca del Minimo (elemento di rango 1) di A[1 . . . n]
min = A[1]
for i = 2 to n do
if A[i] < min then min = A[i]
return min
Complessitá dell’algoritmo = O(n)
Stessa storia per il calcolo del massimo in A (elemento di
rango n)
Per fortuna vale un risultato simile per la ricerca
dell’elemento di di rango i in A, qualunque sia i.
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 3/34
Un pó di intuizione...
Prima ancora di chiederci come trovare l’elemento di rango k
nell’array A[1...n], chiediamoci: come stabilire che un dato
elemento a di A é (o non é) l’elemento di rango k di A?
Un modo semplice potrebbe essere il seguente: dividiamo l’array A
in
A1 =tutti x < a
a
A2 = tutti x > a
come facevamo in Q UICKSORT.
Se |A1 | = k − 1, l’elemento a é proprio l’elemento di rango k che
cercavamo, se |A1 | =
6 k − 1 l’elemento a non é l’elemento di rango
k che cercavamo (tale test riusciamo a realizzarlo in tempo Θ(n)).
La cosa interessante è che il test ci dice molto di più del solo fatto
che l’elemento a é o non é l’elemento di rango k di A.
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 4/34
Possibile algoritmo basato su Divide et Impera
Partiamo dall’array A
A=
e vogliamo trovare l’elemento di rango k in A
⇓
scegliamo un elemento a in A e dividiamo A in:
A1 =tutti x < a
a
A2 = tutti x > a
dove stá l’elemento di rango k ?
Se |A1 | = k − 1, allora l’elemento di rango k é proprio a.
Se |A1 | ≥ k , allora l’elemento di rango k stá in A1
Se |A1 | < k − 1, allora l’elemento di rango k stá in A2 , e
sará l’elemento di rango k − |A1 | − 1 di A2
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 5/34
Algoritmo generale basato su Divide et Impera
S ELECT(A, k)
% trova l’elemento di rango k in A
if |A| = 1 then return(A[1])
else
scegli un elemento a da A e DIVIDI A in A1 e A2 ,
con A1 = {x ∈ A : x < a}, e A2 = {x ∈ A : x > a},
calcola j = |A1 |
if k = j + 1 then return(a)
else if k ≤ j then return(S ELECT(A1 , k))
else return(S ELECT(A2 , k − j − 1))
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 6/34
Esempio A = [15 13 11 19 18 12 14 17], k = 7
15
13
13
11
11
12
19
14
18
15
12
17
14
18
17
19
a = 15
Quindi A1 = [13 11 12 14], |A1 | = j = 4 e poichè
k = 7 > j = 4, ricorriamo nella parte destra dell’array,
ovvero in A2 = [17 18 19] e lì occore cercare l’elemento di
rango k − j − 1 = 7 − 4 − 1 = 2 che è 18, che è anche
l’elemento di rango 7 dell’intero array A
• Osservazione: È ovvio che la partizione di A in (A1 , a, A2 )
si può effettuare in tempo Θ(n), e che la si può effettuare
senza usare un array ausiliare, usando le stesse idee
illustrate in Quicksort.
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 7/34
Analisi della complessità di S ELECT
S ELECT(A, k)
% trova l’elemento di rango k in A
if |A| = 1 then return(A[1])
else
scegli un elemento a da A e DIVIDI A in A1 = {x ∈ A : x < a},
e A2 = {x ∈ A : x > a}, calcola j = |A1 |
if k = j + 1 then return(a)
else if k ≤ j then return(S ELECT(A1 , k))
else return(S ELECT(A2 , k − j − 1))
Sia T (n, k) = complessità di S ELECT(A, k). Detto j + 1 = rango
dell’elemento a scelto, avremo
•T (n, k) = Θ(n) + Θ(1) se k = j + 1
•T (n, k) = Θ(n) + T (j, k) se k ≤ j (ricorriamo infatti in A1 )
•T (n, k) = Θ(n) + T (n − j − 1, k − j − 1) se k > j (ricorriamo infatti
in A2 )
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 8/34
Complessità di S ELECT nel caso peggiore
Ricordando l’analisi effettuata durante lo studio di
Quicksort, abbiamo che la procedura che partiziona A in
A1 , a, e A2 , puó in linea di principio restituire una partizione
di A con |A1 | = n − 1, e |A2 | = 0.
Ció accadrebbe, ad esempio, se avessimo scelto a come
elemento massimo di A. Potremmo avere quindi la
seguente equazione di ricorrenza nel caso di k = 1
T (n, 1) = T (n − 1, 1) + Θ(n)
che ha ovvia soluzione T (n, 1) = Θ(n2 ) ,
Quindi l’algoritmo S ELECT puó anche essere peggiore
dell’algoritmo semplice prima visto!
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 9/34
Peró...
Se avessimo scelto un elemento a per partizionare l’array A
in A1 = {x ∈ A : x < a}, a, e A2 = {x ∈ A : x > a}, per cui
valesse |A1 | = n/c e |A2 | = n(1 − 1/c) − 1, per un qualche
c > 1, avremmo avuto la seguente equazione di ricorrenza
•T (n, k) = Θ(n) + Θ(1) se k = n/c + 1
•T (n, k) = Θ(n) + T (n/c, k) se k ≤ n/c (ricorriamo in A1 )
•T (n, k) = Θ(n) + T (n(1 − 1/c) − 1, k − n(1 − 1/c) − 1)
se k > n/c (ricorriamo in A2 )
Non é difficile vedere che tali equazioni hanno soluzioni
T (n, k) = Θ(n) (dal Teorema generale visto nella Lezione 4)
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 10/34
Cosa succede quindi?
• Esistono delle situazioni "sfortunate" in cui l’algoritmo
S ELECT ha complessitá Θ(n2 )
• Esistono delle situazioni "favorevoli" in cui lo stesso
algoritmo S ELECT ha complessitá Θ(n)
Come possiamo evitare le situazioni "sfavorevoli"?
Come in Quicksort decidiamo di scegliere l’elemento a, in
accordo a cui partizionamo l’array A in A1 ed A2 ,
equiprobabilmente a caso!
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 11/34
In altri termini...
Visto che le situazioni "favorevoli" sembrano essere
"molte" e quelle "sfavorevoli" sembrano essere poche,
se scegliessimo a caso l’elemento a in accordo a cui
partizioniamo l’array A, 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. 2009/10 – p. 12/34
Procediamo quindi a caso
S ELECT(A, k)
% trova l’elemento di rango k in A
if |A| = 1 then return(A[1])
else
scegli a caso a e DIVIDI A in A1 = {x ∈ A : x < a},
e A2 = {x ∈ A : x > a}, calcola j = |A1 |
if k = j + 1 then return(a)
else if k ≤ j then return(S ELECT(A1 , k))
else return(S ELECT(A2 , k − j − 1))
Detta T (n, k) la complessità di S ELECT(A, k), e j + 1 il rango di a, questo
algoritmo impiegherá
• tempo T (n, k) = Θ(n) + Θ(1) (se abbiamo scelto a di rango j + 1 = k)
• tempo T (n, k) = Θ(n) + T (j, k) (se abbiamo scelto a di rango j ≥ k)
•T (n, k) = Θ(n) + T (n − j − 1, k − j − 1) (se abbiamo scelto a di rango
j < k)
Ciascuno di questi eventi occorrerá con probabilitá 1/n, pari alla
probabilitá di scegliere un certo a di rango j + 1 ∈ {1, . . . , n}
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 13/34
e quindi...
Ci troviamo di nuovo di fronte ad una una quantitá (il tempo di
esecuzione di S ELECT) che assume differenti valori con certe
probabilitá.
Di nuovo non ha senso parlare di tempo di esecuzione nel
caso peggiore, ma occorrerá valutare il tempo di esecuzione
nel caso medio.
Ricordiamo ancora una volta 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 é
E[T ] =
n
X
ti × pi .
i=1
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 14/34
ritornando a S ELECT...
Occorre quindi valutare la seguente quantitá per S ELECT
X
T (n, k) =
(tempo di esecuzione)×P r{di avere quel tempo di esec.}
tempo di esec.
che rappresenterá il Tempo Medio di esecuzione di S ELECT
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 15/34
Valutiamola quindi
Per quanto detto prima, il tempo di esecuzione T (n, k) di
S ELECT può assumere differenti valori pari a:
•Θ(n) + Θ(1) (se abbiamo scelto a di rango j + 1 = k)
• T (n, k) = Θ(n) + T (j, k) (se abbiamo scelto a di rango j ≥ k)
•T (n, k) = Θ(n) + T (n − j − 1, k − j − 1) (se abbiamo scelto a
di rango j < k)
Pertanto, il valor medio di T (n, k) sarà dato dalla somma di
tali quantitá moltiplicate per la probabilitá di avere tali
quantitá.
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 16/34
Equazione di ricorrenza per T (n, k)
Sia T (n, k) il tempo medio di esecuzione di S ELECT(n, k)
Abbiamo la seguente ricorsione per T (n, k)
k−2
1 X
T (n, k) =
T (n − j − 1, k − j − 1)
n j=0
+
n−1
X
(ricorsione , k > j + 1)
T (j, k)
(ricorsione , k ≤ j)
j=k
+Θ(1)
+Θ(n)
(terminazione , k = j + 1)
(tempo per partizionare l’array)
Proveremo che ∃c > 0 tale che T (n, k) < cn
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 17/34
Prova che T (n, k) < cn
Per induzione su n. Sappiamo che
T (n, k) =
k−2
X
1
n
T (n − j − 1, k − j − 1) +
j=0
n−1
X
j=k
T (j, k) + Θ(1) + Θ(n)
ovvero, che ∃b > 0 tale che
T (n, k) ≤
k−2
X
1
n
T (n − j − 1, k − j − 1) +
j=0
n−1
X
T (j, k) + bn
j=k
Assumiamo induttivamente che T (s, k) < cs, ∀s < n, e proviamolo
per s = n Abbiamo quindi, dall’ipotesi induttiva
k−2
n−1
j=0
j=k
X 1 X
c(n − j − 1) +
T (n, k) ≤
cj + bn
n
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 18/34
continuiamo
T (n, k) ≤
k−2
X
1
n
c(n − j − 1) +
j=0
n−1
X
j=k
cj + bn
k−2
n−1
k−1
j=0
j=1
j=1
X X
X
1
cj + bn
cj −
(j + 1) +
cn(k − 1) − c
=
n
1
n(n − 1)
k(k − 1) k(k − 1)
=
+c
−c
cnk − cn − c
+ bn
n
2
2
2
2
n
n
1
cnk − cn − ck 2 + ck + c − c
+ bn
=
n
2
2
1 n2
3
=
c − c n + (cn + c)k − ck 2 + bn
n 2
2
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 19/34
Studiamo f (k) =
n2
c2
− c 32 n + (cn + c)k − ck 2
f ′ (k) = cn + c − 2ck,
f ′′ (k) = −2c < 0
con f ′ (k) = cn + c − 2ck = 0 per k =
Quindi
cn+c
2c
=
n+1
2
n+1
2
é un punto di massimo per f (k), ovvero
3 2
c
n+1
= cn − cn +
∀k f (k) ≤ f
2
4
4
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 20/34
Ritorniamo all’equazione di ricorrenza per T (n, k)
Avevamo
1 n2
3
c − c n + (cn + c)k − ck 2 + bn
T (n, k) ≤
n 2
2
1
= f (k) + bn
n 1
n+1
≤ f
+ bn
n
2
c
1 3 2
+ bn
cn − cn +
=
n 4
4
3
c
= cn − c +
+ bn
4
c 4n
c = cn −
n+c−
+ bn
4
4n
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 21/34
Passo CRUCIALE e FINALE (!)
Abbiamo visto che
c n+c−
T (n, k) ≤ cn −
+ bn
4
4n
c
Osserviamo ora che per costante c tale che c > 4b, vale che
c
c − n+c−
+ bn < 0
4
4n
ovvero esiste una costante c > 0 tale che
c
c T (n, k) ≤ cn −
n+c−
+ bn < cn
4
4n
che é quanto volevamo dimostrare...
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 22/34
Pausa di riflessione
Cosa abbiamo fatto?
Abbiamo preso un algoritmo (Select) 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)
Ciò è potuto accadere in quanto la scelta casuale
dell’elemento a (mediante il quale effettuiamo la
partizione dell’array A) fà si che la probabilità di avere
"situazioni" che portano a complessità Θ(n2 ) diventa
"piccola", ed è "grande" invece la probabilità di ricadere in
situazioni che portano a complessità O(n)
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 23/34
Insisto: voglio un algoritmo non randomizzato!
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 24/34
Ricordiamo l’algoritmo generale basato su Divide et Impera
S ELECT(A, k)
% trova l’elemento di rango k in A
if |A| = 1 then return(A[1])
else
scegli un elemento a da A e DIVIDI A in A1 e A2 ,
con A1 = {x ∈ A : x < a}, e A2 = {x ∈ A : x > a},
calcola j = |A1 |
if k = j + 1 then return(a)
else if k ≤ j then return(S ELECT(A1 , k))
else return(S ELECT(A2 , k − j − 1))
e la sua complessitá T (n, k)
Detto j + 1 = rango dell’elemento a scelto, avremo
•T (n, k) = Θ(n) + Θ(1) se k = j + 1
•T (n, k) = Θ(n) + T (j, k) se k ≤ j (ricorriamo infatti in A1 )
•T (n, k) = Θ(n) + T (n − j − 1, k − j − 1) se k > j (ricorriamo infatti
in A2 )
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 25/34
Di conseguenza...
Abbiamo visto che se si sceglie un elemento a di rango
“piccolo", si possono avere equazioni di ricorrenze del tipo
T (n, 1) = T (n − 1, 1) + Θ(n)
con soluzione T (n, 1) = Θ(n2 ) ,
Abbiamo altresí visto che se si sceglie un elemento a di rango
n/c, per qualche costante c > 1, si hanno equazioni di
ricorrenze del tipo
T (n, k) = Θ(n) + T (n/c, k)
con soluzione T (n, k) = Θ(n) ,
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 26/34
Quindi
per avere un algoritmo per il problema della selezione dell’elemento
di rango k che abbia complessità O(n) nel caso peggiore
occorrerebbe scegliere l’elemento a in accordo al quale
partizionamo l’array A in modo tale che a non sia nè "troppo
grande", nè "troppo piccolo"
(infatti, se lo sceglievamo sempre "troppo grande", ad esempio pari
al massimo di A, ottenevamo un algoritmo di complessità Θ(n2 ) nel
caso peggiore)
L’ideale sarebbe scegliere per a un elemento di rango n/2, detto in
gergo mediana di A , che è peró altrettanto difficile quanto il
problema di partenza che vogliamo risolvere!
Come fare ad uscire da questa specie di "circolo vizioso"?
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 27/34
Idea (e complessitá) dell’algoritmo Divide et Impera
1. Dividi gli n elementi in input in ⌊n/5⌋ gruppi di 5 elementi ciascuno, ed
al piú un gruppo addizionale di n mod 5 elementi
Tempo= Θ(n)
2. Trova la mediana di ciascuno degli ⌈n/5⌉ gruppi (ad es., ordinando
ciascun gruppo con InsertionSort e prendendo l’elemento di mezzo)
Tempo= Θ(n)
3. Usa ricorsivamente l’algoritmo per trovare la mediana x delle ⌈n/5⌉
mediane trovate al passo 2.
Tempo= T (⌈n/5⌉)
4. Partiziona l’array input A in (A1 , x, A2 ). Sia |A1 | = j, |A2 | = n − j − 1.
Tempo= Θ(n)
5. Ricorri per cercare l’elemento di rango k in A1 se k ≤ j, ritorna x se
k = j + 1, ricorri in A2 per cercarvi l’elemento di rango k − (j + 1) se
k >j+1
Tempo≤ T (max(|A1 |, |A2 |)
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 28/34
abbiamo quindi
Detta T (n) la complessitá dell’algoritmo nel caso peggiore, essa si puó
scrivere come
T (n) = Θ(n)
(per la divisione di A in n/5 gruppi)
+Θ(n) (per il calcolo della mediana di ciascun gruppo di 5 elementi)
+T (⌈n/5⌉)
(per la ricorsione sulle ⌈n/5⌉ mediane prima trovate)
+Θ(n)
+T (max(|A1 |, |A2 |)
(per la partizione di A)
(per la ricorsione sul lato piú grande della part.)
= Θ(n) + Θ(n) + T (⌈n/5⌉) + Θ(n) + T (max(|A1 |, |A2 |)
= T (max(|A1 |, |A2 |)) + T (⌈n/5⌉) + Θ(n)
Ci serve sapere quant’é max(|A1 |, |A2 |)
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 29/34
Ricordiamo che
A1 = { tutti gli elementi di A che sono < di x}
A2 = { tutti gli elementi di A che sono > di x}
Cerchiamo di valutare |A1 | e |A2 |
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 30/34
Idea dell’analisi
x
I punti rappresentano gli elementi (nel nostro caso 33). Ogni gruppo di 5
elementi é rappresentato da una colonna. Le mediane di ogni gruppo
sono bianche. La mediana delle mediane é l’elemento etichettato con x.
Le frecce vanno da elementi piú grandi a piú piccoli. In ogni gruppo
(tranne l’ultimo) ci sono almeno 3 elementi > di x (sono quelli a destra di
x racchiusi nella linea rossa) In ogni gruppo a sinistra di x (racchiusi nella
linea blu) ci sono almeno 3 elementi < x.
3n
1 n
Quindi |A2 | ≥ 3 2 5 − 2 ≥ 10 − 6 ⇒ |A1 | ≤ 7n/10 + 6
3n
1 n
|A1 | ≥ 3 2 5 − 2 ≥ 10 − 6 ⇒ |A2 | ≤ 7n/10 + 6
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 31/34
Ricapitolando: T (n) = T (max(|A1 |, |A2 |)) + T (⌈n/5⌉) + Θ(n)
Abbiamo poi scoperto che
|A1 |, |A2 | ≤ 7n/10 + 6 ⇒ max(|A1 |, |A2 |) ≤ 7n/10 + 6
abbiamo quindi la ricorsione
T (n) ≤ T (7n/10 + 6) + T (⌈n/5⌉) + Θ(n)
Proveremo che essa ha soluzione T (n) ≤ cn, per qualche costante
c opportuna, per induzione su n ovvero assumeremo che per
qualche costante c, e ∀k < n vale T (k) ≤ ck , indi proveremo che
T (n) ≤ cn
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 32/34
Procediamo
T (n) ≤ T (7n/10 + 6) + T (⌈n/5⌉) + Θ(n)
≤ T (7n/10 + 6) + T (⌈n/5⌉) + an
(per definizione di Θ(n))
≤ c(7n/10 + 6) + c(⌈n/5⌉) + an
(per ipotesi induttiva)
≤ 7cn/10 + 6c + cn/5 + c + an
(in quanto ⌈x⌉ ≤ x + 1)
= 9cn/10 + 7c + an
= cn + (−cn/10 + 7c + an)
≤ cn
(per n sufficientemente grande e purché c > 10a)
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 33/34
Qualche osservazione
• Abbiamo provato che é possibile determinare l’elemento di rango
k in un array A[1 . . . n], 1 ≤ k ≤ n in tempo Θ(n)
• Potremmo ottenere da questo risultato, una versione di Quicksort
che ordina n numeri in tempo Θ(n log n) nel caso peggiore!
Basta infatti usare l’algoritmo S ELECT(n, n/2) prima di partizionare
l’array in due parti, usando l’output di S ELECT(n, n/2) come
l’elemento a mediante il quale si partiziona A. In questo caso la
partizione risulterá essere perfettamente bilanciata (n/2 elementi a
sinistra ed altrettanti a destra), portando ad una equazione di
ricorrenza sul tempo di Quicksort del tipo T (n) = 2T (n/2) + Θ(n),
che sappiamo ha soluzione T (n) = Θ(n log n)
In pratica, peró, l’algoritmo randomizzato che abbiamo visto nella
lezione scorsa risulta essere di gran lunga preferibile.
Universitá degli Studi di Salerno – Corso di Algoritmi – Prof. Ugo Vaccaro – Anno Acc. 2009/10 – p. 34/34