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