2.5 KiB
Merge sort
Il merge sort è una soluzione ricorsiva all'ordinamento per confronto.
Funzionamento
Per questo algoritmo, utilizziamo la tecnica del divide et impera.
- Divide: Divido A in due parti.
- Impera: Metto separatamente in ordine le parti.
- Unisci: Unisco le due parti.
Consideriamo come caso base della ricorsione una parte composta da un numero, che ovviamente è già ordinata con sè stessa.
Merge
Per unire le due parti usiamo una funzione detta merge()
.
Costruiamo una nuova sequenza uguale alla sequenza 1, ma aggiungiamo alla fine un valore sentinella sempre maggiore di tutti gli elementi contenuti.
| 1 | 3 | 7 | 8 | ∞ |
Facciamo la stessa cosa per la sequenza due.
| 2 | 4 | 5 | 6 | ∞ |
Prendo i primi numeri delle due sequenze e metto il più piccolo nella sequenza iniziale.
| 1 | 2 | 3 | | | | | | | | | 7 | 8 | ∞ | | | 4 | 5 | 6 | ∞ |
Continuo finchè non ho messo tutti i numeri; grazie alla sentinella non usciremo mai dalla sequenza, in quanto essa è sempre maggiore di tutti gli altri numeri.
| 1 | 2 | 3 | 4 | 5 | 6 | | | | | | 7 | 8 | ∞ | | | | | | ∞ |
Quando rimangono solo le sentinelle significa che abbiamo aggiunto tutti gli elementi, e quindi abbiamo finito.
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | | | | | | ∞ | | | | | | ∞ |
Costo computazionale
Categoria | Upper bound | Lower bound | Tight bound |
---|---|---|---|
Tempo | O(n log n) |
Ω(n log n) |
θ(n log n) |
Il merge sort è un algoritmo ricorsivo con un caso base in tempo costante e che richiama sè stesso 2 volte.
T(n) =\\
\\
Θ(1) \qquad n=1\\
2 T(\frac{n}{2}) + Θ(n) \qquad n \neq 1
Applicando il caso particolare del Master Theorem, otteniamo:
T(n) =\\
\\
Θ(1) \qquad n=1\\
Θ(n log n) \qquad n \neq 1
Pseudocodice
def merge_sorted(part):
# Caso base
if len(part) == 1:
return part
# Divide
middle = len(part) // 2
part_a = part[:middle]
part_b = part[middle:]
# Impera
sort_a = merge_sorted(part_a)
sort_b = merge_sorted(part_b)
# Combina
return merge(sort_a, sort_b)
Visualizzazione
visualgo.net (Nota: visualizza solo la fase Unisci del sort)