Se cerchi solo di accelerare il tuo algoritmo ricorsivo, la memoria potrebbe essere sufficiente. Questa è la tecnica di memorizzazione dei risultati delle chiamate di funzione in modo che le chiamate future con gli stessi parametri possano semplicemente riutilizzare il risultato. Questo è applicabile se (e solo se) la tua funzione
- non ha effetti collaterali e
- dipende solo dai suoi parametri (cioè non da alcuni stati).
Ti farà risparmiare tempo se (e solo se) la funzione viene chiamata ripetutamente con gli stessi parametri. Esempi popolari includono la definizione ricorsiva dei numeri di Fibonacci, cioè
f( 0 )f( 1 )f( n + 2 )= 0= 1= f( n + 1 ) + f( n ), n ≥ 0
ff( n )f(n+1)
Si noti che, al contrario, la memoria è quasi inutile per algoritmi come unisci ordinamento: di solito pochi (se presenti) elenchi parziali sono identici e i controlli di uguaglianza sono costosi (l'ordinamento è solo leggermente più costoso!).
Nelle implementazioni pratiche, il modo in cui archiviate i risultati è di grande importanza per le prestazioni. L'uso delle tabelle hash può essere la scelta ovvia, ma potrebbe interrompere la località. Se i parametri sono numeri interi non negativi, le matrici sono una scelta naturale ma possono causare un sovraccarico di memoria enorme se si utilizzano solo alcune voci. Pertanto, la memoria è un compromesso tra effetto e costo; se ripaga dipende dal tuo scenario specifico.
La programmazione dinamica è completamente un'altra bestia. È applicabile a problemi con la proprietà che
- può essere suddiviso in sottoproblemi (probabilmente in più di un modo),
- questi sottoproblemi possono essere risolti in modo indipendente,
- Le soluzioni (ottimali) di tali sottoproblemi possono essere combinate con soluzioni (ottimali) del problema originale e
- i sottoproblemi hanno la stessa proprietà (o sono banali).
Questo è generalmente (implicitamente) implicito quando le persone invocano il Principio di ottimalità di Bellman .
Ora, questo descrive solo una classe di problemi che possono essere espressi da un certo tipo di ricorsione. La valutazione di questi è (spesso) efficace perché la memoisation può essere applicata con grande efficacia (vedi sopra); di solito, sottoproblemi minori si verificano come parti di molti problemi più grandi. Esempi popolari includono la modifica della distanza e l' algoritmo Bellman-Ford .