È facile eliminare la ricorsione della coda.
Ci sono alcuni casi curiosi in cui la ricorsione non-coda può anche essere eliminata.
-
Esposizione 1: numeri di Fibonacci.
Una soluzione ricorsiva ingenua
fib(n) if (n < 2) return n return fib(n-1) + fib(n-2)
porta a complessità esponenziale. Una soluzione iterativa
fib(n) f_0 = 0 f_1 = 1 for i = 2; i < n; ++i f = f_0 + f1 f_0 = f1 f_1 = f return f
è lineare. So che posso avere uno logaritmico, ma è oltre il punto.
-
Allegato 2: unisci l'ordinamento
Una soluzione ricorsiva
merge_sort(begin, end) mid = begin + (end - begin) merge_sort(begin, mid) merge_sort(mid, end) merge(begin, mid, end)
(che non è così male come mostra 1, ma ancora) consente anche una versione iterativa:
merge_sort(begin, end) for stride = 2; stride < end - begin; stride *= 2 for start = begin; start < end; start += stride merge(start, start + stride/2, start + stride)
Queste mostre apparentemente non correlate condividono un tratto comune: non c'è lavoro svolto sulla via 1 .
Le vere domande sono,
-
questa caratteristica garantisce che l'eliminazione è possibile,
-
è possibile identificarlo e
-
una volta identificato, c'è un modo meccanico per eliminare effettivamente la ricorsione.
Dichiarazione di non responsabilità: mi interessa solo l'eliminazione senza usare uno stack. So che è sempre possibile eliminare la ricorsione introducendo una pila come mostrato in Modo generale per convertire un ciclo (while / for) in ricorsione o da una ricorsione a un ciclo?
[1] Nessuno ci derubare andando giù per la montagna. Non abbiamo soldi andando giù per la montagna. Quando abbiamo i soldi, sulla via del ritorno, allora puoi sudare.