Pour expliquer la récursivité , j'utilise une combinaison d'explications différentes, généralement pour essayer à la fois:
- expliquer le concept,
- expliquer pourquoi c'est important,
- expliquer comment l'obtenir.
Pour commencer, Wolfram | Alpha le définit plus simplement que Wikipedia :
Une expression telle que chaque terme est généré en répétant une opération mathématique particulière.
Mathématiques
Si votre élève (ou la personne que vous expliquez aussi, je dirai désormais élève) a au moins quelques connaissances en mathématiques, il est évident qu'ils ont déjà rencontré la récursivité en étudiant les séries et leur notion de récursivité et leur relation de récurrence .
Une très bonne façon de commencer est alors de démontrer avec une série et de dire que c'est tout simplement ce qu'est la récursion:
- une fonction mathématique ...
- ... qui s’appelle pour calculer une valeur correspondant à un nième élément ...
- ... et qui définit certaines limites.
Habituellement, vous obtenez soit "hein heh, whatev '" au mieux car ils ne l'utilisent toujours pas, soit plus probablement un ronflement très profond.
Exemples de codage
Pour le reste, il s’agit en fait d’une version détaillée de ce que j’ai présenté dans l’ addendum de ma réponse à la question que vous avez évoquée concernant les pointeurs (mauvais jeu de mots).
A ce stade, mes étudiants savent généralement comment imprimer quelque chose à l'écran. En supposant que nous utilisons C, ils savent comment imprimer un seul caractère avec write
ou printf
. Ils connaissent également les boucles de contrôle.
J'ai habituellement recours à quelques problèmes de programmation répétitifs et simples jusqu'à ce qu'ils l'obtiennent:
Factorielle
Factorial est un concept mathématique très simple à comprendre, et sa mise en œuvre est très proche de sa représentation mathématique. Cependant, ils pourraient ne pas l'obtenir au début.
Alphabets
La version alphabet est intéressante pour leur apprendre à réfléchir à la mise en ordre de leurs déclarations récursives. Comme avec les pointeurs, ils vous jetteront des lignes au hasard. Le but est de les amener à réaliser qu’une boucle peut être inversée en modifiant les conditions OU en inversant simplement l’ordre des instructions dans votre fonction. C'est là que l'impression de l'alphabet est utile, car c'est quelque chose de visuel pour eux. Demandez-leur simplement d’écrire une fonction imprimant un caractère pour chaque appel et s’appelant récursivement pour écrire le suivant (ou le précédent).
Amateurs de FP, oubliez le fait qu'imprimer des choses dans le flux de sortie est un effet secondaire pour le moment ... Ne soyons pas trop ennuyeux sur le front de la FP. (Mais si vous utilisez un langage prenant en charge les listes, n'hésitez pas à concaténer une liste à chaque itération et à imprimer le résultat final. Mais d'habitude, je les commence avec C, ce qui n'est malheureusement pas le meilleur pour ce type de problèmes et de concepts.) .
Exponentiation
Le problème de l'exponentiation est légèrement plus difficile ( à ce stade d'apprentissage). Évidemment, le concept est exactement le même que pour une factorielle et il n’ya pas de complexité supplémentaire… sauf que vous avez plusieurs paramètres. Et cela suffit généralement à décontenancer les gens et à les décontenancer au début.
Sa forme simple:
peut être exprimé comme ceci par récurrence:
Plus fort
Une fois que ces problèmes simples ont été montrés ET réimplémentés dans des tutoriels, vous pouvez donner des exercices un peu plus difficiles (mais très classiques):
- Les chiffres de Fibonacci ,
- Le plus grand commun diviseur ,
- Le problème des 8-reines ,
- Le jeu Les tours de Hanoi ,
- Et si vous avez un environnement graphique (ou pouvez fournir des stubs de code pour celui-ci ou pour une sortie de terminal ou s'ils peuvent déjà le gérer), des choses comme:
- Et pour des exemples pratiques, pensez à écrire:
- un algorithme de traversée d'arbres,
- un simple analyseur d'expression mathématique,
- un jeu de démineur.
Note: Encore une fois, certains d'entre eux ne sont vraiment pas plus difficiles… Ils abordent simplement le problème sous le même angle, ou sous un angle légèrement différent. Mais la pratique rend parfait.
Aides
Une référence
Certaines lectures ne font jamais de mal. Au début, ils se sentiront encore plus perdus. C'est le genre de chose qui pousse sur vous et qui se cache derrière votre tête jusqu'au jour où vous réalisez que vous l'avez enfin. Et puis vous repensez à ces choses que vous lisez. La récursion , la récursion en informatique et les pages de relation de récurrence sur Wikipedia suffiraient pour le moment.
Niveau / profondeur
En supposant que vos étudiants n’ont pas beaucoup d’expérience en codage, fournissez des talons de code. Après les premières tentatives, donnez-leur une fonction d'impression capable d'afficher le niveau de récursivité. Imprimer la valeur numérique du niveau aide.
Le diagramme empilable
Il est également utile d'indenter un résultat imprimé (ou la sortie du niveau), car cela donne une autre représentation visuelle de ce que fait votre programme, en ouvrant et en fermant des contextes de pile, tels que des tiroirs ou des dossiers dans un explorateur de système de fichiers.
Acronymes récursifs
Si votre élève est déjà un peu familiarisé avec la culture informatique, il se peut qu'il utilise déjà des projets / logiciels avec des noms utilisant des acronymes récursifs . C'est une tradition qui existe depuis quelque temps, en particulier dans les projets GNU. Quelques exemples incluent:
Récursif:
- GNU - "GNU's Not Unix"
- Nagios - "Nagios ne va pas insister pour la sainteté"
- PHP - "préprocesseur hypertexte PHP" (et initialement "page d'accueil personnelle")
- Wine - "Le vin n'est pas un émulateur"
- Zile - "Zile Is Lossy Emacs"
Mutuellement récursif:
- HURD - "HIRD de démons remplaçant Unix" (où HIRD est "HURD d'interfaces représentant la profondeur")
Demandez-leur d'essayer de trouver les leurs.
De même, il existe de nombreuses occurrences d'humour récursif, comme la correction de recherche récursive de Google . Pour plus d'informations sur la récursivité, lisez cette réponse .
Pièges et apprentissage ultérieur
Certaines questions avec lesquelles les gens ont généralement du mal et pour lesquelles vous devez connaître les réponses.
Pourquoi, oh mon Dieu pourquoi ???
Pourquoi ferais-tu ça? Une raison valable mais non évidente est qu'il est souvent plus simple d'exprimer un problème de cette façon. Une raison peu évidente, mais évidente, est qu'il faut souvent moins de dactylographie (ne leur donnez pas la sensation d'être si mal pour utiliser simplement la récursivité ...).
Certains problèmes sont définitivement plus faciles à résoudre avec une approche récursive. En règle générale, tout problème que vous pouvez résoudre à l'aide d'un paradigme Divide and Conquer convient à un algorithme de récursion à plusieurs branches.
C'est quoi encore N ??
Pourquoi mon n
ou (quel que soit le nom de votre variable) est différent à chaque fois? Les débutants ont généralement du mal à comprendre ce que sont une variable et un paramètre, et comment les éléments nommés n
dans votre programme peuvent avoir des valeurs différentes. Alors maintenant, si cette valeur est dans la boucle de contrôle ou la récursivité, c'est encore pire! Soyez gentil et n'utilisez pas les mêmes noms de variable partout et indiquez clairement que les paramètres ne sont que des variables .
Conditions de fin
Comment puis-je déterminer mon état final? C'est facile, demandez-leur de dire les étapes à haute voix. Par exemple, pour la factorielle, commencez par 5, puis 4, puis ... jusqu'à 0.
Le diable est dans les détails
Ne parlez pas trop tôt de choses comme l’ optimisation des appels de queue . Je sais, je sais, le coût total de possession est bien, mais ils s'en moquent au début. Donnez-leur un peu de temps pour bien comprendre le processus, de manière à ce qu’il fonctionne pour eux. N'hésitez pas à briser leur monde plus tard, mais donnez-leur une pause.
De même, ne parlez pas directement de la première lecture de la pile d'appels et de sa consommation de mémoire et ... bien ... du débordement de pile . Je donne souvent des leçons particulières à des étudiants qui me montrent des conférences où ils ont 50 diapositives sur tout ce qu'il y a à savoir sur la récursion, alors qu'ils peuvent à peine écrire une boucle correctement à ce stade. Voilà un bon exemple de la façon dont une référence aidera plus tard, mais qui pour l’instant vous confond profondément.
Mais s'il vous plaît, précisez, en temps voulu, qu'il existe des raisons de choisir la voie itérative ou récursive .
Récursion mutuelle
Nous avons vu que les fonctions peuvent être récursives, et même qu’elles peuvent avoir plusieurs points d’appel (8 reines, Hanoi, Fibonacci ou même un algorithme d’exploration pour un dragueur de mines). Mais qu'en est-il des appels mutuellement récursifs ? Commencez par les mathématiques ici aussi. f(x) = g(x) + h(x)
où g(x) = f(x) + l(x)
et h
et l
juste faire des choses.
Commencer par des séries mathématiques facilite l'écriture et la mise en œuvre car le contrat est clairement défini par les expressions. Par exemple, les séquences féminine et masculine de Hofstadter :
Cependant, en termes de code, il convient de noter que la mise en œuvre d'une solution mutuellement récursive conduit souvent à une duplication du code et devrait plutôt être simplifiée en un seul formulaire récursif (Voir La résolution de Chaque puzzle de Sudoku par Peter Norvig .