Qu'est-ce que la récursivité et quand dois-je utiliser?
L'un des thèmes qui semble venir régulièrement sur les listes de diffusion et les discussions en ligne est le bien-fondé (ou pas) de faire un Diplôme en Sciences Informatiques. Un argument qui semble venir de temps et de nouveau pour le négatif de la soirée, c'est qu'ils ont été codant pour un nombre d'années et qu'ils n'ont jamais utilisé la récursivité.
La question est donc:
- Ce qui est de la récursivité?
- Quand dois-je utiliser la récursivité?
- Pourquoi ne pas les gens d'utiliser la récursivité?
- Et peut-être que cela aide: stackoverflow.com/questions/126756/...
- Cela peut aider à saisir le concept: accédez au lien fourni sur le deuxième commentaire de la question sur cette page et de faire ce que les commentaires disent de faire: stackoverflow.com/questions/3021/...
Vous devez vous connecter pour publier un commentaire.
Il y a un certain nombre de bonnes explications de la récursivité dans ce fil, cette réponse, c'est pourquoi vous ne devriez pas l'utiliser dans la plupart des langues.* Dans la plupart des grandes impératif implémentations de langue (c'est à dire tous les grands de la mise en œuvre de C, C++, Basic, Python, Ruby,Java et C#) itération est infiniment préférable à la récursivité.
De voir pourquoi, marcher à travers les étapes que ci-dessus langues à utiliser pour l'appel d'une fonction:
De faire toutes ces étapes prennent du temps, généralement un peu plus qu'il n'en faut pour parcourir une boucle. Cependant, le vrai problème est dans l'étape #1. Lorsque de nombreux programmes de démarrage, ils assignent un seul morceau de la mémoire de leur pile, et quand ils sont à court de mémoire (souvent, mais pas toujours en raison de la récursivité), le programme se bloque à cause d'un un débordement de pile.
Donc, dans ces langues, la récursivité est plus lent, et il vous rend vulnérable à s'écraser. Il y a encore quelques arguments pour l'utilisant bien. En général, le code écrit de manière récursive est plus courte et un peu plus élégante, une fois que vous savez comment faire pour le lire.
Il y a une technique que la langue exécutants peuvent utiliser appelée la queue d'appel d'optimisation qui peut éliminer certaines classes de débordement de la pile. Mettre succinctement: si une fonction de retour d'expression est simplement le résultat d'un appel de fonction, alors vous n'avez pas besoin d'ajouter un nouveau niveau dans la pile, vous pouvez les réutiliser pour la fonction appelée. Malheureusement, peu de langage impératif-implémentations de queue-appel d'optimisation intégré.
* J'aime la récursivité. Mon préféré statique de la langue ne pas utiliser de boucles à tous, la récursivité est la seule façon de faire quelque chose à plusieurs reprises. Je ne pense pas que la récursivité est généralement une bonne idée dans des langues qui ne sont pas à l'écoute pour elle.
** Par la voie de Mario, le nom typique pour votre ArrangeString fonction "joindre", et je serais surpris si la langue de votre choix n'a pas déjà une.
Un anglais Simple exemple de récursivité.
A la base, l'informatique sens, la récursivité est une fonction qui s'appelle elle-même. Disons que vous avez une liste liée à la structure:
Et vous voulez savoir combien de temps une liste chaînée est que vous pouvez faire cela avec la récursivité:
(Ceci pourrait être fait avec une boucle for, mais est utile comme une illustration de la notion)
length(list->next)
doit encore revenir àlength(list)
de sorte que le dernier peut ajouter 1 au résultat. Ont été écrit pour passer la longueur si loin le long, alors seulement pourrions-nous oublier l'appelant existé. Commeint length(const Node* list, int count=0) { return (!list) ? count : length(list->next, count + 1); }
.Chaque fois qu'une fonction s'appelle elle-même, la création d'une boucle, alors que c'est la récursivité. Comme avec n'importe quoi il y a de bons usages et à de mauvais usages de la récursivité.
Le plus simple est de la queue de la récursivité, où la dernière ligne de la fonction est un appel à elle-même:
Cependant, c'est un boiteux, presque inutile exemple, car il peut facilement être remplacé par des plus efficaces itération. Après tout, la récursivité souffre d'un appel de fonction, les frais généraux, qui, dans l'exemple ci-dessus pourrait être importante par rapport à l'exploitation, à l'intérieur de la fonction elle-même.
Donc toute raison de faire de la récursivité plutôt que d'itération devrait être de profiter de la la pile des appels de faire quelques trucs forts. Par exemple, si vous appelez une fonction plusieurs fois avec des paramètres différents à l'intérieur de la boucle, alors que c'est un moyen pour accomplir la ramification. Un exemple classique est le Triangle de Sierpinski.
Vous pouvez dessiner un de ces très simplement avec la récursivité, où la pile d'appel des succursales dans 3 directions:
Si vous essayez de faire la même chose avec des itérations je pense que vous trouverez cela prend beaucoup plus de code à accomplir.
D'autres cas d'utilisation courants peuvent inclure la traversée des hiérarchies, par exemple un site web crawlers, répertoire des comparaisons, etc.
Conclusion
Dans la pratique, la récursivité qui fait le plus de sens quand vous en avez besoin itératif de ramification.
La récursivité est une méthode de résolution de problèmes basée sur la division et de conquête de la mentalité.
L'idée de base est que vous prenez le problème d'origine et de le diviser en plus petites (plus facilement résolu) instances de lui-même, de résoudre ces petites instances (habituellement en utilisant le même algorithme de nouveau), puis remonter vers la solution finale.
L'exemple canonique est une routine pour générer la Factorielle de n. La Factorielle de n est calculé en multipliant tous les nombres entre 1 et n. Une solution itérative en C# ressemble à ceci:
Il n'y a rien de surprenant au sujet de la solution itérative et il doit faire sens pour quiconque est familier avec le C#.
La solution récursive est trouvé en reconnaissant que le nième Factorielle est n * Fact(n-1). Ou pour le dire d'une autre façon, si vous savez ce que la Factorielle du nombre est, vous pouvez calculer la suivante. Voici la solution récursive en C#:
La première partie de cette fonction est connue comme une de la Base de Cas (ou parfois de la Garde de la Clause) et tout ce qui empêche l'algorithme de running à tout jamais. Elle retourne la valeur 1 lorsque la fonction est appelée avec une valeur de 1 ou moins. La deuxième partie est plus intéressante et est connu comme le Récursive Étape. Ici, nous appelons la même méthode avec un peu modifié le paramètre (nous décrémenter par 1), puis multiplier le résultat avec notre copie de n.
Lors de la première rencontre, ce peut être une sorte de confusion, donc il est instructif d'examiner comment il fonctionne lorsque vous exécutez. Imaginez que nous appelons FactRec(5). Nous entrons dans la routine, ne sont pas récupérés par le cas de base et on se retrouve donc comme ceci:
Si nous re-entrer dans la méthode avec le paramètre 4 nous sommes de nouveau n'est pas stoppé par le gardien de la clause et donc nous retrouver à:
Si l'on substitue cette valeur de retour dans la valeur de retour ci-dessus nous obtenons
Cela devrait vous donner une idée de la façon dont la solution finale est arrivé au nous allons donc la voie rapide et montrer à chaque étape sur le chemin vers le bas:
Finale de substitution se produit lorsque le cas de base est déclenchée. À ce stade, nous avons une simple algrebraic formule pour résoudre qui correspond directement à la définition des Factorielles, en premier lieu.
Il est instructif de noter que chaque appel à la méthode les résultats dans une base de cas a été déclenché ou un appel à la même méthode, où les paramètres sont plus proches d'une base de cas (souvent appelé un appel récursif). Si ce n'est pas le cas, alors la méthode s'exécute indéfiniment.
FactRec()
doit être multiplié parn
avant de retourner.La récursivité est la résolution d'un problème avec une fonction qui s'appelle elle-même. Un bon exemple de ceci est une fonction factorielle. Factorielle, c'est un problème de maths où la factorielle de 5, par exemple, est 5 * 4 * 3 * 2 * 1. Cette fonction permet de résoudre ce en C# pour des entiers positifs (non testé - il y a peut être un bug).
La récursivité se réfère à une méthode qui permet de résoudre un problème par la résolution d'une version plus petite de la le problème et puis en utilisant le résultat de plus quelques autres le calcul de formuler la réponse au problème initial. Souvent, dans le processus de résolution de la plus petite version, la méthode permettra de résoudre une encore plus petite version du problème, et ainsi de suite, jusqu'à ce qu'il atteigne un "cas de base" qui est trivial à résoudre.
Par exemple, pour calculer une factorielle du nombre
X
, on peut la représenter commeX times the factorial of X-1
. Ainsi, la méthode "analyse" pour trouver la factorielle deX-1
, et multiplie ensuite ce qu'il a obtenu parX
de donner une réponse définitive. Bien sûr, de trouver la factorielle deX-1
, il va d'abord calculer la factorielle deX-2
, et ainsi de suite. Le cas de base serait quandX
est 0 ou 1, dans lequel cas, il sait que le retour1
depuis0! = 1! = 1
.Envisager une vieille, bien connu de problème:
La définition du pgcd est étonnamment simple:
où la mod est la opérateur modulo (qui est, le reste après la division entière).
En anglais, cette définition dit le plus grand commun diviseur d'un nombre et le zéro est un nombre, et le plus grand commun diviseur de deux nombres m et n est le plus grand diviseur commun de n et le reste après division m par n.
Si vous voulez savoir pourquoi cela fonctionne, voir l'article de Wikipedia sur le Algorithme d'euclide.
Nous allons calculer pgcd(10, 8) comme un exemple. Chaque étape est égale à celle juste avant:
Dans la première étape, 8 n'est pas égale à zéro, de sorte que la deuxième partie de la définition s'applique. 10 mod 8 = 2 car 8 passe en 10 fois avec un reste de 2. À l'étape 3, la deuxième partie s'applique de nouveau, mais cette fois-8 mod 2 = 0 car 2 divise 8 sans reste. À l'étape 5, le deuxième argument est 0, donc la réponse est 2.
Avez-vous remarqué que pgcd apparaît sur les deux côtés droit et gauche du signe d'égalité? Un mathématicien dirais que cette définition est récursive car l'expression que vous voulez définir se reproduit à l'intérieur de sa définition.
Des définitions récursives ont tendance à être élégant. Par exemple, une définition récursive de la somme d'une liste est
où
head
est le premier élément dans une liste ettail
est le reste de la liste. Notez quesum
se reproduit à l'intérieur de sa définition à la fin.Peut-être que vous préférez le maximum de valeur dans une liste au lieu de cela:
Vous pouvez définir la multiplication de nombres entiers non négatifs de manière récursive pour le transformer en une série d'ajouts:
Si peu sur la transformation de la multiplication dans une série d'ajouts ne fait pas de sens, essayez d'étendre quelques exemples simples pour voir comment il fonctionne.
Fusion de tri a une belle définition récursive:
Des définitions récursives sont tout autour si vous savez quoi chercher. Notez que toutes ces définitions ont très simple de la base de cas, par exemple, pgcd(m, 0) = m. Le récursive cas whittle de loin sur le problème pour trouver les réponses faciles.
Avec cette compréhension, vous pouvez maintenant apprécier les autres algorithmes dans L'article de Wikipedia sur la récursivité!
L'exemple canonique est la factorielle qui ressemble à:
En général, la récursivité n'est pas nécessairement rapide (appel de fonction, les frais généraux tend à être élevée en raison des fonctions récursives ont tendance à être de petite taille, voir ci-dessus) et peuvent souffrir de certains problèmes (débordement de pile quelqu'un?). Certains disent qu'ils ont tendance à être difficile à obtenir dans non négligeable de cas, mais je n'ai pas vraiment acheter que. Dans certaines situations, la récursivité fait le plus de sens et est la plus élégante et la plus claire de la façon d'écrire une fonction particulière. Il convient de noter que certaines langues faveur récursive des solutions et de les optimiser beaucoup plus (LISP vient à l'esprit).
Une fonction récursive est une fonction qui s'appelle elle-même. La raison la plus commune que j'ai trouvé pour l'utilisation, il est traversant une structure en arbre. Par exemple, si j'ai un TreeView avec des cases à cocher (pensez à l'installation d'un nouveau programme, "choisir les fonctionnalités à installer" à la page), j'aimerais un "check all" bouton qui serait quelque chose comme ceci (pseudo-code):
De sorte que vous pouvez voir que le checkRecursively vérifie d'abord le nœud qui c'est passé, puis appelle elle-même pour chaque nœud enfants.
Vous devez être un peu prudent avec la récursivité. Si vous vous retrouvez dans une boucle récursive infinie, vous obtiendrez une exception de Dépassement de Pile 🙂
Je ne peux pas penser à une raison pourquoi les gens ne devraient pas l'utiliser, le cas échéant. Il est utile dans certaines circonstances et pas dans d'autres.
Je pense que c'est une technique intéressante, certains codeurs peut-être la fin de l'utiliser plus souvent que ce qu'ils devraient, sans justification réelle. Ce qui a donné à la récursivité d'une mauvaise réputation dans certains milieux.
La récursivité est une expression directement ou indirectement de référencement de lui-même.
Envisager acronymes récursifs comme un simple exemple:
Plus d'exemples sur Wikipedia
La récursivité qui fonctionne le mieux avec ce que j'aime à appeler "la fractale des problèmes", où vous avez affaire à une chose importante qui est faite de plus petites versions de cette grande chose, chaque de ce qui est encore plus petite version de la chose, et ainsi de suite. Si jamais vous avez à parcourir ou rechercher à travers quelque chose comme un arbre ou imbriquée des structures identiques, vous avez un problème qui pourrait être un bon candidat pour la récursivité.
Les gens à éviter la récursivité pour un certain nombre de raisons:
La plupart des gens (moi y compris) couper leur programmation dents de la procédure ou de la programmation orientée objet par opposition à la programmation fonctionnelle. Pour ces personnes, l'approche itérative (généralement à l'aide de boucles) se sent plus naturel.
Ceux d'entre nous qui coupe notre programmation dents sur procédurale ou orientée objet de la programmation ont souvent été dit pour éviter une récursion parce que c'est source d'erreurs.
On nous a souvent dit que la récursivité est lente. L'appel et le retour à une routine à plusieurs reprises implique beaucoup de la pile en poussant et en sautant, ce qui est plus lent que celui de la boucle. Je pense que certaines langues gérer mieux que d'autres, et ces langues sont probablement pas ceux où le paradigme dominant est procédurale ou orientée objet.
Pour au moins un couple de langages de programmation que j'ai utilisé, je me souviens avoir entendu les recommandations de ne pas utiliser la récursivité si elle va au-delà d'une certaine profondeur, parce que sa pile n'est pas profonde.
Récursive de déclaration est celle qui vous permet de définir le processus de quoi faire la prochaine que d'une combinaison d'entrées et de ce que vous avez déjà fait.
Par exemple, prendre factorielle:
Mais il est facile de voir factorielle(6) est aussi:
Donc généralement:
Bien sûr, la chose la plus délicate à propos de la récursivité, c'est que si vous voulez définir les choses en termes de ce que vous avez déjà fait, il doit être un endroit pour commencer.
Dans cet exemple, nous venons de faire un cas particulier par la définition de la factorielle(1) = 1.
Maintenant, nous voyons de bas en haut:
Depuis que nous avons défini factorielle(1) = 1, nous atteignons le "bas".
En règle générale, les procédures récursives sont en deux parties:
1) La partie récursive, qui définit une procédure en termes de nouvelles entrées combinées avec ce que vous avez "déjà fait" par la même procédure. (c'est à dire
factorial(n) = n*factorial(n-1)
)2) Une pièce de base, ce qui permet de s'assurer que le processus ne soit pas répéter éternellement en lui donnant un peu de place pour le début (c'est à dire
factorial(1) = 1
)Il peut être un peu déroutant pour obtenir autour de votre tête au premier abord, mais il suffit de regarder un tas d'exemples et il devrait tous se réunir. Si vous voulez une compréhension beaucoup plus profonde de la notion, étude induction mathématique. Aussi, soyez conscient que certaines langues optimiser les appels récursifs, tandis que d'autres ne le font pas. Il est assez facile de faire incroyablement lent fonctions récursives si vous n'êtes pas prudent, mais il existe également des techniques pour les rendre performants dans la plupart des cas.
Espère que cela aide...
J'aime cette définition:
Dans la récursivité, une routine résout une petite partie du problème lui-même, et qui divise le problème en petits morceaux, puis appelle elle-même pour résoudre chacun des morceaux plus petits.
J'aime aussi Steve McConnells discussion de la récursivité dans le Code Complet où il critique les exemples utilisés dans les livres d'Informatique sur la Récursivité.
Je pensais que c'était un point très intéressant à soulever et peut-être une raison pourquoi la récursivité est souvent mal compris.
EDIT:
Ce n'était pas une fouille à la réponse de Dav - je n'avais pas vu cette réponse lorsque j'ai posté cette
1.)
Une méthode est récursive si elle peut s'appeler elle-même; soit directement:
ou indirectement:
2.) Lors de l'utilisation de la récursivité
3.) Les gens utiliser la récursivité seulement quand il est très complexe à écrire du code itératif. Par exemple, l'arbre transversal des techniques comme la précommande, postorder peut être fait à la fois itérative et récursive. Mais habituellement, nous utilisons récursive en raison de sa simplicité.
Voici un exemple simple: combien d'éléments dans un ensemble. (il existe de meilleures façons de compter les choses, mais c'est une belle récursive simple exemple.)
Tout d'abord, nous avons besoin de deux règles:
Supposons que vous avez un jeu comme ceci: [x x x]. nous allons compter le nombre d'éléments.
L'on peut représenter comme suit:
Lors de l'application d'une solution récursive, généralement, vous avez au moins 2 règles:
Si nous traduisons ci-dessus de pseudo-code, on obtient:
Il y a beaucoup plus d'exemples utiles (déplacement le long d'un arbre, par exemple) qui, je suis sûr que d'autres personnes vont couvrir.
Bien, c'est un assez décent définition que vous avez. Et wikipédia a une bonne définition trop. Donc, je vais ajouter un autre (probablement le pire) de la définition pour vous.
Quand les gens parlent de "récursivité", ils sont généralement de parler d'une fonction qu'ils ont écrit qui s'appelle elle-même à plusieurs reprises jusqu'à ce qu'il se fait de son travail. La récursivité peut être utile lors de la traversée des hiérarchies dans des structures de données.
Un exemple: Une définition récursive d'un escalier:
Un escalier se compose de:
- une seule étape et un escalier (récursivité)
- ou une seule étape (résiliation)
Répéter sur un problème résolu: ne rien faire, vous avez terminé.
Répéter sur un problème ouvert: faire la prochaine étape, puis répéter sur le reste.
En anglais:
Supposons que vous pouvez faire 3 choses:
Vous avez un lot de pommes en face de vous sur une table et vous voulez savoir combien de pommes il y a des.
Le processus de répéter la même chose jusqu'à ce que vous êtes fait s'appelle de la récursivité.
J'espère que c'est le "langage simple" réponse que vous cherchez!
Une fonction récursive est une fonction qui contient un appel à elle-même. Un appel récursif struct est une structure qui contient une instance de lui-même. Vous pouvez combiner les deux, comme un appel récursif de la classe. La partie clé de l'récursive de l'élément, c'est qu'il contient une instance/appel de lui-même.
Tenir compte de deux miroirs face à face. Nous avons vu le pur effet infini qu'ils font. Chaque réflexion est une instance d'un miroir, qui est contenue dans une autre instance d'un miroir, etc. Le miroir contenant un reflet de lui-même est la récursivité.
Un un arbre de recherche binaire est un bon exemple de programmation de la récursivité. La structure est récursive à chaque Nœud contenant 2 instances d'un Nœud. Fonctions pour travailler sur un arbre de recherche binaires sont également récursive.
C'est une vieille question, mais je veux ajouter une réponse du point de vue logistique (j'.e pas de l'exactitude de l'algorithme de point de vue ou le point de vue des performances).
J'utilise Java pour le travail, et Java ne supporte pas la fonction imbriquée. En tant que tel, si je veux faire de la récursivité, je pourrais avoir à définir une fonction externe (qui n'existe que parce que mon code se cogne contre Java bureaucratique de l'article), ou je pourrais avoir à refactoriser le code (pour qui j'ai vraiment hate de le faire).
Ainsi, j'ai souvent éviter la récursivité, et l'utilisation de la pile de l'opération au lieu de cela, parce que la récursivité lui-même est essentiellement une pile en fonctionnement.
Vous voulez l'utiliser à tout moment vous avez une structure en arbre. Il est très utile pour lire des données XML.
La récursivité comme il s'applique à la programmation est essentiellement l'appel d'une fonction à partir de l'intérieur de sa propre définition (à l'intérieur de lui-même), avec des paramètres différents afin d'accomplir une tâche.
"Si j'ai un marteau, faire tout ce qui ressemble à un clou."
La récursivité est un problème de résolution de stratégie pour énorme de problèmes, où à chaque pas, juste de, "la tour 2 petites choses dans un plus grand chose," à chaque fois avec le même marteau.
Exemple
Supposons que votre bureau est couvert avec un désordre désorganisé de 1024 papiers. Comment voulez-vous faire un soigné, propre pile de papiers à partir du désordre, en utilisant la récursivité?
Avis que c'est assez intuitif, en dehors de tout compter (ce qui n'est pas strictement nécessaire). Vous ne pourriez pas aller tout le chemin vers le bas pour 1 feuille de meules, dans la réalité, mais vous pourrait, et il fonctionne encore. L'important, c'est le marteau: Avec vos bras, vous pouvez toujours mettre une pile au-dessus de l'autre pour faire un plus gros stack, et il n'a pas d'importance (dans la raison) quel soit pile est.
La récursivité est le processus par lequel un appel de méthode jeles pour être en mesure d'effectuer une certaine tâche. Il réduit redundency de code. La plupart des recurssive fonctions ou méthodes doivent avoir un condifiton pour briser la recussive appel c'est à dire arrêter d'appeler lui-même si une condition est remplie - ce qui empêche la création d'une boucle infinie. Toutes les fonctions ne sont adaptés pour être utilisés de manière récursive.
hey, désolé si mon avis est d'accord avec quelqu'un, j'essaie juste d'expliquer la récursivité dans la plaine de l'anglais.
supposons que vous disposez de trois gestionnaires - Jack, John et Morgan.
Jack gère 2 programmeurs, John - 3, et Morgan - 5.
vous allez donner à chaque gestionnaire de 300$ et que vous voulez savoir quel serait le coût.
La réponse est évidente - mais si de 2 de Morgan-s employés sont aussi des gestionnaires?
VOICI la récursivité.
vous commencez par le haut de la hiérarchie. la estival coût est de 0$.
vous commencez avec Jack,
Ensuite vérifier s'il a toute les gestionnaires que les employés. si vous trouvez l'un d'eux sont, de vérifier si elles ont toute les gestionnaires que les employés, et ainsi de suite. Ajouter 300$ à la estival coût à chaque fois que vous trouver un gestionnaire.
lorsque vous avez terminé avec Jack, allez à la de Jean, ses employés, et de Morgan.
Vous ne saurez jamais, combien de cycles allez-vous avant d'obtenir une réponse, si vous savez comment beaucoup de gestionnaires vous avez et combien de Budget pouvez-vous dépenser.
La récursivité est un arbre avec des branches et des feuilles, appelé les parents et les enfants, respectivement.
Lorsque vous utilisez une récursivité de l'algorithme, plus ou moins consciemment de construire un arbre à partir des données.
En clair, la récursivité des moyens pour répéter quelque chose de nouveau et de nouveau.
Dans la programmation est un exemple de l'appel de la fonction à l'intérieur de lui-même .
Regard sur l'exemple suivant de calcul de la factorielle d'un nombre:
De l'algorithme expositions structurels la récursivité sur un type de données si, fondamentalement, se compose d'un interrupteur de mise en rapport avec des cas pour chaque cas le type de données.
par exemple, lorsque vous travaillez sur un type
structurelle de l'algorithme récursif aurait la forme
c'est vraiment le moyen le plus évident d'écrire des algorith qui fonctionne sur une structure de données.
maintenant, quand vous regardez les entiers (ainsi, les nombres naturels), tel que défini à l'aide des axiomes de Peano,
vous voyez que structurelle de l'algorithme récursif sur des entiers ressemble à ceci
le trop-bien-connu fonction factorielle est le plus trivial exemple de
ce formulaire.
appel de la fonction elle-même ou de l'utilisation de sa propre définition.
La récursivité en informatique est une technique utilisée pour calculer un résultat ou un effet secondaire normal de retour à partir d'une seule fonction (méthode, la procédure, ou bloc) de l'invocation.
La fonction récursive, par définition, doivent avoir la capacité de s'appeler elle-même, soit directement ou indirectement (par le biais d'autres fonctions) en fonction d'une condition de sortie ou les conditions n'étant pas remplies. Si une sortie condition est remplie, le particulier invocation retourne à l'appelant. Cela continue jusqu'à la première invocation est retourné à partir de, date à laquelle le résultat souhaité ou d'effet secondaire sera disponible.
Comme un exemple, voici une fonction pour effectuer l'algorithme Quicksort en Scala (copiés de l'article de Wikipédia pour Scala)
Dans ce cas, la condition de sortie est une liste vide.
Un grand nombre de problèmes peut être considéré de deux types de pièces:
Quel est donc une fonction récursive? Eh bien, c'est là que vous avez une fonction qui est définie en fonction d'elle-même, directement ou indirectement. OK, ça semble ridicule jusqu'à ce que vous vous rendez compte qu'il est judicieux pour les problèmes du type de celles décrites ci-dessus: vous résoudre la base de cas et de traiter avec le récursive des cas en utilisant les appels récursifs à résoudre les petits morceaux du problème incorporé à l'intérieur.
Véritablement l'exemple classique de l'endroit où vous avez besoin de récursivité (ou quelque chose qui sent très bien comme ça), c'est quand vous avez affaire à un arbre. Les feuilles de l'arbre sont les cas de base, et les branches sont les récursive cas. (En pseudo-C.)
La façon la plus simple de l'impression de ce dans le but est d'utiliser la récursivité:
C'est mort facile de voir que cela va fonctionner, car il est clair comme du cristal. (Le non-récursive équivalent, c'est beaucoup plus complexe, nécessitant une pile structure en interne pour gérer la liste de choses à traiter.) Eh bien, en supposant que personne ne fait une circulaire de connexion de cours.
Mathématiquement, le truc à montrer que la récursivité est apprivoisé est de se concentrer sur la recherche d'une métrique pour la taille de l'argumentation. Pour notre exemple d'arbre, le plus simple métrique est la profondeur maximale de l'arbre ci-dessous le nœud courant. Sur les feuilles, c'est zéro. À une branche avec seulement les feuilles en dessous, c'est l'un, etc. Ensuite, vous pouvez simplement montrer qu'il n'y a strictement l'ordre de la taille des arguments que la fonction est appelée dans le but de traiter l'arbre; les arguments pour les appels récursifs sont toujours "moins" dans le sens de la métrique de l'argument pour l'ensemble de l'appel. Avec un strictement décroissante cardinal métrique, vous êtes triés.
Il est également possible d'avoir une récursion infinie. C'est le désordre et dans de nombreuses langues ne fonctionne pas parce que la pile explose. (Lorsqu'il fonctionne, le moteur de langue doit être la détermination de la fonction d'une certaine manière n'est pas de retour et est donc en mesure d'optimiser loin de la tenue de la pile. Choses difficiles en général; tail-recursion est juste le plus trivial manière de faire).
La récursivité, c'est quand vous avez une opération qui utilise lui-même. Il en sera probablement de disposer d'un point d'arrêt, sinon il serait à tout jamais.
Disons que vous souhaitez rechercher un mot dans le dictionnaire. Vous avez une opération appelée "look-up" à votre disposition.
Votre ami dit "j'ai vraiment pu cuillère sur certains pudding dès maintenant!" Vous ne savez pas ce qu'il veut dire, si vous regardez en haut "cuillère" dans le dictionnaire, et il lit quelque chose comme ceci:
Cuillère: nom - un ustensile avec un tour scoop à la fin.
Cuillère: verbe à l'aide d'une cuillère sur quelque chose
Cuillère: verbe - se blottir près de derrière
Aujourd'hui, que vous n'êtes vraiment pas bien l'anglais, cela vous mène dans la bonne direction, mais vous avez besoin de plus d'infos. Si vous sélectionnez "ustensile" et "câlin" pour plus d'informations.
Des câlins: verbe - pour se blottir
Ustensile: nom - un outil, souvent de manger un ustensile
Hey! Vous savez ce qui se est, et il n'a rien à voir avec le pudding. Vous savez aussi que le pudding est quelque chose que vous mangez, si elle fait sens aujourd'hui. Votre ami doit avoir envie de manger du pudding avec une cuillère.
Okay, Okay, c'était un très boiteux exemple, mais il illustre (peut-être mal) les deux parties principales de la récursivité.
1) Il utilise lui-même. Dans cet exemple, vous n'avez pas vraiment l'air d'un mot de façon significative jusqu'à ce que vous comprenez, et que peut signifier plus de mots. Ce qui nous amène au point deux,
2) Il s'arrête quelque part. Il doit avoir une sorte de cas de base. Sinon, vous auriez simplement une recherche de chaque mot dans le dictionnaire, qui n'est probablement pas trop utile. Notre scénario de base est que vous avez obtenu suffisamment d'informations pour faire un lien entre ce que vous l'avez déjà fait et de ne pas comprendre.
Traditionnels exemple qui est donné est factoriel, où 5 factorielle est 1*2*3*4*5 (120). Le cas de base serait de 0 (ou 1, selon le cas). Donc, pour tout nombre entier n, vous effectuez les opérations suivantes
est n égal à 0? retour 1
sinon, retour n * (factorielle de n-1)
nous allons faire cela avec l'exemple de 4 (dont on sait à l'avance est 1*2*3*4 = 24).
la factorielle de 4 ... est-il 0? non, donc il doit être 4 * factorielle de 3
mais quelle est la factorielle de 3? c'est 3 * factorielle de 2
la factorielle de 2 est 2 * factorielle de 1
la factorielle de 1 est 1 * factorielle de 0
et nous SAVONS que la factorielle de 0! 😀 c'est 1, c'est la définition
la factorielle de 1 est 1 * factorielle de 0, qui était de 1... donc 1*1 = 1
la factorielle de 2 est 2 * factorielle de 1, qui était de 1... donc 2*1 = 2
la factorielle de 3 est 3 * factorielle de 2, qui a été 2... donc 3*2 = 6
la factorielle de 4 (enfin!!) est 4 * factorielle de 3, 6... 4*6 est de 24
Factorielle est un simple cas de "cas de base, et utilise lui-même".
Maintenant, remarquez, nous étions encore à travailler sur la factorielle de 4 tout le chemin vers le bas... Si nous voulions factorielle de 100, nous devrions avoir à aller tout le chemin jusqu'à 0... ce qui pourrait avoir beaucoup de frais généraux à elle. De la même manière, si nous trouvons un obscur mot à chercher dans le dictionnaire, il pourrait prendre, à la recherche d'autres mots et de numérisation pour le contexte des indices jusqu'à ce que nous trouver un lien, nous sommes familiers avec. Récursive méthodes peuvent prendre beaucoup de temps pour travailler leur chemin à travers. Cependant, quand ils sont utilisés correctement, et compris, ils peuvent faire le travail compliqué étonnamment simple.
La définition la plus simple de la récursivité est "l'auto-référence". Une fonction qui renvoie à lui-même, j'. e. appelle elle-même est récursive. La chose la plus importante à garder à l'esprit, c'est qu'une fonction récursive doit avoir un "cas de base", j'. e. une condition que si les véritables causes ne pas appeler lui-même, et donc mettre fin à la récursivité. Sinon, vous aurez une récursion infinie:
la récursivité http://cart.kolix.de/wp-content/uploads/2009/12/infinite-recursion.jpg
La récursivité est une technique de définition d'une fonction, d'un ensemble ou d'un algorithme en fonction d'elle-même.
Par exemple
Maintenant elle peut être définie de manière récursive comme:-
En termes de programmation, lorsqu'une fonction ou méthode s'appelle elle-même à plusieurs reprises, jusqu'à ce qu'une condition spécifique devient satisfait, ce processus est appelé la Récursivité. Mais il doit y avoir une condition d'arrêt et de la fonction ou de la méthode doit pas entrer dans une boucle infinie.
ses une façon de faire les choses, indéfiniment, de sorte que chaque option est utilisée.
par exemple, si vous voulez récupérer tous les liens sur une page html que vous souhaitez avoir des récurrences parce que quand vous obtenez tous les liens sur la page 1, vous voulez récupérer tous les liens sur chacun des liens qui se trouvent sur la première page. ensuite, pour chaque lien vers une page que vous voulez à ces liens et ainsi de suite... en d'autres mots, c'est une fonction qui s'appelle elle-même de l'intérieur de lui-même.
lorsque vous faites cela, vous avez besoin d'un moyen de savoir quand s'arrêter, sinon tu va être dans une boucle sans fin de sorte que vous ajouter un entier en paramètre à la fonction pour suivre le nombre de cycles.
en c#, vous aurez quelque chose comme ceci:
J'ai créé une fonction récursive pour concaténer une liste de chaînes de caractères, avec un séparateur entre eux. Je l'utilise principalement pour créer des expressions SQL, en passant par une liste de champs comme le "éléments "et un" virgule+espace' comme séparateur. Voici la fonction (Elle utilise Borland Builder types de données natifs, mais peut être adapté à toutes les autres de l'environnement):
J'appelle cela de cette façon:
Imaginez que vous avez un tableau nommé "champs " avec ces données à l'intérieur: 'albumName', 'releaseDate', 'labelId'. Vous pouvez ensuite appeler la fonction:
Que la fonction commence à travailler, la variable "résultat "reçoit la valeur de la position 0 de la matrice, ce qui est" albumName'.
Puis il vérifie si la position de l'affaire est la dernière. Comme il n'est pas le cas, il concatène le résultat avec le séparateur et le résultat d'une fonction, qui, oh mon Dieu, est-ce la même fonction. Mais cette fois, check it out, il appelle lui-même en ajoutant 1 à la position.
Il ne cesse de répéter, de la création d'une pile LIFO, jusqu'à ce qu'il atteigne un point où la position en cours EST la dernière, alors la fonction retourne uniquement le point sur cette position sur la liste, pas de la concaténation de plus. Ensuite la pile est concaténé à l'envers.
Eu? Si vous ne le faites pas, j'ai une autre façon de l'expliquer. :o)
Je utiliser la récursivité. Quel est le rapport avec le fait d'avoir un CS degré... (que je n'ai pas, par la voie)
Des utilisations les plus courantes que j'ai trouvé:
Mario, je ne comprends pas pourquoi vous avez utilisé la récursivité pour l'exemple.. Pourquoi ne pas simplement faire une boucle par chaque entrée? Quelque chose comme ceci:
La méthode ci-dessus serait plus rapide et plus simple. Il n'y a pas besoin d'utiliser la récursivité en place d'une boucle simple. Je pense que ces sortes d'exemples est pourquoi la récursivité obtient une mauvaise réputation. Même les canonique de la fonction factorielle exemple est mieux mis en œuvre avec une boucle.
Effectivement la meilleure solution récursive pour factorielle doit être:
Parce que cette version est Queue Récursive