Menu
Coddy logo textTech

Heap sort

Ultimo aggiornamento

L'heap sort tratta l'array come un heap binario. Prima costruisce un max-heap, così l'elemento più grande sta alla radice (indice 0). Poi scambia ripetutamente la radice con l'ultimo elemento non ordinato, fissando il massimo al suo posto, e fa scendere la nuova radice (sift-down) per ripristinare la proprietà di heap. Premi play qui sopra per vedere la costruzione dell'heap e le estrazioni.

L'heap sort garantisce tempo O(n log n) come il merge sort, ma ordina in loco con solo O(1) di spazio extra. Non è stabile e tende a sfruttare la cache peggio del quicksort, quindi si sceglie spesso quando contano sia un limite garantito sia una memoria costante.

Complessità temporale e spaziale

CasoComplessitàNote
Caso miglioreO(n log n)Costruzione + n estrazioni
Caso medioO(n log n)Ordine casuale
Caso peggioreO(n log n)Garantito
SpazioO(1)In loco
StabileNoIl sift-down riordina gli elementi uguali

Passo dopo passo

PassoCosa succede
1Costruisci un max-heap dall'array (sift-down a partire dall'ultimo genitore).
2Scambia la radice (il massimo) con l'ultimo elemento dell'heap.
3Riduci l'heap di uno: l'ultima posizione ora è ordinata.
4Fai scendere la nuova radice per ripristinare la proprietà di max-heap.
5Ripeti finché nell'heap resta un solo elemento.

Esempio svolto

Ordinamento di [3, 1, 6, 5, 2, 4]. La barra | segna il confine tra l'heap che si riduce e la coda ordinata:

PassataArrayAzione
Costruzione heap[6, 5, 4, 1, 2, 3]Sift-down dall'ultimo genitore per costruire il max-heap; ora 6 è alla radice.
1[5, 3, 4, 1, 2 | 6]Scambia la radice 6 con l'ultima posizione, riduci l'heap e fai scendere 3.
2[4, 3, 2, 1 | 5, 6]Porta fuori la radice 5, poi fai scendere 2 così 4 sale alla radice.
3[3, 1, 2 | 4, 5, 6]Porta fuori la radice 4, poi fai scendere 1 così 3 sale alla radice.
4[2, 1 | 3, 4, 5, 6]Porta fuori la radice 3; 2 rispetta già la proprietà di heap.
5[1 | 2, 3, 4, 5, 6]Porta fuori la radice 2; resta un solo elemento, quindi l'array è ordinato.

Quando usare l'heap sort

Usalo quandoEvitalo quando
Ti serve un caso peggiore O(n log n) garantito, senza rischio di O(n²).Ti serve un ordinamento stabile che preservi l'ordine delle chiavi uguali.
La memoria è poca: ordina in loco con solo O(1) di spazio extra.Contano le prestazioni di cache e i dati stanno in memoria: il quicksort di solito è più veloce.
Stai già mantenendo un heap (ad es. una coda di priorità) sui dati.Vuoi il minor numero di confronti: merge sort e quicksort spesso ne fanno meno in pratica.
Un input non fidato potrebbe innescare il caso peggiore del quicksort e non puoi randomizzare.I dati sono quasi ordinati: l'insertion sort su di essi gira in tempo quasi lineare.

Codice Heap Sort

Un'implementazione di Heap Sort pulita ed eseguibile in Python, JavaScript, Java, C++, C. Scegli un linguaggio, copia il codice o aprilo già caricato nel Playground di Coddy.

Codice Heap Sort in Python

Python
1def heap_sort(a):2    n = len(a)3    # Build a max-heap, deepest parent first4    for i in range(n // 2 - 1, -1, -1):5        sift_down(a, i, n)6    # Repeatedly move the max to the end and shrink the heap7    for end in range(n - 1, 0, -1):8        a[0], a[end] = a[end], a[0]9        sift_down(a, 0, end)10    return a11
12
13def sift_down(a, i, size):14    while True:15        largest = i16        left, right = 2 * i + 1, 2 * i + 217        if left < size and a[left] > a[largest]:18            largest = left19        if right < size and a[right] > a[largest]:20            largest = right21        if largest == i:22            return23        a[i], a[largest] = a[largest], a[i]24        i = largest25
26
27nums = [12, 11, 13, 5, 6, 7]28print("Before:", nums)29heap_sort(nums)30print("After: ", nums)
Esegui questo codice nel playground Python

Domande frequenti sull'heap sort

Qual è la complessità temporale dell'heap sort?
L'heap sort è O(n log n) nel caso migliore, medio e peggiore. Costruire l'heap costa O(n) e ognuna delle n estrazioni costa O(log n). Usa O(1) di spazio extra.
L'heap sort è stabile?
No. L'operazione di sift-down può spostare elementi uguali uno oltre l'altro, quindi l'heap sort non preserva l'ordine relativo delle chiavi uguali.
Quando conviene usare l'heap sort?
Usa l'heap sort quando ti serve un caso peggiore O(n log n) garantito con solo O(1) di memoria extra. Evita il rischio O(n²) del quicksort senza il buffer O(n) del merge sort, a scapito della stabilità e delle prestazioni di cache.
Qual è la differenza tra heap sort e quicksort?
Entrambi ordinano in loco, ma il quicksort ha un caso peggiore O(n²) mentre l'heap sort garantisce O(n log n). In pratica il quicksort di solito è più veloce grazie a una migliore località di cache e a meno scambi, quindi l'heap sort si preferisce soprattutto quando il limite nel caso peggiore deve essere garantito.
Che rapporto c'è tra l'heap sort e una coda di priorità?
Un heap binario è l'implementazione standard di una coda di priorità, e l'heap sort consiste in sostanza nell'estrarre ripetutamente il massimo da quella coda. Se tieni già i tuoi dati in un heap, estrarre gli elementi uno a uno ti dà un ordinamento senza costi extra.
L'heap sort ha bisogno di un max-heap o di un min-heap?
Per ordinare in ordine crescente in loco usa un max-heap: a ogni passata l'elemento più grande viene scambiato in fondo, facendo crescere la coda ordinata da destra. Un min-heap produrrebbe un ordine decrescente in loco, oppure crescente se estrai gli elementi in un array separato.
Illustrazione dei linguaggi di programmazione di Coddy

Padroneggia gli algoritmi con Coddy

INIZIA