Il principio generale della ricorsione è quello di risolvere un problema ipotizzando che un problema più piccolo possa essere risolto, e tenendo conto della differenza tra il problema più piccolo e quello che viene attualmente chiesto di risolvere.
Molti algoritmi ricorsivi, ad es. fattoriale ricorsivo, assume un problema più piccolo per 1 e poi, data la risposta, risolve il delta tra quella (più piccola per una) risposta e la risposta richiesta, ad es. moltiplicando la risposta del problema più piccolo di N.
Nel caso della tua domanda, l'approccio è quello di risolvere non solo uno ma due problemi minori e combinare la risposta usando l'unione. I problemi minori sono suddivisioni del problema più grande in m
, che è la metà dell'intervallo che è stato chiesto di risolvere.
A proposito, ci sono molti modi diversi in cui unire l'ordinamento è codificato. In parte dipende dal fatto che la tua lingua supporti efficientemente fette di array (o meno).
Se lo fa, l'ordinamento di unione viene in genere chiesto di ordinare un array dato ad ogni invocazione, dove l'array da ordinare è in realtà un sottoinsieme di un array più grande, ma una volta passato come argomento, viene visto passare da 0 a alcuni .length.
Se la lingua non consente fette, come potrebbe essere il caso nella tua domanda, allora l'ordinamento di fusione viene diretto per ordinare un sotto intervallo identificato esplicitamente dell'array (passando l'inizio aggiuntivo ( l
) e fine ( r
) parametri) invece di trasformare la porzione in un altro array (slice) e passare solo quella.
In ogni caso dovrebbe essere relativamente facile vedere che m
è scelto a metà circa tra l
e r
. Quindi, la prima delle due chiamate ricorsive richiede di ordinare subrange l
a m
, e il secondo, il subrange da m+1
a r
. Una volta uniti, questo esegue il tipo richiesto dell'intero l
a r
subrange richiesto.
La chiamata iniziale avrà l
come 0
e r
come lunghezza intera, quindi alla prima chiamata viene chiesto di ordinare l'intero array e, a sua volta, chiede ai suoi assistenti ricorsivi di ordinare circa la metà dell'array. A loro volta suddividono anche la porzione dell'array a cui sono chiesti di dividere in circa la metà ... Alla fine, l'intero intervallo dell'array originale viene ordinato e unito.
Molti algoritmi ricorsivi usano più di una chiamata (auto) ricorsiva. Ad esempio, gli attraversamenti di alberi ricorsivi funzionano in modo simile: un attraversamento di ordine postale visita il nodo stesso per ultimo dopo essere chiamato ricorsivamente a sinistra ea destra. Potresti vedere la suddivisione in due problemi più piccoli più facilmente con la ricorsione di un attraversamento di alberi perché c'è molto meno lavoro da fare per identificare il problema più piccolo da risolvere prima (c'è solo destra e sinistra).
Ma l'ordinamento di fusione fa la stessa cosa: per ogni intervallo che viene chiesto di ordinare, prima (usando l'invocazione ricorsiva) ordina la metà sinistra, poi la metà destra, quindi si unisce. Deve identificare le metà usando un po 'di aritmetica, che la differenzia dall'altra traversata ad albero con motivi simili.
Una variante dell'ordinamento di unione potrebbe suddividere l'array in tre sezioni, ordinandole ciascuna (in modo ricorsivo, ovviamente) e poi unendole. La parte di unione richiederebbe un parametro aggiuntivo (per la terza parte scelta, ad esempio merge(array,l,m,n,r);
).