Esercizio - quickselect, confronti attesi per il minimo, la mediana e il massimo
Testo. Quickselect con pivot casuale cerca il -esimo elemento più piccolo di chiavi distinte.
- Eseguire a mano l'algoritmo su con , con pivot nell'ordine , contando i confronti.
- Calcolare con la ricorrenza esatta il numero atteso di confronti per , e .
- Calcolare con la formula chiusa i casi , e confrontarli con il costo di quicksort.
- Per e la mediana () confrontare con il limite e con .
Soluzione
1. Esecuzione. Ogni passo costa (taglia ) confronti.
- Pivot su : confronti; , . Poiché si prosegue su .
- Pivot su : confronti; , . Poiché , si cerca in l'elemento di rango .
- Pivot su : confronto; , e si prosegue su : un solo elemento, la risposta è (che è il terzo più piccolo: ).
Totale confronti.
2. Ricorrenza esatta. Il pivot ha rango uniforme; costa ; se ci si ferma, se si prosegue nei elementi minori con lo stesso , se nei maggiori con : Valori piccoli: ( ferma, ricade su ). Per , : con e , quindi . Per il calcolo analogo dà : la mediana costa più del minimo, perché il pivot ha più probabilità di lasciare un sottoproblema grande.
3. Formula chiusa. Con :
- : (cioè );
- : stesso valore per simmetria, ;
- : .
Quicksort su chiavi costa : trovare la mediana costa di un ordinamento a , ma per grande il rapporto scende (lineare contro ).
4. , . La formula dà , cioè ; il limite è rispettato e è una buona approssimazione (differenza , dovuta ai termini di ordine inferiore).
import random
def qselect(a, k):
c = 0
while True:
if len(a) == 1: return c
p = random.choice(a); c += len(a) - 1
lo = [x for x in a if x < p]; hi = [x for x in a if x > p]
if k <= len(lo): a = lo
elif k == len(lo) + 1: return c
else: k -= len(lo) + 1; a = hi
print(sum(qselect(list(range(1, 1002)), 501) for _ in range(5000)) / 5000) # circa 3340Risultato. Esecuzione a mano: confronti. , ; : () e (); , mediana: .
Verifica Python: ricorrenza esatta con Fraction e formula chiusa coincidono su tutti i casi (anche ); simulazioni: , : ; , : su prove.
Versione ripasso
- Esecuzione su , : pivot ( confronti, si scende in ), pivot (, in ), pivot (): risposta , totale (Analisi probabilistica di quicksort e quickselectCon pivot casuale due elementi di rango $i<j$ vengono confrontati con probabilità $2/(j-i+1)$; sommando sulle coppie il numero atteso di confronti di quicksort è esattamente $2(n+1)H_n-4n\approx2n\ln n-2{,}85,n$ (stessa formula dalla ricorrenza $C_n=n-1+\frac2n\sum_{k<n}C_k$). Quickselect trova il $k$-esimo elemento con attesa lineare, al più $4n$ confronti (mediana $\approx3{,}39,n$). Pivot fisso su input casuale equivale a pivot casuale su input qualunque.Analisi probabilistica di quicksort e quickselect →).
- Ricorrenza: ; , , , .
- Formula: ; : , : ; : (quicksort: ).
- , mediana: , vicino a .
- Verifica: ricorrenza e formula coincidono; simulazione e .
- Errore tipico: dimenticare di aggiornare quando si va a destra ().