Si vous cherchez simplement à accélérer votre algorithme récursif, la mémoisation pourrait être suffisante. Il s'agit de la technique de stockage des résultats des appels de fonction afin que les appels futurs avec les mêmes paramètres puissent simplement réutiliser le résultat. Ceci est applicable si (et seulement si) votre fonction
- n'a pas d'effets secondaires et
- ne dépend que de ses paramètres (c'est-à-dire pas d'un certain état).
Cela vous fera gagner du temps si (et seulement si) la fonction est appelée avec les mêmes paramètres encore et encore. Des exemples populaires incluent la définition récursive des nombres de Fibonacci, c'est-à-dire
f(0)f(1)f(n+2)=0=1=f(n+1)+f(n), n≥0
Lorsqu'il est évalué naïvement, est souvent appelé exponentiellement. Avec la mémoisation, a toujours été calculé par déjà, donc il ne reste qu'un nombre linéaire d'appels.f ( n ) f ( n + 1 )ff(n)f(n+1)
Notez que, en revanche, la mémoisation est presque inutile pour des algorithmes comme le tri par fusion: généralement peu (le cas échéant) de listes partielles sont identiques, et les contrôles d'égalité sont chers (le tri n'est que légèrement plus coûteux!).
Dans les implémentations pratiques, la façon dont vous stockez les résultats est d'une grande importance pour les performances. L'utilisation de tables de hachage peut être le choix évident, mais peut casser la localité. Si vos paramètres sont des entiers non négatifs, les tableaux sont un choix naturel mais peuvent entraîner une surcharge de mémoire énorme si vous n'utilisez que certaines entrées. Par conséquent, la mémoisation est un compromis entre effet et coût; son efficacité dépend de votre scénario spécifique.
La programmation dynamique est une bête complètement différente. Il est applicable aux problèmes avec la propriété qui
- il peut être partitionné en sous-problèmes (probablement de plusieurs manières),
- ces sous-problèmes peuvent être résolus indépendamment,
- des solutions (optimales) de ces sous-problèmes peuvent être combinées à des solutions (optimales) du problème d'origine et
- les sous-problèmes ont la même propriété (ou sont triviaux).
Ceci est généralement (implicitement) sous-entendu lorsque les gens invoquent le principe d'optimalité de Bellman .
Maintenant, cela ne décrit qu'une classe de problèmes qui peuvent être exprimés par un certain type de récursivité. Leur évaluation est (souvent) efficace, car la mémoisation peut être appliquée à bon escient (voir ci-dessus); généralement, des sous-problèmes plus petits surviennent en tant que parties de nombreux problèmes plus importants. Les exemples populaires incluent la distance d'édition et l' algorithme Bellman-Ford .