Tutte le funzioni ricorsive possono essere codificate con iterazioni? [chiuso]


10

Quali sono i vantaggi della ricorsione?

Alcuni linguaggi di programmazione possono ottimizzare la ricorsione della coda, ma, ancora in termini generali, la ricorsione consuma più risorse rispetto ai cicli regolari.

È possibile avere una versione iterativa di alcune funzioni ricorsive?



Risposte:


10

Sì, puoi codificare le funzioni ricorsive come iterazioni. Fondamentalmente richiede di mantenere manualmente le informazioni che altrimenti sarebbero state gestite dal metodo che chiama il codice generato dal compilatore.

In altre parole, è necessario uno stack in cui ogni voce è una struttura contenente i parametri passati e tutte le variabili locali. Lavori sempre sulla voce più in alto nello stack. Se hai bisogno di chiamare te stesso, crea una nuova voce e aggiungi lo stack. Al termine, prendere la voce più in alto dello stack esponendo quella seguente e utilizzare la voce in precedenza più in alto per estrarre i valori di ritorno e aggiornare di conseguenza la nuova voce in cima.

Ti suggerisco di studiare un libro del compilatore per vedere come questo viene solitamente implementato nel codice macchina.


Capisco. Quindi, quale vantaggio avrebbe la ricorsione? Semplicità?
OscarRyz,

2
@OscarRyz: Sì, ed è più elegante.
Michael K,

@OscarRyz, il modo in cui ho descritto è la ricorsione. Semplicemente non viene fatto con le istruzioni native della CPU. Farlo manualmente ti consente di fare cose, come la parallelizzazione, che mappano male alle istruzioni native.

15

La ricorsione è spesso un modo più naturale di vedere le cose rispetto all'iterazione. Ad esempio, considera l'attraversamento interno di un albero binario: inorder(left); process(); inorder(right);è molto più semplice che mantenere esplicitamente uno stack.

Fintanto che non vai troppo in profondità (facendo esplodere la pila), la differenza nell'uso delle risorse è di solito banale. Non ti preoccupare in generale. Il codice semplice è normalmente migliore del codice ottimizzato a mano, anche se ci sono eccezioni. Giusto è normalmente meglio che veloce.

Qualsiasi algoritmo ricorsivo può essere espresso come algoritmo iterativo, ma potrebbe essere necessario mantenere uno stack esplicito (corrispondente allo stack di chiamate gestito in modo implicito). Dopotutto, se compili una funzione ricorsiva, ottieni qualcosa che si basa sulla manipolazione di uno stack e sul ciclo attraverso la funzione, ed è iterativo.

Le funzioni ricorsive della coda possono essere facilmente tradotte in loop e non hanno bisogno di uno stack, ma questo è un caso speciale.


8
Direi che giusto è sempre meglio che veloce. Il codice che fa la cosa sbagliata molto rapidamente non è molto buono per nessuno.
Mason Wheeler,

1
Ma cosa succede se riesci a fare quella cosa sbagliata davvero in fretta ?!
RationalGeek,

1
@jkohlhepp - Posso risolvere qualsiasi problema all'istante. La risposta è 0.
Nota per se stessi - pensa a un nome il

2
L'uso della ricorsione piuttosto che di uno stack esplicito può essere più efficiente, evitando la necessità di allocazioni di heap, possibile frammentazione della memoria e possibili problemi di localizzazione. Tuttavia, a "destra è normalmente meglio di veloce", lo stack overflow nel caso in cui il tuo software debba gestire significa che il tuo codice è rotto. Di solito, i casi problematici sono abbastanza facili da individuare: la ricorsione su un albero (ragionevolmente equilibrato) va bene, ma la ricorsione su un albero che può essere molto sbilanciato o su un elenco collegato, può essere un grave bug in una lingua come C. Peggio ancora , può sopravvivere a semplici test e arrestarsi in modo anomalo solo se distribuito per davvero.
Steve314,

1
Penso che tutti capiate cosa volesse dire Mason e state solo scherzando per il gusto di farlo. Naturalmente un programma lento corretto è più utile di un programma veloce errato.
Giorgio,

4

Quali sono i vantaggi della ricorsione?

Prova a risolvere il problema delle Torri di Hanoi in modo iterativo. Una volta che ti arrendi, dai un'occhiata alla soluzione iterativa e confrontala con quella ricorsiva. Quale è più semplice?

È possibile avere una versione iterativa di alcune funzioni ricorsive?

Sì, in linea di principio. Tuttavia, per molti problemi, inclusi compiti molto comuni, come attraversamenti di alberi, le soluzioni ricorsive sono molto più semplici ed eleganti di quelle iterative.


3

Quali sono i vantaggi della ricorsione?

Semplicità. Senza l'ottimizzazione del tail-call, ovviamente, occorrono più risorse (stack), ma come implementereste, per esempio, deltreein Java senza ricorsione? La svolta è che delete()possono eliminare le directory solo se sono vuote; eccolo con la ricorsione:

deltree(File fileOrDirectory) {
    if (fileOrDirectory.isDirectory()) {
        for (File subFileOrDirectory : fileOrDirectory.listFiles()) {
            deltree(subFileOrDirectory);
        }
    }
    fileOrDirectory.delete();
}

1
Con una pila, come indicato da altre risposte.
Nicole,

Sì, ma quanto è semplice? -)
Joonas Pulakka,

Oh, la ricorsione è decisamente migliore. Pensavo stessi dicendo che non era possibile.
Nicole,

0

Credo che la ricorsione sia uno di quegli strumenti che un programmatore deve avere per vivere. Con la ricorsione puoi "pensare" i tuoi algoritmi e risolverli proprio come ci hai pensato. Ma, devo avvertirti, tutti parlano di quanto sia bella la ricorsione e di quanta semplicità porti al codice, riguardo al fatto che ho alcune cose da dire:

  1. Innanzitutto, pensare al "modo ricorsivo" di un algoritmo non è facile. Costruire una funzione come un fattoriale (n!) O qualcosa come Hanoi Towers è solo la punta dell'iceberg, e raggiungere il fondo richiede un tempo troppo lungo.
  2. Non pensare che la ricorsione porti semplicità solo nel tuo codice, a volte il modo iterativo è brutto e disordinato, ma è conveniente (guarda nella soluzione ricorsiva del problema di Fibonacci)

Avendo in mente queste cose, impara la ricorsione! è divertente, complesso e ti spezzerà il cervello! Ma ti ritroverai ad amarlo.

Buona fortuna!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.