/***************************************************************************
			       Langage C
				 TP nø3

 Olivier SANNIER
 Denis VANPEPERSTRAETE
 Groupe C
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>

/* ------------------------------------------------------------------------
  D‚finition de la structure noeud qui contient un entier et deux pointeurs
  sur une structure de mˆme type. On pourra ainsi cr‚er un arbre binaire de
  recherche pour des entiers.
-------------------------------------------------------------------------- */
typedef struct NOEUD {
    int valeur;
    struct NOEUD *filsg, *filsd;
 } noeud, *pnoeud;


 /*--------------------------------------------------------------------------
   void pasdarbre(void)

   Cette fonction affiche un message informant l'utilisateur que l'arbre
   sur lequel il voulait travailler est vide. Elle ne doit ˆtre appel‚e
   que dans ce cas pr‚cis puisqu'elle ne fait aucune v‚rification.

   Entr‚e -> rien
   Sortie -> rien
--------------------------------------------------------------------------*/
 void pasdarbre(void)
 {
   textattr(LIGHTRED+BLINK);
   cprintf("                             L'arbre est vide  !!!");
   textattr(LIGHTGRAY);
 }

/*--------------------------------------------------------------------------
   void placer_nombre(int nb, pnoeud *pere)

   Cette fonction est charg‚e d'ajouter un ‚l‚ment … un arbre binaire de
   recherche. Pour cela, elle v‚rifie que le noeud origine qu'on lui a pass‚
   n'est pas NULL. Si c'est le cas, il faut modifier ce pointeur pour qu'il
   pointe sur l'‚l‚ment … ajouter. Sinon, si la valeur … ajouter est
   sup‚rieure … la valeur du noeud alors si ce noeud … un fils droit, la
   fonction est relanc‚e avec pour noeud racine le fils droit. Sinon, un
   ‚l‚ment est ins‚r‚ en tant que fils droit du noeud.
   Il en va de mˆme si la valeur est inf‚rieure … la valeur du noeud.
   Si un ‚l‚ment existe d‚ja, il ne sera pas ajout‚ en plus.

   Entr‚e -> nb   : nombre … ajouter
	     pere : noeud sur lequel effectuer les v‚rifications, pass‚ par
		    paramŠtre
   Sortie -> rien
--------------------------------------------------------------------------*/
void placer_nombre(int nb, pnoeud *pere) {
  if (*pere != NULL)     // si le noeud n'est pas NULL
  {

    if (nb>(*pere)->valeur)              // si la valeur est sup‚rieure
    {
      if ((*pere)->filsd != NULL)        // si le fils droit existe
	placer_nombre(nb, &((*pere)->filsd));  // on relance avec ce fils
      else
      {                                        // sinon on ajoute l'‚l‚ment
	(*pere)->filsd = (pnoeud)malloc(sizeof(noeud));
	(*pere)->filsd->valeur = nb;
	(*pere)->filsd->filsg=NULL;
	(*pere)->filsd->filsd=NULL;
      }
    }
    else                                   // sinon
    {
      if (nb<(*pere)->valeur)              // si la valeur est inf‚rieure
      {
	if ((*pere)->filsg != NULL)      // si le fils gauche existe
	  placer_nombre(nb, &((*pere)->filsg));  // on relance avec ce fils
	else
	{                                       // sinon on ajoute un ‚l‚ment
	  (*pere)->filsg = (pnoeud)malloc(sizeof(noeud));
	  (*pere)->filsg->valeur = nb;
	  (*pere)->filsg->filsg=NULL;
	  (*pere)->filsg->filsd=NULL;
	}
      }
    }
  }
  else
  {             // sinon on ajoute un ‚l‚ment qui est forc‚ment une feuille
    *pere = (pnoeud)malloc(sizeof(noeud));
    (*pere)->filsg=NULL;
    (*pere)->filsd=NULL;
    (*pere)->valeur=nb;
  }
}

/*--------------------------------------------------------------------------
   void repete(char *chaine, char cara, int nb)

   Cette fonction place dans chaine une suite de nb caractŠres identiques
   et dont la valeur est celle de cara.
   Cette fonction n'est utilis‚e que par la fonction affiche. Elle permet
   de r‚aliser un affichage simili-graphique sans la moindre instruction
   de d‚placement du curseur puisque les d‚placements sont provoqu‚s par
   des r‚p‚titions.

   Entr‚e -> chaine : un pointeur sur un tableau de caractŠres.
	     cara   : caractŠre … r‚p‚ter
	     nb     : nombre de r‚p‚titions … effectuer.
   Sortie -> rien
--------------------------------------------------------------------------*/
void repete(char *chaine, char cara, int nb)
{
  int i;
  for(i=0;i<nb;i++)
    chaine[i]=cara;
  chaine[nb]='\0';           // terminaison de la chaine
}


/*--------------------------------------------------------------------------
  void afficher(pnoeud tete, int profondeur)

   Cette fonction affiche un arbre binaire sous forme pseudo graphique
   verticale. Pour cela, elle affiche la valeur du noeud … une certaine
   position sur la ligne. Cette position d‚pend directement de la profondeur
   du noeud en cours de traitement.
   Pour effectuer ce positionnement, elle fait appel … la fonction repete
   qui lui fournit des chaines contenant 4*profondeur espaces.

   Entr‚e -> tete       : un pointeur sur le noeud qui doit ˆtre affich‚.
	     profondeur : la profondeur du noeud tete
   Sortie -> rien
--------------------------------------------------------------------------*/
void afficher(pnoeud tete, int profondeur)
{
char chaine[255], blanc[255];

  if (tete==NULL)
    pasdarbre();
  else
  {

    if (profondeur)                  // si on est sous la racine
      strcpy(chaine, "|");        // on doit mettre un trait
    else
      chaine[0] = 0;               // sinon on a rien
    if (profondeur>1)      // si on a pass‚ les trois premiers noeuds, on
    {                         // doit d‚caler l'affichage
      repete(blanc, ' ', (profondeur-1)*4);
      strcat(chaine, blanc);
      strcat(chaine, "|");
    }
    if (profondeur)        // si on n'est pas … la racine, on ajoute un lien
      strcat(chaine, "___");
    textcolor(CYAN);
    cprintf("%s", chaine);   // on affiche la chaine de positionnement
    textcolor(WHITE);
    cprintf("%d\r\n", tete->valeur);  // on affiche le noeud
    if (tete->filsg != NULL)               // et on recommence ‚ventuellement
      afficher(tete->filsg, profondeur +1);  // avec le fils gauche

    if (tete->filsd != NULL)           // et on recommence ‚ventuellement
      afficher(tete->filsd, profondeur+1);  // avec le fils droit
  }
}

/*--------------------------------------------------------------------------
   void libre(pnoeud tete)

   Cette fonction libŠre l'espace m‚moire occup‚ par un arbre binaire.

   Entr‚e -> tete : un pointeur sur l'arbre qui doit ˆtre lib‚r‚.
   Sortie -> rien
--------------------------------------------------------------------------*/
void libre(pnoeud tete)
{
  if (tete!=NULL)
  {
    if (tete->filsd != NULL)
      libre(tete->filsd);
    if (tete->filsg != NULL)
      libre(tete->filsg);

    free(tete);
  }
}

/*--------------------------------------------------------------------------
   void affpre(pnoeud debut)

   Cette fonction r‚alise un affichage pr‚fix‚ de l'arbre pass‚ en paramŠtre.
   Il s'agit d'une fonction r‚cursive, c'est … dire qu'elle n'affiche qu'un
   noeud puis se rappelle si un fils existe.

   Entr‚e -> debut : un pointeur sur le noeud qui doit ˆtre affich‚.
   Sortie -> rien
--------------------------------------------------------------------------*/
void affpre(pnoeud debut)
{
  if (debut==NULL)
    pasdarbre();
  else
  {
    printf("%4d", debut->valeur);
    if (debut->filsg!=NULL)
      affpre(debut->filsg);
    if (debut->filsd!=NULL)
      affpre(debut->filsd);
  }
}

/*--------------------------------------------------------------------------
   void affinf(pnoeud debut)

   Cette fonction r‚alise un affichage infix‚ de l'arbre pass‚ en paramŠtre.
   Il s'agit d'une fonction r‚cursive, c'est … dire qu'elle se rappelle si le
   fils gauche existe puis affiche la valeur du noeud puis se rappelle si
   le fils droit existe.

   Entr‚e -> debut : un pointeur sur le noeud qui doit ˆtre affich‚.
   Sortie -> rien
--------------------------------------------------------------------------*/
void affinf(pnoeud debut)
{
  if (debut==NULL)
    pasdarbre();
  else
  {
    if (debut->filsg!=NULL)
      affinf(debut->filsg);
    printf("%4d", debut->valeur);
    if (debut->filsd!=NULL)
      affinf(debut->filsd);
  }
}

/*--------------------------------------------------------------------------
   void affpost(pnoeud debut)

   Cette fonction r‚alise un affichage postfix‚ de l'arbre pass‚ en
   paramŠtre. Il s'agit d'une fonction r‚cursive, c'est … dire qu'elle se
   rappelle si le fils gauche existe puis se rappelle si le fils droit
   existe puis enfin affiche la valeur du noeud

   Entr‚e -> debut : un pointeur sur le noeud qui doit ˆtre affich‚.
   Sortie -> rien
--------------------------------------------------------------------------*/
void affpost(pnoeud debut)
{
  if (debut==NULL)
    pasdarbre();
  else
  {
    if (debut->filsg!=NULL)
      affpost(debut->filsg);
    if (debut->filsd!=NULL)
      affpost(debut->filsd);
    printf("%4d", debut->valeur);
  }
}

/*--------------------------------------------------------------------------
   int recherche(pnoeud debut, int nb_rech)

   Cette fonction recherche un nombre dans un arbre. Si la valeur cherch‚e
   est identique … la valeur du noeud, la recherche est finie, on renvoie
   1. Sinon, la recherche est relanc‚e si un fils gauche existe et que la
   valeur voulue est inf‚rieure … la valeur du noeud.
   Sinon, la recherche est relanc‚e avec le fils droit … condition que
   celui-ci existe.

   Entr‚e -> debut   : un pointeur sur le noeud dans lequel chercher.
	     nb_rech : le nombre cherch‚
   Sortie -> 0       : ‚l‚ment non trouv‚
	     1       : ‚l‚ment pr‚sent dans l'arbre
--------------------------------------------------------------------------*/
int recherche(pnoeud debut, int nb_rech)
{
  if (debut==NULL)
    pasdarbre();
  else
  {
    if (debut->valeur==nb_rech)    // si la valeur est ‚gale
      return 1;
    else
    {                          // sinon on relance ‚ventuellement
      if ((debut->filsg!=NULL)&&(nb_rech<debut->valeur))
	return recherche(debut->filsg, nb_rech);
      else
	if (debut->filsd!=NULL)
	  return recherche(debut->filsd, nb_rech);
    }

  }
  return 0;
}

/*--------------------------------------------------------------------------
   void afftout(pnoeud debut)

   Cette fonction pr‚sente l'affichage des trois types suivant :
   pr‚fix‚, infix‚ et postfix‚.
   Elle ne le fait qu'… la condition que l'arbre existe.

   Entr‚e -> debut : un pointeur sur l'arbre … afficher.
   Sortie -> rien
--------------------------------------------------------------------------*/
void afftout(pnoeud debut)
{
  if (debut!=NULL)
  {
    printf("\nOrdre pr‚fix‚ :\n");
    affpre(debut);
    printf("\nOrdre infix‚ :\n");
    affinf(debut);
    printf("\nOrdre postfix‚ :\n");
    affpost(debut);
  }
  else
    pasdarbre();
}

/*--------------------------------------------------------------------------
   void affligne(pnoeud debut, int deb, int fin, int profondeur)

   Cette fonction r‚alise un affichage "graphique" d'un arbre. Pour cela,
   elle se place au milieu de la zone d‚finie par deb et fin pour y afficher
   la valeur du noeud actuel. Si ce noeud a un fils, elle affiche le lien
   vers ce fils puis relance l'affichage pour ce fils avec un intervalle
   correspondant … la moiti‚ de l'intervalle pr‚c‚dent.
   Le lien est mod‚lis‚ de la fa‡on suivante :
	  nb
	  |_______
		  |

   Entr‚e -> debut      : un pointeur sur le noeud … afficher.
	     deb        : colonne de d‚but (1 - 80)
	     fin        : colonne de fin (deb - 80)
	     profondeur : profondeur du noeud dans l'arbre (uniquement
			  utilis‚ pour pouvoir dessiner les liaisons)
   Sortie -> rien
--------------------------------------------------------------------------*/
void affligne(pnoeud debut, int deb, int fin, int profondeur)
{
char ligne[80];     // ligne pour les lien

  if (debut!=NULL)    // si j'ai un arbre
  {
    gotoxy(deb+(fin-deb)/2, (profondeur*3)+1);
    textcolor(WHITE);
    cprintf("%d", debut->valeur);     // affichage de la valeur
    textcolor(LIGHTGRAY);
    if (debut->filsg!=NULL)       // si le fils gauche existe
    {
      repete(ligne, '_', (fin-deb)/4);   // mise en place du lien graphique
      gotoxy(deb+ (fin-deb)/4+1, (profondeur*3)+2);
      printf("%s|", ligne);
      gotoxy(deb+ (fin-deb)/4, (profondeur*3)+3);
      printf("|");
      affligne(debut->filsg, deb, deb+(fin-deb)/2, profondeur+1); // relance
    }
    if (debut->filsd!=NULL)       // si le fils droit existe
    {
      repete(ligne, '_', (fin-deb)/4);   // mise en place du lien graphique
      gotoxy(deb +(fin-deb)/2, (profondeur*3)+2);
      printf("|%s", ligne);
      gotoxy(deb+3*(fin-deb)/4, (profondeur*3)+3);
      printf("|");
      affligne(debut->filsd, deb+(fin-deb)/2, fin, profondeur+1); // relance
    }
  }
  else
    pasdarbre();
}

/*--------------------------------------------------------------------------
   void supprime(pnoeud *deb, int nb)

   Cette fonction a pour r“le de supprimer un ‚l‚ment dans un arbre.
   Pour cela, elle emploie le principe propos‚ dans l'‚nonc‚ du TD :
   On recherche l'‚l‚ment … supprimer.
   Si celui-ci existe alors :
     Si c'est une feuille, on fait pointer le lien de son pŠre sur NULL
     Sinon :
       Si l'‚l‚ment n'a qu'un fils, ce fils le remplace.
       Sinon On recherche l'‚l‚ment le plus grand du sous arbre gauche dont
	     l'‚l‚ment … supprimer est racine. On remplace l'‚l‚ment
	     … supprimer par ce Max. Il faut donc maintenant refaire les
	     liens qui pointaient sur Max.
	     Donc :
	     Si Max est une feuille (pas de fils gauche) alors :
	       On fait pointer le lien de son pŠre sur NULL.
	     Sinon
	       On fait pointer le lien de son pŠre sur son fils (gauche
	       forc‚ment car ‚tant le plus grand, il n'a pas de fils droit)

   Dans tous les cas, il ne faut pas oublier de lib‚rer la m‚moire pr‚c‚-
   demment utilis‚e par l'‚l‚ment que l'on vient de supprimer.

   Entr‚e -> deb : un pointeur sur la racine de l'arbre, pass‚ par paramŠtre
		   car la racine peut ˆtre modifi‚e.
	     nb  : la valeur de l'‚l‚ment … supprimer.
   Sortie -> rien
--------------------------------------------------------------------------*/
void supprime(pnoeud *deb, int nb)
{
pnoeud peresuppr, suppr, *lien, peremax, max;

  suppr=*deb;
  peresuppr=NULL;
  // recherche de l'‚l‚ment … supprimer et de son pere
  while ((suppr!=NULL) &&(suppr->valeur!=nb))
  {
    peresuppr=suppr;
    if (suppr->valeur > nb)
      suppr=suppr->filsg;
    else
      suppr=suppr->filsd;
  }

  if (suppr!=NULL)                     // si cet ‚l‚ment existe
  {
    if (peresuppr!=NULL)      // si le pŠre existe alors
    {
      if (suppr->valeur > peresuppr->valeur)  // on trouve le cot‚ … modifier
	lien = &(peresuppr->filsd);          // chez le parent de cet ‚l‚ment
      else
	lien = &(peresuppr->filsg);
    }
    else                     // sinon on doit modifier la racine de l'arbre
      lien = deb;

    // cette affectation est faite pour ‚viter d'avoir … refaire ce test
    // … chaque fois qu'on voudra modifier le lien de peresuppr qui pointait
    // sur suppr. Ainsi, on a juste … modifier la valeur de *lien.

    if ((suppr->filsg==NULL)&&(suppr->filsd==NULL))   // si c'est une feuille
      *lien = NULL;    // on annule bon cot‚ du parent
    else                                             // sinon
    {
      if (suppr->filsg==NULL)         // si pas de fils gauche
	*lien=suppr->filsd;  // on fait pointer le parent sur le fils restant
      else
      {
	if (suppr->filsd==NULL)     // si pas de fils droit
	  *lien=suppr->filsg;// on fait pointer le parent sur le fils restant
	else                       // si deux fils
	{
    // r‚cup‚ration de l'‚l‚ment max et de son pŠre dans le sous-arbre gauche
	  max=suppr->filsg;
	  peremax=suppr;
	  while (max->filsd!=NULL)
	  {
	    peremax=max;
	    max=max->filsd;
	  }

	  *lien=max;          // remplacement par le plus grand

	  if (peremax!=suppr) // si on a effectivement pu touver un max
	  {
	    if (max->filsg==NULL)      // si pas de fils gauche pour max
	      peremax->filsd=NULL;    // alors pas de fils droit pour le pere
	    else
	     peremax->filsd=max->filsg;  // sinon lien entre pŠre et suivant

 // mise en place des liens pour que max prenne sa place
 // si on effectivement trouv‚ un max (on a avanc‚ dans l'arbre) alors,
 // le fils gauche de max pointe sur le fils gauche de l'‚l‚ment supprim‚
 // ceci ‚vite de provoquer un bouclage de l'‚l‚ment max sur lui-mˆme.
	    max->filsg=suppr->filsg;
	  }
// dans tous les cas, le fils droit est le mˆme que l'‚l‚ment … supprimer.
	  max->filsd=suppr->filsd;
	}
      }
    }
    free(suppr);                        // lib‚ration de l'‚l‚ment supprim‚
  }
  else
    printf("\nEl‚ment … supprimer introuvable");

}

/*--------------------------------------------------------------------------
   pnoeud recur_copie(pnoeud abr1)

   Cette fonction est la partie r‚cursive de la fonction de copie d'arbre
   binaire de recherche. Elle est appel‚e par la fonction copie qui a pris
   soin de lib‚rer l'arbre dans lequel elle va copier l'arbre construit ici.
   La m‚thode employ‚e est la suivante :
     on alloue on nouvel ‚l‚ment dans abr2
     il prend la valeur de l'‚l‚ment corespondant dans abr1.
     pour l'instant, ses deux pointeurs sont mis … NULL.
     Si abr1 … un fils gauche, alors le fils gauche de abr2 est ‚gal
       au r‚sultat de l'appel … recur_copie avec comme paramŠtre le fils
       gauche de abr1.
     Si abr1 … un fils droit, alors le fils droit de abr2 est ‚gal
       au r‚sultat de l'appel … recur_copie avec comme paramŠtre le fils
       droit de abr1.
     On retourne alors comme r‚sultat un pointeur sur l'‚l‚ment que l'on
     vient d'allouer. Ainsi, lors du d‚pilement des fonctions, les liens
     seront mis en place correctement.

   Entr‚e -> abr1 : un pointeur sur la racine de l'arbre source
   Sortie -> un pointeur sur l'‚lement allou‚ pour le nouvel arbre
--------------------------------------------------------------------------*/
pnoeud recur_copie(pnoeud abr1)
{
pnoeud abr2;

  abr2=(pnoeud)malloc(sizeof(noeud));
  (abr2)->valeur=abr1->valeur;
  (abr2)->filsg=NULL;
  (abr2)->filsd=NULL;

  if (abr1->filsg!=NULL)
    (abr2)->filsg=recur_copie(abr1->filsg);

  if (abr1->filsd!=NULL)
    (abr2)->filsd=recur_copie(abr1->filsd);

  return abr2;
}

/*--------------------------------------------------------------------------
   int copie(pnoeud abr1, pnoeud *abr2)

   Cette fonction est la fonction englobante pour recur_copie.
   Elle permet de passer un arbre source et un arbre destination tout en
   sachant trŠs bien que l'arbre destination sera d‚truit par cette fonction.

   Entr‚e -> abr1 : un pointeur sur la racine de l'arbre source.
	     abr2 : un pointeur pass‚ par paramŠtre sur la racine de l'arbre
		    de destination.
   Sortie -> 0    : problŠme lors de la copie (arbre source vide).
	     1    : copie r‚ussie.
--------------------------------------------------------------------------*/
int copie(pnoeud abr1, pnoeud *abr2)
{
  if (abr1!=NULL)
  {
    libre(*abr2);
    *abr2=recur_copie(abr1);
    return 1;
  }
  else
  {
    pasdarbre();
    return 0;
  }
}

/*--------------------------------------------------------------------------
   int compte(pnoeud deb)

   Cette fonction compte le nombre d'‚l‚ments pr‚sents dans l'arbre dont
   la racine est pass‚e en paramŠtre.
   Il s'agit d'une fonction r‚cursive. Elle procŠde la maniŠre suivante :
   Une variable locale retour est mise … z‚ro.
   Si l'arbre est vide, on renvoie 0.
   Sinon Si le noeud … un fils gauche, on ajoute … retour le nombre
	    d'‚l‚ments pr‚sents dans le sous arbre gauche.
	 Si le noeud … un fils droit, on ajoute … retour le nombre
	    d'‚l‚ments pr‚sents dans le sous arbre droit.
	 Puis on renvoie retour+1 car le nombre d'‚l‚ments du sous arbre
	 actuel c'est la somme du nombre d'‚l‚ments de ses sous-arbre … qui
	 il faut ajouter un pour compter l'‚l‚ment racine.

   Entr‚e -> deb : un pointeur sur la racine de l'arbre dans lequel compter.
   Sortie -> nombre d'‚l‚ments dans l'arbre
--------------------------------------------------------------------------*/
int compte(pnoeud deb)
{
int retour=0;

  if (deb==NULL)
    return 0;
  else
  {
    if (deb->filsg!=NULL)
      retour+=compte(deb->filsg);
    if (deb->filsd!=NULL)
      retour+=compte(deb->filsd);
    return retour+1;
  }
}

/*--------------------------------------------------------------------------
   int comptefeuilles(pnoeud deb)

   Cette fonction compte le nombre de feuilles dans un arbre.
   Comme la fonction compte, elle est r‚cursive mais applique un principe
   un peu diff‚rent :
   On initialise la variable de retour … 0.
   Si l'arbre est vide, on renvoie 0
   Sinon Si le noeud n'a pas de fils, on renvoie 1. En effet, on vient de
	 trouver 1 feuille dans ce sous arbre constitu‚ d'un ‚l‚ment.
	 Si le noeud … un fils gauche, on ajoute … retour le nombre
	    de feuilles du sous arbre gauche.
	 Si le noeud … un fils droit, on ajoute … retour le nombre
	    de feuilles du sous arbre droit.
	 On renvoie alors ce nombre de feuilles.

   Entr‚e -> deb : un pointeur sur la racine de l'arbre dans lequel compter.
   Sortie -> nombre de feuilles dans l'arbre
--------------------------------------------------------------------------*/
int comptefeuilles(pnoeud deb)
{
  int retour=0;

  if (deb==NULL)
    return 0;
  else
  {
    if ((deb->filsd==NULL)&&(deb->filsg==NULL))
      return 1;
    else
    {
      if (deb->filsg!=NULL)
	retour+=comptefeuilles(deb->filsg);
      if (deb->filsd!=NULL)
	retour+=comptefeuilles(deb->filsd);
      return retour;
    }
  }

}

/*--------------------------------------------------------------------------
   int recur_profondeur(pnoeud deb, int profond)

   Cette fonction est la partie r‚cursive de la fonction de calcul de la
   pronfondeur d'un arbre.
   Elle initialise deux variables gauche et droite … 0. Ce sont respecti-
   vement les valeurs de profondeurs des sous arbre gauche et droit de la
   racine pass‚e en paramŠtre.

   Si l'arbre est vide, on retourne 0
   Sinon, si la racine n'a pas de fils, on retourne la pronfondeur de cette
	  racine. En effet, la pronfondeur atteinte est bien celle de ce
	  noeud.
	  sinon, on affecte … gauche la profondeur du sous arbre gauche
	  et on affecte … droite la profondeur du sous arbre droit.

	  On teste alors la plus grande valeur de profondeur entre droite
	  et gauche afin de la renvoyer.

   Entr‚e -> deb     : un pointeur sur la racine d'un sous arbre.
	     profond : la profondeur de la racine dans l'arbre entier
   Sortie -> nombre de feuilles dans l'arbre
--------------------------------------------------------------------------*/
int recur_profondeur(pnoeud deb, int profond)
{
int gauche=0, droite=0;

  if (deb==NULL)
    return 0;
  else
  {
    if ((deb->filsg==NULL) && (deb->filsd==NULL))
      return profond;
    else
    {
      if (deb->filsg!=NULL)
	gauche+= recur_profondeur(deb->filsg, profond+1);
      if (deb->filsd!=NULL)
	droite+= recur_profondeur(deb->filsd, profond+1);

      if (droite>gauche)
	return droite;
      else
	return gauche;
    }
  }
}

/*--------------------------------------------------------------------------
   int profondeur(pnoeud deb)

   Cette fonction englobe recur_profondeur afin de permettre … l'utilisateur
   de ne pas se soucier de mettre une valeur convenable dans le deuxiŠme
   paramŠtre. Ici, on met car on considŠre que la profondeur de l'‚l‚ment
   racine d'un arbre est 1

   Entr‚e -> deb     : un pointeur sur la racine d'un sous arbre.
   Sortie -> nombre de feuilles dans l'arbre
--------------------------------------------------------------------------*/
int profondeur(pnoeud deb)
{
  return recur_profondeur(deb, 1);
}

/*--------------------------------------------------------------------------
   void main (void)

   C'est la fonction principale, elle gŠre le menu proposant les diff‚rentes
   possibilit‚s afin d'essayer les fonctions demand‚es dans ce TD.

   Entr‚e -> rien.
   Sortie -> rien.
--------------------------------------------------------------------------*/
void main (void){
  pnoeud arbre[2];
  char cara;
  int nombre, arbreactuel=0;

  arbre[0]=arbre[1]=NULL;

  do
  {
    clrscr();
    textcolor(GREEN);
    cprintf("                    --- Arbre binaire de recherche ---\r\n\r\n");
    textcolor(LIGHTGRAY);
    cprintf("0 : Changer d'arbre binaire\r\n\r\n");
    textcolor(YELLOW);
    cprintf("PremiŠre partie\r\n");
    textcolor(LIGHTGRAY);
    cprintf("1 : Ajouter un nombre\r\n");
    cprintf("2 : Afficher l'arbre actuel (graphique colonne)\r\n");
    cprintf("3 : Afficher l'arbre actuel (ordre pr‚fix‚)\r\n");
    cprintf("4 : Afficher l'arbre actuel (ordre infix‚)\r\n");
    cprintf("5 : Afficher l'arbre actuel (ordre postfix‚)\r\n");
    cprintf("6 : Afficher les ordres pr‚fix‚, infix‚ et postfix‚\r\n");
    cprintf("7 : Recherche d'un nombre\r\n\r\n");
    textcolor(YELLOW);
    cprintf("DeuxiŠme partie\r\n");
    textcolor(LIGHTGRAY);
    cprintf("8 : Afficher l'arbre actuel (graphique ligne)\r\n");
    cprintf("9 : Supprimer un ‚l‚ment de l'arbre actuel\r\n");
    cprintf("A : Copie de l'arbre actuel dans l'autre arbre\r\n");
    cprintf("B : Nombre d'‚l‚ments de l'arbre actuel\r\n");
    cprintf("C : Nombre de feuille de l'arbre actuel\r\n");
    cprintf("D : Nombre de niveaux de l'arbre actuel\r\n");
    cprintf("q : Quitter\r\n");
    textcolor(BROWN);
    cprintf("\r\nVous travaillez sur l'arbre %d", arbreactuel+1);
    textcolor(CYAN);
    cprintf("\r\nVotre choix : ");
    fflush(0);
    cara=toupper(getche());
    clrscr();
    switch(cara)
    {
      case '0' : arbreactuel=1-arbreactuel;
		 break;
      case '1' : printf("\nValeur … ajouter ? ");                    // ajout
		 scanf("%d", &nombre);
		 placer_nombre(nombre, &arbre[arbreactuel]);
		 break;
      case '2' : printf("\n");                          // affichage vertical
		 afficher(arbre[arbreactuel], 0);
		 getch();
		 break;
      case '3' : printf("\nOrdre pr‚fix‚ :\n");          // affichage pr‚fix‚
		 affpre(arbre[arbreactuel]);
		 getch();
		 break;
      case '4' : printf("\nOrdre infix‚ :\n");            // affichage infix‚
		 affinf(arbre[arbreactuel]);
		 getch();
		 break;
      case '5' : printf("\nOrdre postfix‚ :\n");        // affichage postfix‚
		 affpost(arbre[arbreactuel]);
		 getch();
		 break;
      case '6' : printf("\n");                         // affichage des trois
		 afftout(arbre[arbreactuel]);
		 getch();
		 break;
      case '7' : printf("\nValeur … rechercher ? ");             // recherche
		 scanf("%d", &nombre);
		 if (recherche(arbre[arbreactuel], nombre))
		   printf("\nLe nombre %d a ‚t‚ trouv‚", nombre);
		 else
		   printf("\nLe nombre %d n'a pas ‚t‚ trouv‚", nombre);
		 getch();
		 break;
      case '8' : affligne(arbre[arbreactuel],1,80,0); // affichage horizontal
		 getch();
		 break;
      case '9' : printf("\nValeur … supprimer ? ");            // suppression
		 scanf("%d", &nombre);
		 if (recherche(arbre[arbreactuel], nombre))
		   supprime(&arbre[arbreactuel], nombre);
		 else
		   printf("\nLe nombre %d n'est pas dans l'arbre", nombre);
		 getch();
		 break;
      case 'A' : printf("Copie en cours...\n");                      // copie
		 if (copie(arbre[arbreactuel], &(arbre[1-arbreactuel])))
		   printf("Copie effectu‚e.\n");
		 else
		   printf("La copie a echou‚e.\n");
		 getch();
		 break;
      case 'B' : printf("Nombre d'‚l‚ments : %d",        // nombre d'‚l‚ments
			   compte(arbre[arbreactuel]));
		 getch();
		 break;
      case 'C' : printf("Nombre de feuilles : %d",      // nombre de feuilles
			   comptefeuilles(arbre[arbreactuel]));
		 getch();
		 break;
      case 'D' : printf("Nombre de niveaux : %d",        // nombre de niveaux
			   profondeur(arbre[arbreactuel]));
		 getch();
		 break;
    }
  } while ((cara!='Q') && (cara!=27));

  libre(arbre[0]);
  libre(arbre[1]);
}

