J'ai étudié les fonctions récursives, et apparemment, ce sont des fonctions qui s'appellent elles-mêmes et n'utilisent pas d'itérations / boucles (sinon ce ne serait pas une fonction récursive).
Cependant, en surfant sur le Web pour des exemples (le problème récursif des 8 reines), j'ai trouvé cette fonction:
private boolean placeQueen(int rows, int queens, int n) {
boolean result = false;
if (row < n) {
while ((queens[row] < n - 1) && !result) {
queens[row]++;
if (verify(row,queens,n)) {
ok = placeQueen(row + 1,queens,n);
}
}
if (!result) {
queens[row] = -1;
}
}else{
result = true;
}
return result;
}
Il y a une while
boucle impliquée.
... donc je suis un peu perdu maintenant. Puis-je utiliser des boucles ou non?
placeQueen
"place 8 queens" et la version la plus simple deplaceQueen
"place 7 queens" (puis place 6, etc.)Réponses:
Vous avez mal compris la récursivité: bien qu'elle puisse être utilisée pour remplacer l'itération, il n'y a absolument aucune obligation pour la fonction récursive de ne pas avoir d'itérations internes à elle-même.
La seule condition pour qu'une fonction soit considérée comme récursive est l'existence d'un chemin de code par lequel elle s'appelle, directement ou indirectement. Toutes les fonctions récursives correctes ont également un conditionnel quelconque, les empêchant de "se reproduire" pour toujours.
Votre fonction récursive est idéale pour illustrer la structure de la recherche récursive avec retour arrière. Elle commence par la vérification de la condition de sortie
row < n
et procède à des décisions de recherche sur son niveau de récursivité (c'est-à-dire la sélection d'une position possible pour le nombre de reinesrow
). Après chaque itération, un appel récursif est effectué pour s'appuyer sur la configuration que la fonction a trouvée jusqu'à présent; finalement, il "row
touchen
le fond" lorsqu'il atteint l'appel récursif qui estn
profond.la source
La structure générale d'une fonction récursive ressemble à ceci:
Le texte que j'ai marqué comme
/*recursive processing*/
pourrait être n'importe quoi. Il peut inclure une boucle, si le problème résolu le nécessite, et peut également inclure des appels récursifs àmyRecursiveFunction
.la source
Vous pouvez sûrement utiliser des boucles dans une fonction récursive. Ce qui rend une fonction récursive, c'est seulement le fait que la fonction s'appelle à un moment donné de son chemin d'exécution. Cependant, vous devriez avoir une condition pour empêcher les appels de récursion infinis à partir desquels votre fonction ne peut pas retourner.
la source
Les appels et boucles récursifs ne sont que deux manières / constructions pour implémenter un calcul itératif.
Une
while
boucle correspond à un appel récursif de queue (voir par exemple ici ), c'est-à-dire une itération dans laquelle vous n'avez pas besoin de sauvegarder les résultats intermédiaires entre deux itérations (tous les résultats d'un cycle sont prêts lorsque vous entrez dans le cycle suivant). Si vous avez besoin de stocker des résultats intermédiaires que vous pourrez réutiliser plus tard, vous pouvez soit utiliser unewhile
boucle avec une pile (voir ici ), soit un appel récursif non récursif (c'est-à-dire arbitraire).De nombreuses langues vous permettent d'utiliser les deux mécanismes et vous pouvez choisir celui qui vous convient le mieux et même les mélanger dans votre code. Dans les langages impératifs comme C, C ++, Java, etc., vous utilisez normalement une boucle
while
oufor
lorsque vous n'avez pas besoin d'une pile, et vous utilisez des appels récursifs lorsque vous avez besoin d'une pile (vous utilisez implicitement la pile d'exécution). Haskell (un langage fonctionnel) n'offre pas de structure de contrôle d'itération, vous ne pouvez donc utiliser que des appels récursifs pour effectuer l'itération.Dans votre exemple (voir mes commentaires):
la source
Vous avez raison de penser qu'il existe une relation entre la récursivité et l'itération ou la boucle. Les algorithmes récursifs sont souvent convertis manuellement ou même automatiquement en solutions itératives à l'aide de l'optimisation des appels de queue.
Dans huit reines, la partie récursive est liée au stockage des données nécessaires au suivi arrière. Lorsque vous pensez à la récursivité, il est utile de penser à ce qui est poussé sur la pile. La pile peut contenir des paramètres de passage par valeur et des variables locales qui jouent un rôle clé dans l'algorithme, ou parfois des éléments qui ne sont pas aussi apparemment pertinents comme l'adresse de retour ou dans ce cas, une valeur transmise avec le nombre de reines utilisées mais pas changé par l'algorithme.
L'action qui se produit dans huit reines est qu'essentiellement, on nous donne une solution partielle pour un certain nombre de reines dans les premières colonnes à partir desquelles nous déterminons de manière itérative des choix valides jusqu'à présent dans la colonne actuelle que nous passons récursivement pour être évalués pour la colonnes restantes. Localement, huit reines gardent une trace de la ligne qu'il essaie et si le suivi arrière se produit, il est prêt à parcourir les lignes restantes ou à revenir en arrière en retournant simplement s'il ne trouve aucune autre ligne qui pourrait fonctionner.
la source
La partie "créer une version plus petite du problème" peut avoir des boucles. Tant que la méthode s'appelle en passant comme paramètre la version plus petite du problème, la méthode est récursive. Bien sûr, une condition de sortie, lorsque la plus petite version possible du problème est résolue et que la méthode renvoie une valeur, doit être fournie pour éviter une condition de dépassement de pile.
La méthode de votre question est récursive.
la source
La récursivité appelle à nouveau votre fonction et le principal avantage de la récursivité est d'économiser de la mémoire. La récursivité peut contenir des boucles, elles sont utilisées pour effectuer une autre opération.
la source