Menu
Coddy logo textTech

Merge sort

Ultimo aggiornamento

Il merge sort è un algoritmo divide et impera. Divide ricorsivamente l'array a metà finché ogni pezzo non ha un solo elemento (che è ordinato per definizione), poi fonde di nuovo i pezzi in ordine. Il passo di fusione scorre due sottoarray ordinati con due puntatori, copiando ogni volta il più piccolo dei due elementi in testa. Premi play qui sopra per vedere l'array ricostruito fusione dopo fusione.

Dato che divide sempre a metà, il merge sort richiede tempo O(n log n) in ogni caso: il suo caso peggiore è buono quanto il migliore. Il compromesso è O(n) di spazio extra per il buffer temporaneo della fusione.

Complessità temporale e spaziale

CasoComplessitàNote
Caso miglioreO(n log n)Divide sempre a metà l'input
Caso medioO(n log n)Ordine casuale
Caso peggioreO(n log n)Garantito: nessun input sfavorevole
SpazioO(n)Buffer temporaneo per la fusione
StabileSìI pareggi si risolvono prendendo prima da sinistra durante la fusione

Passo dopo passo

PassoCosa succede
1Se l'intervallo ha 0 o 1 elementi, è già ordinato.
2Dividi l'intervallo in due metà.
3Applica ricorsivamente il merge sort alla metà sinistra.
4Applica ricorsivamente il merge sort alla metà destra.
5Fondi le due metà ordinate con due puntatori.

Esempio svolto

Ordinamento di [5, 2, 4, 1]:

PassataArrayAzione
Divisione[5, 2] | [4, 1]Dividi l'array in due metà
Divisione[5] [2] | [4] [1]Dividi ancora finché ogni pezzo è un solo elemento
Fusione[2, 5] | [1, 4]Fondi [5],[2] in [2, 5] e [4],[1] in [1, 4]
Fusione[1, 2, 4, 5]Fondi [2, 5] e [1, 4]: prendi 1, poi 2, poi 4, poi 5
Fine[1, 2, 4, 5]L'array è completamente ordinato

Quando usare il merge sort

Usalo quandoEvitalo quando
Ti serve un caso peggiore O(n log n) garantitoLa memoria è poca e O(n) di spazio extra non è accettabile
Conta la stabilità (le chiavi uguali mantengono il loro ordine)Ordini array piccoli, dove l'insertion sort è più veloce
Stai ordinando una lista concatenataL'ordinamento in loco è un requisito irrinunciabile
I dati sono troppo grandi per la RAM (ordinamento esterno)La località della cache domina e vincono le passate in loco del quicksort

Codice Merge Sort

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

Codice Merge Sort in Python

Python
1def merge_sort(a):2    if len(a) <= 1:3        return a4    mid = len(a) // 25    left = merge_sort(a[:mid])6    right = merge_sort(a[mid:])7    return merge(left, right)8
9
10def merge(left, right):11    out = []12    i = j = 013    while i < len(left) and j < len(right):14        if left[i] <= right[j]:15            out.append(left[i])16            i += 117        else:18            out.append(right[j])19            j += 120    out.extend(left[i:])21    out.extend(right[j:])22    return out23
24
25nums = [38, 27, 43, 3, 9, 82, 10]26print("Before:", nums)27print("After: ", merge_sort(nums))
Esegui questo codice nel playground Python

Domande frequenti sul merge sort

Qual è la complessità temporale del merge sort?
Il merge sort è O(n log n) nel caso migliore, medio e peggiore, perché divide sempre l'array a metà. Usa O(n) di spazio extra per il buffer di fusione.
Il merge sort è stabile?
Sì, se il passo di fusione risolve i pareggi prendendo prima dalla metà sinistra. Così gli elementi uguali mantengono il loro ordine relativo originale, ed è per questo che il merge sort è una scelta comune per l'ordinamento stabile.
Perché usare il merge sort invece del quicksort?
Il merge sort garantisce O(n log n) anche con input ostili ed è stabile, mentre il quicksort può degradare a O(n²). Il merge sort è anche preferito per le liste concatenate e per l'ordinamento esterno. Lo svantaggio è la sua memoria extra O(n).
Qual è la differenza tra merge sort e quicksort?
Sono entrambi ordinamenti divide et impera, ma il quicksort partiziona attorno a un pivot e ordina in loco con O(log n) di spazio sullo stack, mentre il merge sort divide a metà senza guardare i valori e fonde usando un buffer O(n). In pratica il quicksort di solito è più veloce grazie alla località della cache, ma il merge sort ha un caso peggiore O(n log n) garantito ed è stabile.
Quando conviene usare il merge sort in pratica?
Scegli il merge sort quando ti serve un ordinamento stabile con un limite O(n log n) garantito, quando ordini liste concatenate (dove non ha bisogno di accesso casuale) o quando fai l'ordinamento esterno di dati troppo grandi per stare in memoria. Evitalo quando la memoria scarseggia, perché gli serve O(n) di spazio extra.
Il merge sort ordina in loco?
No. Il merge sort standard alloca un buffer temporaneo O(n) per fondere le due metà, quindi non è in loco. Esistono varianti di fusione in loco, ma sono complesse e più lente o perdono la stabilità, quindi la versione con buffer è la scelta comune.
Illustrazione dei linguaggi di programmazione di Coddy

Padroneggia gli algoritmi con Coddy

INIZIA