begin process at 2012 02 10 18:09:37
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Maths & Algorithmes

 > LES PROCÉDURES RÉCURSIVES

LES PROCÉDURES RÉCURSIVES


 Description

La version récursive
void afficher_arbre_recursivement(struct arbre * a,int decalage) {
  int i;
  if (a!=NULL) {
    for (i=0;i<decalage;i++) {
      printf(" ");
    }
    printf("( début affichage noeud %d)\n",a->valeur_noeud);
    afficher_arbre_recursivement(a->fils_gauche,decala ge+1);
    afficher_arbre_recursivement(a->fils_droit,decalag e+1);
    for (i=0;i<decalage;i++) {
      printf(" ");
    }
    printf("( fin affichage noeud %d)\n",a->valeur_noeud);
  }
}

Vers une dérécursivation
Les étapes nécessaires à la dérécursivation sont :

la compréhension de la récursion,
une analyse fine du type de récursion,
le passage à une version dérécursivée.

La compréhension de la récursion
Tout d'abord, on peut vérifier que la procédure est récursive. De plus, on peut s'assurer en la testant qu'elle est correcte.

On peut remarquer qu'elle n'est pas récursive terminale : une fonction (ou une procédure) récursive terminale ne contient qu'un seul appel récursif et il est la dernière instruction de la fonction (ou de la procédure). Il va donc falloir utiliser une pile de données pour dérécursiver la fonction. Avant d'implémenter cette pile, il est préférable d'attendre l'analyse fine de la récursion.

Il peut être intéressant de comprendre la fonction récursive. Celle-ci réalise un affichage des nœuds d'un arbre. Voici une trace d'exécution :

(~/divers/derecursivation)>derecursivation
( début affichage noeud 10)
  ( début affichage noeud 20)
    ( début affichage noeud 0)
    ( fin affichage noeud 0)
    ( début affichage noeud 30)
    ( fin affichage noeud 30)
  ( fin affichage noeud 20)
  ( début affichage noeud 40)
  ( fin affichage noeud 40)
( fin affichage noeud 10)


L'analyse fine de la récursion
Lorsque l'on réalise une analyse plus fine de la récursion, on se rend compte que le bloc d'instructions correspondant à un nœud (à un sous-arbre donné pour être plus précis) est décomposé en deux parties. La première de ces parties est :

    for (i=0;i<decalage;i++) {
      printf(" ");
    }
    printf("( début affichage noeud %d)\n",a->valeur_noeud);

La seconde est :
    for (i=0;i<decalage;i++) {
      printf(" ");
    }
    printf("( fin affichage noeud %d)\n",a->valeur_noeud);

On peut remarquer dans une trace d'exécution que les deux blocs correspondants à ces deux parties de code sont séparés :
(~/divers/derecursivation)>derecursivation
( début affichage noeud 10)
  ( début affichage noeud 20)
    ( début affichage noeud 0)
    ( fin affichage noeud 0)
    ( début affichage noeud 30)
    ( fin affichage noeud 30)
  ( fin affichage noeud 20)
  ( début affichage noeud 40)
  ( fin affichage noeud 40)
( fin affichage noeud 10)


L'effet de cette séparation fait apparaître la nécécessité de stocker dans la pile une variable pouvant prendre deux valeurs : POSITION_DEBUT et POSITION_FIN. Une valeur de POSITION_DEBUT indique que l'on se trouve dans la première partie, une valeur de POSITION_FIN indique que l'on se trouve dans la seconde partie.

La procédure récursive fait varier à chaque appel ses deux paramètres a et decalage. Il est donc nécessaire de les passer tous les deux sur la pile. Dans le cas où la procédure récursive ne modifie qu'un sous-ensemble de ses paramètres, il n'est utile que d'empiler ce sous-ensemble.

Le passage à la version dérécursivée
On sait à présent quels sont les paramètres que l'on aura besoin d'empiler : un pointeur sur le sous-arbre courant, le décalage actuel et la position (pouvant prendre la valeur POSITION_DEBUT ou la valeur POSITION_FIN). On peut à présent programmer les fonctions suivantes :

struct pile * pileCreerVide();,
int pileEstVide(struct pile * p);,
void pileLiberer(struct pile * p);,
void pileEmpiler(struct pile * p,struct arbre * valeur_element,int decalage_element,int position_element);,
void pileDepiler(struct pile *p,struct arbre ** valeur_element,int * decalage_element,int * position_element);.

Voyons à présent la version récursive et la version dérécursivée, et observons les similitudes. void afficher_arbre_recursivement(struct arbre * a,int decalage) {
  int i;
  if (a!=NULL) {
    for (i=0;i<decalage;i++) {
      printf(" ");
    }
    printf("( début affichage noeud %d)\n",a->valeur_noeud);
    afficher_arbre_recursivement(a->fils_gauche,decala ge+1);
    afficher_arbre_recursivement(a->fils_droit,decalag e+1);
    for (i=0;i<decalage;i++) {
      printf(" ");
    }
    printf("( fin affichage noeud %d)\n",a->valeur_noeud);
  }
}

void afficher_arbre_iterativement(struct arbre * a,int decalage) {
  struct pile * p;
  struct arbre * arbre_element;
  int decalage_element;
  int position_element;
  int i;
  p = pileCreerVide();
  if (a!=NULL) {
    pileEmpiler(p,a,decalage,POSITION_DEBUT);
  }
  while (!pileEstVide(p)) {
    pileDepiler(p,&arbre_element,&decalage_element,&po sition_element);
    if (arbre_element!=NULL) {
      if (position_element==POSITION_DEBUT) {
        for (i=0;i<decalage_element;i++) {
          printf(" ");
        }
        printf("( début affichage noeud %d)\n",arbre_element->valeur_noeud);
        pileEmpiler(p,arbre_element,decalage_element,POSIT ION_FIN);
        pileEmpiler(p,arbre_element->fils_droit,decalage_e lement+1,POSITION_DEBUT);
        pileEmpiler(p,arbre_element->fils_gauche,decalage_ element+1,POSITION_DEBUT);
      }
      else {
        for (i=0;i<decalage_element;i++) {
          printf(" ");
        }
        printf("( fin affichage noeud %d)\n",arbre_element->valeur_noeud);
      }
    }
  }
  pileLiberer(p);
}


On notera le renommage des variables dans le cas du programme dérécursivé. Cela n'était pas nécessaire.

    afficher_arbre_recursivement(a->fils_gauche,decala ge+1);
    afficher_arbre_recursivement(a->fils_droit,decalag e+1);

         pileEmpiler(p,arbre_element,decalage_element,POSIT ION_FIN);
        pileEmpiler(p,arbre_element->fils_droit,decalage_e lement+1,POSITION_DEBUT);
        pileEmpiler(p,arbre_element->fils_gauche,decalage_ element+1,POSITION_DEBUT);


On notera d'une part l'inversion entre le fils gauche et le fils droit (afin que le fils gauche soit dépilée en premier) et d'autre part l'empilement du nœud courant, en POSITION_FIN et avant l'empilement des deux fils (afin que la fin de la procédure soit exécutée après que le fils gauche et que le fils droit aient été traités.

La version dérécursivée
void afficher_arbre_iterativement(struct arbre * a,int decalage) {
  struct pile * p;
  struct arbre * arbre_element;
  int decalage_element;
  int position_element;
  int i;
  p = pileCreerVide();
  if (a!=NULL) {
    pileEmpiler(p,a,decalage,POSITION_DEBUT);
  }
  while (!pileEstVide(p)) {
    pileDepiler(p,&arbre_element,&decalage_element,&po sition_element);
    if (arbre_element!=NULL) {
      if (position_element==POSITION_DEBUT) {
        for (i=0;i<decalage_element;i++) {
          printf(" ");
        }
        printf("( début affichage noeud %d)\n",arbre_element->valeur_noeud);
        pileEmpiler(p,arbre_element,decalage_element,POSIT ION_FIN);
        pileEmpiler(p,arbre_element->fils_droit,decalage_e lement+1,POSITION_DEBUT);
        pileEmpiler(p,arbre_element->fils_gauche,decalage_ element+1,POSITION_DEBUT);
      }
      else {
        for (i=0;i<decalage_element;i++) {
          printf(" ");
        }
        printf("( fin affichage noeud %d)\n",arbre_element->valeur_noeud);
      }
    }
  }
  pileLiberer(p);
}

Les fichiers :



 Conclusion

Remerciement toujours à mon plus fidele ami et "maitre" MoonStone alias LeBouffon ( qui n'a rien à voir avec un certain Loiseau de Belgique comme "un " certain tente de supposer :p ) qui m'a aidé à la revision de mes cours, il y'a quelques mois de cela. Que je met aujours'hui ici, comme ça, pour le fun, parce que je l'avais fait sous emmatopiak et que j'ai envie de relancer la machine du laché de codes :p


 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Sources du même auteur

Source avec Zip DESASSEMBLEUR JAVA
Source avec Zip REGEXP EN C SANS LIBRAIRIES
Source avec Zip UN BOT EN C POUR LE IRC AVEC SON BAZOOKA

 Sources de la même categorie

Source avec Zip UN EXAMPLE D'APPLICATION EN CUDA DE L'ALGORITHME DE SCAN POU... par oguzaras
Source avec Zip Source avec une capture CHIFFREMENT DE VIGENERE par lajouad
Source avec Zip Source avec une capture ANALYSE SYNTAXIQUE par lajouad
Source avec Zip Source avec une capture STRUCTURE D'UNE MATRICE PAR LES LISTE LINÉAIRE (NON CONTUGUS... par benzarabel
Source avec Zip Source avec une capture DESSINER UNE ARBRE BINAIRE( MODE CONSOLE): par benzarabel

Commentaires et avis

Aucun commentaire pour le moment.

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Anciennes versions de Borland C++ [ par Totofweb ] Bonjour Où pourrais-je trouver des anciennes versions de Borland C++ (qui permettaient de faire des applications visuelles quand même). J'ai un vie Différence entre les versions de Visual C++ [ par CodeMercury ] Salut,J'aimerai savoir quelles sont les différences entre les versions éducatives, standart, et proffessionnelle de Visual C++.Peut-on programmer libr Différence entre les versions de Visual C++ [ par CodeMercury ] Salut,J'aimerai savoir quelles sont les différences entre les versions éducatives, standart, et proffessionnelle de Visual C++.Peut-on programmer libr question sur les versions de linux [ par boumarsel ] Quelle est la meilleure version de linux adapt&#233;e au developpement et aux bases de donn&#233;es. j'ai actuelement Mandrake 10, c'est vraiment du n fonctions_procedures en C [ par mafiaman42 ] Bonjour a tous, Voila je suis en BTS info et je dois introduire dans un programme principal en C , des fonctions et proc&#233;dures, comment dois je f Comparaison de version [ par drkns ] Bonjour,Je souhaite effectuer une comparaison de deux "version" ex : 10.25.32 000 est il superieur à 10.26.32 000.Aurriez vous une idée sur la manière ODBC et versions de windows... [ par orbb ] Bonjour, j'aimerai savoir si le support de l'odbc est disponible de base dans toutes les versions de windows, et principalement l'odbc v3.xet sinon a versions [ par mogwai93 ] Bonjour osversioninfo permet de récupérer des infos sur le windows installé est-ce qu'il existe un équivalent pour internet explorer et media play [BATCH]Sript en batch nettoyage toutes versions de windows pour poste de travail et serveur [ par greg110774 ] [i]Bonjour à vous, Je recherche des scripts de nettoyage en batch (.bat) pour les versions Windows de XP, Vista, Seven, Windows Server 2003, de même


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 5,320 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales