web-dev-qa-db-fra.com

Raison de l'instruction de retour dans l'appel de fonction récursive

J'avais juste un doute dans ma tête. Le sous-programme suivant (pour rechercher un élément, dans une liste, par exemple) a une instruction de retour à la fin:

list *search_list(list *l, item_type x) {
  if (l == NULL) return(NULL);
  if (l->item == x)
    return(l);
  else
    return( search_list(l->next, x) );
}

Je ne peux pas obtenir la signification de l'instruction de retour à la fin (c'est-à-dire retourner la liste de recherche (l-> suivant, x)). Il serait vraiment utile que quelqu'un puisse expliquer ce concept en utilisant un modèle de pile.

14
user1369975

Une instruction return renvoie une valeur à appelant immédiat du cadre d'appel de la fonction actuelle. En cas de récursivité, cet appelant immédiat peut être une autre invocation de cette même fonction.

Dans la plupart des langues, si vous n'utilisez pas la valeur de retour d'une fonction que vous avez appelée (récursivement ou non), cette valeur de retour est ignorée ou il s'agit d'une erreur diagnostiquable. Dans certains langages, la valeur de retour du dernier appel de fonction est automatiquement réutilisée en tant que valeur de retour de l'appel de fonction en cours, mais ils ne différencient pas les appels de fonction normaux et récursifs.

En supposant que les valeurs de retour inutilisées soient éliminées en silence, si vous aviez écrit le code comme ceci:

list *search_list(list *l, item_type x) {
  if (l == NULL) return(NULL);
  if (l->item == x)
    return(l);
  else
    search_list(l->next, x); // no return!
}

puis search_list renverrait uniquement une valeur définie pour une liste vide (NULL) ou si le premier élément correspond à la valeur que vous recherchez. Dès que la fonction passe dans l'appel récursif, vous ne savez pas quel sera le résultat, car le résultat de l'appel récursif est rejeté.

De plus, vous vous engagez à renvoyer une valeur de votre fonction, mais vous avez un chemin (le récursif) où vous ne spécifiez pas quelle valeur renvoyer. Selon la langue que vous utilisez, cela entraîne généralement un diagnostic obligatoire ou un comportement indéfini (ce qui est un raccourci pour: tout peut arriver et cela peut changer à tout moment sans préavis. Ne tenez personne d'autre que vous-même responsable s'il se trompe) votre présentation la plus importante). Il existe certaines situations où la valeur de retour manquante peut sembler fonctionner, mais cela peut changer la prochaine fois que vous exécutez le programme (avec ou sans recompilation).

19

Deux choses; Renvoyer la liste entière dans le cas où vous trouvez le "x" que vous recherchez ne garantit pas nécessairement l'utilisation de la récursivité, mais cela mis à part, considérez ce qui suit:

Supposons que vous recherchez une valeur de X = "décembre" et que votre liste soit la valeur numérique des mois de l'année, un pointeur sur le mois suivant et les éléments l-> de la liste sont les noms épelés des mois. (Janvier, février, ..., décembre). Vous avez besoin des trois retours pour les résultats possibles. Le premier, return (NULL) est nécessaire si la liste ne contient pas le X que vous recherchez. La seconde, (return (l)) renvoie la liste, dans ce cas, vous indiquant que vous avez trouvé votre "x". Le dernier est l'endroit où le modèle de pile entre en jeu. Les appels successifs à la fonction auraient mis à jour des variables locales (spécifiquement, l-> item) comme ceci:

1: l->item = January
   returns search_list(l->next, x)
2: l->item = February
   returns search_list(l->next, x)
3-11: March, April, May, June, July, August, September, October, November
   all return search_list(l->next, x)
12: l->item = December
  This matches the second if() and returns your list, letting you know you found your search item.
1
panhandel