4.8. Algorithmes et programmes
sur les arbres binaires


Plan du chapitre:

1. Implantations des 4 algorithmes de parcours


2.  Arbres binaires de recherche




 

1. Implantations des 4 algorithmes de parcours

Implantation de chacun des trois parcours en profondeur par la gauche définissant un ordre implicite (préfixé, infixé, postfixé) sur l'affichage et le traitement des données contenues dans l'arbre. Chaque type de parcours est un cas particulier du parcours général. Nous terminons par le parcours en largeur avec une file Fifo.

Nous allons implanter en Delphi les  3 algorithmes sous forme de procédures récursives. Nous supposons que les informations stockées dans un noeud sont du type chaîne de caractère (string), le traitement consistera ici à écrire le contenu de la string d'un noeud lorsqu'il est parcouru.
 

1.1 Implantations avec variables dynamique et classe

Nous proposons deux implantation possibles que le lecteur testera sur sa machine

Implantation en Delphi avec des variables dynamiques  :

type
    parbre = ^arbre;
    arbre = record
                  info : string ;
                  filsG, filsD: parbre
           end;

Implantation en Delphi avec une classe  :

interface
// dans cette classe tous les champ sont publics afin de simplifier l'écriture
type
   TreeBin = class
      private
         procedure FreeRecur( x :TreeBin ) ;
      public
         Info : string;
         filsG , filsD : TreeBin;
         constructor CreerTreeBin(s:string);overload;
         constructor CreerTreeBin(s:string; fg , fd : TreeBin);overload;
         destructor Liberer;
    end;

implementation
{--------------------   Méthodes privé -------------------------}
procedure TreeBin.FreeRecur ( x : TreeBin ) ;
 // parcours postfixe pour détruire les objets de l'arbre x
begin
  FreeRecur( x.filsG );
  FreeRecur( x.filsD );
  x.Free
end;

{--------------------   Méthodes public -------------------------}
constructor TreeBin.CreerTreeBin(s:string);
 begin
     self.info := s;
     self.filsG := nil;
     self.filsD := nil;
 end;

 constructor TreeBin.CreerTreeBin(s : string ; fg, fd : TreeBin);
 begin
     self.info := s;
     self.filsG := fg;
     self.filsD := fd;
 end;

destructor TreeBin.Liberer;
 // la destruction de tout l'arbre :
begin
   FreeRecur (self) ;
   self := nil;
end;

end.

Nous prenons comme exemple sur lequel appliquer les 4 algorithmes, l'arbre binaire  X suivant (chaque noeud a une info de type caractère stocké dans une string) :
 
=

Remonter



1.2 Implantation du parcours en préordre

Algorithme de parcours en pré-ordre : (ordre préfixé)
parcourir ( Arbre )
si Arbre ¹Æ  alors
   Traiter-1 (info(Arbre.Racine)) ;
   parcourir ( Arbre.filsG ) ;
   parcourir ( Arbre.filsD ) ;
Fsi


La procédure écrirera succsessivement : abdecf

Préordre en Delphi avec les variables dynamiques  :

procedure prefixe (f : parbre);
  begin
    if f <> nil then
      with f^ do
        begin
          write(info);
          prefixe( filsG );
          prefixe( filsD )
        end
  end;

Préordre en Delphi avec la classe  :

interface
type
   TreeBin = class
      private
         procedure FreeRecur( x :TreeBin ) ;
         procedure PreOrdre ( x : TreeBin);
      public
         Info : string;
         filsG , filsD : TreeBin;
         constructor CreerTreeBin(s:string);overload;
         constructor CreerTreeBin(s:string; fg , fd : TreeBin);overload;
         destructor Liberer;
         procedure Prefixe;
    end;

implementation
{--------------------   Méthodes privé -------------------------}
procedure TreeBin.PreOrdre ( x : TreeBin ) ;
 // parcours préfixé d'un arbre x
begin 
 if x<>nil then
 begin

   write(
x.info);
   PreOrdre( x.filsG );
   PreOrdre( x.filsD ) 
 end
end;
//autres méthodes ......

{--------------------   Méthodes public -------------------------}
procedure Prefixe;
// parcours préfixé de l'objet
begin
  PreOrdre( self );
end;
//autres méthodes ......

end.

Remonter



1.3 Implantation du parcours en postordre

Algorithme de parcours en post-ordre : (ordre postfixé)
parcourir ( Arbre )
si Arbre ¹ Æ  alors
   parcourir ( Arbre.filsG ) ;
   parcourir ( Arbre.filsD ) ;
   Traiter-3 (info(Arbre.Racine)) ;
Fsi


La procédure écrirera succsessivement : debfca

Postordre en Delphi avec les variables dynamiques  :

procedure postfixe (f : parbre);
  begin
    if f <> nil then
      with f^ do
        begin
          postfixe( filsG );
          postfixe( filsD );
          write(info)
        end
  end;

Postordre en Delphi avec la classe  :

interface
type
   TreeBin = class
      private
         procedure FreeRecur( x :TreeBin ) ;
         procedure PreOrdre ( x : TreeBin);
         procedure PostOrdre ( x : TreeBin);
      public
         Info : string;
         filsG , filsD : TreeBin;
         constructor CreerTreeBin(s:string);overload;
         constructor CreerTreeBin(s:string; fg , fd : TreeBin);overload;
         destructor Liberer;
         procedure Prefixe;
         procedure Postfixe;
    end;

implementation
{--------------------   Méthodes privé -------------------------}
procedure TreeBin.PostOrdre ( x : TreeBin ) ;
 // parcours postfixé d'un arbre x
begin 
 if x<>nil then
 begin   PostOrdre( x.filsG );
   PostOrdre( x.filsD );
   write(x.info); 
 end
end
;
//autres méthodes ......

{--------------------   Méthodes public -------------------------}
procedure Postfixe;
// parcours préfixé de l'objet
begin
  PostOrdre( self );
end;
//autres méthodes ......

end.

Remonter



1.4 Implantation du parcours en ordre infixé

Algorithme de parcours en ordre symétrique : (ordre infixé)
parcourir ( Arbre )
si Arbre ¹Æ  alors
   parcourir ( Arbre.filsG ) ;
   Traiter-2 (info(Arbre.Racine)) ;
   parcourir ( Arbre.filsD ) ;
Fsi

La procédure écrirera succsessivement: dbeafc

Ordre infixé en Delphi avec les variables dynamiques  :

procedure infixe (f : parbre);
  begin
    if f <> nil then
      with f^ do
        begin
          infixe( filsG );
          write(info);
          infixe( filsD )
        end
  end;

Ordre infixé en Delphi avec la classe  :

interface
type
   TreeBin = class
      private
         procedure FreeRecur( x :TreeBin ) ;
         procedure PreOrdre ( x : TreeBin);
         procedure PostOrdre ( x : TreeBin);
         procedure InfixeOrdre ( x : TreeBin);
      public
         Info : string;
         filsG , filsD : TreeBin;
         constructor CreerTreeBin(s:string);overload;
         constructor CreerTreeBin(s:string; fg , fd : TreeBin);overload;
         destructor Liberer;
         procedure Prefixe;
         procedure Postfixe;
         procedure Infixe;
    end;

implementation
{--------------------   Méthodes privé -------------------------}
procedure TreeBin.InfixeOrdre ( x : TreeBin ) ;
 // parcours infixé d'un arbre x
begin
 if
x<>nil then
 begin

    InfixeOrdre( x.filsG );
   write(x.info);
   InfixeOrdre( x.filsD );
 end
end
;
//autres méthodes ......

{--------------------   Méthodes public -------------------------}
procedure Infixe;
// parcours préfixé de l'objet
begin
  InfixeOrdre( self );
end;
//autres méthodes ......

end.

Remonter



1.5 Implantation du parcours en largeur

Algorithme de parcours en largeur (hiérarchique)
Largeur ( Arbre )
si Arbre ¹ Æ  alors
   ajouter Arbre.racine dans Fifo;
   tantque Fifo ¹ Æ faire
     prendre premier de Fifo;
     traiter premier de Fifo;
     ajouter filsG de premier de Fifo dans Fifo;
     ajouter filsD de premier de Fifo dans Fifo;
   ftant
Fsi


La procédure écrirera succsessivement : abcdef
 

Implantation en Delphi avec les variables dynamiques et un TList  :

type
    parbre = ^arbre;
    arbre = record
                  info : string ;
                  filsG, filsD: parbre
           end;
 

Nous utilisons un objet Delphi de classe TList pour implanter notre Fifo.
 
Un TList stocke un tableau de pointeurs (Pointer en Delphi). Un objet TList est souvent utilisé pour gérer une liste d'objets. TList introduit des propriétés et méthodes permettant d'ajouter ou de supprimer des objets de la liste. En particulier afin d'implanter une file de type Fifo, nous utiliserons les membres suivants du TList.

méthodes
   function Add( x : Pointer): Integer; Ajoute un nouvel élément en fin de liste et renvoie son rang.
   function First : Pointer; Renvoie le premier élément du tableau (celui de rang 0).
   procedure Delete( Index : Integer); Supprime l'élément d'indice spécifié par le paramètre Index.

attributs
  property Count : Integer; Indique le nombre d'entrées utilisées de la liste.
 

Le TList ne contiendra pas les noeuds de l'arbre eux-mêmes mais les pointeurs vers les noeuds (type parbre ici) :


 
 
procedure Largeur ( x : parbre);
  var Fifo : TList;
  begin
    if f <> nil then
    begin
     Fifo:=TList.Create;  // crée la Fifo
     Fifo.Add( x ); // ajoute la racine x dans Fifo
     while Fifo.Count<>0 do
     begin
       write(parbre(Fifo.First)^.info); // traitement du premier
       if parbre(Fifo.First)^.filsG <> nil then
            Fifo.Add(parbre(Fifo.First)^.filsG); // ajoute le fils gauche du premier dans Fifo
       if parbre(Fifo.First)^.filsD <> nil then
            Fifo.Add(parbre(Fifo.First)^.filsD); // ajoute le fils droit du premier dans Fifo
       Fifo.delete(0); // supprime l'élément de rang 0 (le premier)
     end;
     Fifo.Free ; // supprime la Fifo
    end
  end;

On applique la procédure Largeur à l'arbre X afin de parcourir et d'écrire hiérarchiquement les caractères de chaque noeud. Ci-dessous le début d'un suivi d'exécution de la procédure Largeur :
 
Instruction exécutée Action sur le TList Fifo
Fifo:=TList.Create;
// ajouter la racine x dans Fifo
Fifo.Add( x ); 

Début de la boucle while :
// traitement du premier
write(parbre(Fifo.First)^.info)

ecrit : a
// ajoute le fils gauche du premier dans Fifo
Fifo.Add(parbre(Fifo.First)^.filsG)
// ajoute le fils droit du premier dans Fifo
Fifo.Add(parbre(Fifo.First)^.filsD)
// supprime l'élément de rang 0 (le premier)
Fifo.delete(0);
Reprise de la boucle while :
// traitement du premier
write(parbre(Fifo.First)^.info)

etc ....
 


ecrit : b

Remonter



1.6 Programme Delphi complet

Ci-dessous un programme complet en Delphi (avec variables dynamiques) à exécuter tel quel avec Delphi en mode console; il est conseillé au lecteur de ré-écrire ce programme en utilisant la classe TreeBin décrite ci-haut :

program Tree;
{les arbres sont parcourus sous les 3 formes
in, post et pré-fixées }

{$APPTYPE CONSOLE}

uses   sysutils;
  type
    parbre = ^arbre;
    arbre = record
        val: char;
        g, d: parbre
      end;
  var
    rac,arb1,arb2,arb3,arb4,arb5: parbre;
 

  procedure construit (var rac:parbre; filsg,filsd:parbre;elt:string);
  // construit un arbre
  begin
   if rac=nil then begin
    new(rac);
    with rac^ do  begin
        val := elt;
        g := filsg;
        d := filsd
      end;
   end
  end;{construit}
 

procedure edite (f: parbre);
{infixe avec parentheses}
  begin
    if f <> nil then
     with f^ do  begin
          write('(');
          edite(g);
          write(val);
          edite(d);
          write(')')
        end
  end;{edite}

  procedure postfixe (f: parbre);
  begin
    if f <> nil then
      with f^ do begin
          postfixe(g);
          postfixe(d);
          write(val);
        end
  end;{postfixe}

  procedure prefixe (f: parbre);
  begin
    if f <> nil then
      with f^ do begin
          write(val);
          prefixe(g);
          prefixe(d)
        end
  end;{prefixe}

  procedure infixe (f: parbre);
  begin
    if f <> nil then
      with f^ do begin
          infixe(g);
          write(val);
          infixe(d);
        end
  end;{infixe}

procedure Largeur ( f : parbre);
  var Fifo : TList;
  begin
    if f <> nil then begin
     Fifo:=TList.Create;  // crée la Fifo
     Fifo.Add( f ); // ajoute la racine f dans Fifo
     while Fifo.Count<>0 do begin
       write(parbre(Fifo.First)^.info); // traitement du premier
       if parbre(Fifo.First)^.filsG <> nil then
            Fifo.Add(parbre(Fifo.First)^.filsG); // ajoute le fils gauche du premier dans Fifo
       if parbre(Fifo.First)^.filsD <> nil then
            Fifo.Add(parbre(Fifo.First)^.filsD); // ajoute le fils droit du premier dans Fifo
       Fifo.delete(0); // supprime l'élément de rang 0 (le premier)
     end;
     Fifo.Free ; // supprime la Fifo
    end
  end;{Largeur}

begin {prog-principal}
{       b
      /   \
     c     f
   /  \
  d    e
}
  arb1:=nil;
  arb2:=nil;
  arb3:=nil;
  arb4:=nil;
  arb5:=nil;
  construit(arb1,nil,nil,'d');
  construit(arb2,nil,nil,'e');
  construit(arb3,arb1,arb2,'c');
  construit(arb4,nil,nil,'f');
  construit(arb5,arb3,arb4,'b');
{----------------------------------
        g
       /  \
      h    i
}
  arb1:=nil;
  arb2:=nil;
  arb3:=nil;
  construit(arb1,nil,nil,'h');
  construit(arb2,nil,nil,'i');
  construit(arb3,arb1,arb2,'g');
{----------------------------------
        a
       /  \
      b    g
}

  rac:=nil;
  construit(rac,arb5,arb3,'a');
{----------------------------------}
{          a
         /    \
        b       g
      /   \   /   \
     c     f  h    i
   /  \
  d    e
}
  writeln('lecture parenthésée:');
  edite(rac);
  writeln;
  writeln('lecture notation infixée:');
  infixe(rac);
  writeln;
  writeln('lecture notation postfixée:');
  postfixe(rac);
  writeln;
  writeln('lecture notation préfixée:');
  prefixe(rac);
  writeln;
  writeln('lecture hiérarchique:');
  Largeur(rac);
  writeln
end.

Remonter

2. Arbres binaires de recherche
 

Rappel de la définition : (nommé aussi arbre binaire ordonné horizontalement )

Un arbre binaire de recherche satisfait aux critères suivants :
  • L'ensemble des étiquettes est totalement ordonné.
  • Une étiquette est dénommée clef.
  • Les clefs de tous les noeuds du sous-arbre gauche d'un noeud X, sont inférieures ou égales à la clef de X.
  • Les clefs de tous les noeuds du sous-arbre droit d'un noeud X, sont supérieures à la clef de X.

  •  
 

Nous en avons déjà vu au chap4.7 :

Nous proposons une seule implantation avec le type parbre déjà défini avec des variables dynamiques au paragraphe précédent.
 

Rappel de la spécification avec des variables dynamiques  :

type
    parbre = ^arbre;
    arbre = record
                  info : string ;
                  filsG, filsD: parbre
           end;

Implantation en Delphi avec une classe héritant des TreeBin  :

interface

type
   TreeBinRech = class ( TreeBin )

    end;

implementation

end.


 

2.1 Insertion dans un arbre binaire de recherche

Algorithme d'insertion dans un arbre de recherche
placer  l'élément Elt dans l'arbre Arbre  par adjonctions successives aux feuilles

placer ( Arbre Elt )

si Arbre = Æ alors
   creer un nouveau noeud contenant Elt
   Arbre.Racine = ce nouveau noeud
sinon
{ - tous les éléments "info" de tous les noeuds du sous-arbre de gauche
     sont inférieurs ou égaux à l'élément "info" du noeud en cours (arbre)

   - tous les éléments "info" de tous les noeuds du sous-arbre de droite
     sont supérieurs à l'élément "info" du noeud en cours (arbre)
 }
  si clef ( Elt£  clef ( Arbre.Racine ) alors
     placer ( Arbre.filsG Elt )
  sinon
    placer ( Arbre.filsD Elt )
Fsi

Soit par exemple la liste de caractères alphabétiques  : e d f a c b u w , que nous rangeons dans cet ordre d'entrée dans un arbre binaire de recherche. Ci-dessous le suivi de l'algorithme de placements successifs de chaque caractère de cette liste dans un arbre de recherche:
 
Insertions successives des éléments Arbre de recherche obtenu
placer ( racine , 'e' ) 
e est la racine de l'arbre.
    e
placer ( racine , 'd' ) 
d < e donc à fils gauche de e.
placer ( racine , 'f' ) 
f > e donc fils droit de e.
placer ( racine , 'a' ) 
a < e donc à gauche, a < d donc fils gauche de d.
placer ( racine , 'c' ) 
c < e donc à gauche, c < d donc à gauche,  c > a donc fils gauche de a.
placer ( racine , 'b' ) 
b < e donc à gauche, b < d donc à gauche,  b > a donc à droite de a, b < c donc fils gauche de c.
placer ( racine , 'u' ) 
u > e donc à droite de e, u > f donc fils droit de f.
placer ( racine , 'w' ) 
w > e donc à droite de e, w > f donc à droite de f, w > u donc fils droit de u.

Placer en Delphi avec les variables dynamiques  :

procedure placer (var arbre:parbre ; elt:string);
{remplissage récursif de l'arbre binaire de recherche 
par adjonctions  successives aux feuilles de l'arbre }
begin
 if arbre = nil then
 begin
  new(arbre);
  arbre^.info:=elt;
  arbre^.filsG :=nil;
  arbre^.filsD :=nil
 end
 else
 if elt <= arbre^.info then placer (arbre^.filsG ,elt)
 else placer (arbre^.filsD , elt);
end;

Placer en Delphi avec la classe TreeBinRech  :

interface

type
   TreeBinRech = class ( TreeBin )
      private
         procedure placerArbre (var arbre:TreeBinRech ; elt : string);
      public
         procedure Placer ( elt : string);
    end;

implementation
{--------------------   Méthodes privé -------------------------}
procedure TreeBinRech.placerArbre (var arbre:TreeBinRech ; elt:string);
{remplissage récursif de l'arbre binaire de recherche 
par adjonctions  successives aux feuilles de l'arbre }
begin
 if not Assigned(arbre) then
    arbre:=TreeBinRech.CreerTreeBin( elt )
 else
 if elt <= arbre.info then placerArbre (TreeBinRech(arbre.filsG) ,elt)
  else placerArbre (TreeBinRech(arbre.filsD) , elt);
end;

{--------------------   Méthodes public -------------------------}
 procedure TreeBinRech.Placer ( elt : string);
 begin
     placerArbre ( self, elt )
 end;

end.

Remonter



2.2 Recherche dans un arbre binaire de recherche

Algorithme de recherche dans un arbre de recherche
chercher l'élément Elt dans l'arbre Arbre :

Chercher ( Arbre Elt ) : Arbre

si Arbre = Æ alors
  Afficher Elt non trouvé dans l'arbre; 
sinon
  si clef ( Elt )  <  clef ( Arbre.Racine ) alors
     Chercher ( Arbre.filsG Elt )//on cherche à gauche
  sinon
      si clef ( Elt )  >  clef ( Arbre.Racine ) alors
         Chercher ( Arbre.filsD Elt )//on cherche à droite
      sinon retourner Arbre.Racine //l'élément est dans ce noeud
      Fsi
  Fsi
Fsi

Ci-dessous le suivi de l'algorithme de recherche du caractère b dans l'arbre précédent :

Chercher ( Arbre , b

Chercher ( Arbre.filsG , b

Chercher ( Arbre.filsG , b

Chercher ( Arbre.filsD , b

Chercher ( Arbre.filsG , b

retourner Arbre

Chercher en Delphi avec les variables dynamiques  :

function Chercher( arbre:parbre; elt:string) : parbre;
begin
 if arbre = nil then 
 begin
      result := nil;
      writeln('élément non trouvé')
 end
 else
   if elt = arbre^.info then result := arbre //l'élément est dans ce noeud
   else
     if elt < arbre^.info then
        result := Chercher(arbre^.filsG , elt) //on cherche à gauche
    else
       result := Chercher(arbre^.filsD , elt) //on cherche à droite
end;

Chercher en Delphi avec la classe TreeBinRech  :

interface

type
   TreeBinRech = class ( TreeBin )
      private
         procedure placerArbre (var arbre:TreeBinRech ; elt : string);
         function ChercherArbre( arbre:TreeBinRech; elt:string) : TreeBinRech;
      public
         procedure Placer ( elt : string);
         procedure Chercher ( elt : string);
    end;

implementation
{--------------------   Méthodes privé -------------------------}
function TreeBinRech.ChercherArbre( arbre:TreeBinRech; elt:string) : TreeBinRech;
begin
 if not Assigned(arbre) then
 begin
      result := nil;
      writeln('élément non trouvé')
 end
 else
   if elt = arbre.info then result := arbre //l'élément est dans ce noeud
   else
     if elt < arbre.info then
        result := ChercherArbre(TreeBinRech(arbre.filsG) , elt) //on cherche à gauche
    else
       result := ChercherArbre(TreeBinRech(arbre.filsD) , elt) //on cherche à droite
end;

{--------------------   Méthodes public -------------------------}
 procedure TreeBinRech.Chercher ( elt : string);
 begin
     ChercherArbre( self , elt )
 end;

end.

Remonter



2.3 Plus grand et plus petit élément d'un arbre binaire de recherche

Algorithmes de recherche du max et du min
chercher le plus grand élément dans l'arbre Arbre :
//descendre toujours le plus à droite

PlusGrand ( Arbre ) : Arbre
si Arbre.filsD = Æ alors
  retourner Arbre.Racine //c'est le pus grand élément
sinon
  PlusGrand ( Arbre.filsD  )
Fsi



chercher le plus petit élément dans l'arbre Arbre :
//descendre toujours le plus à gauche

PlusPetit ( Arbre ) : Arbre
si Arbre.filsG = Æ alors
  retourner Arbre.Racine //c'est le pus petit élément
sinon
  PlusPetit ( Arbre.filsG  )
Fsi

Chercher max et min avec les variables dynamiques  :

function PlusGrand ( arbre:parbre ) : parbre;
begin
 if arbre^.filsD = nil then 
      result := arbre
 else
   result := PlusGrand( arbre^.filsD ) //on descend à droite
end;

function PlusPetit ( arbre:parbre ) : parbre;
begin
 if arbre^.filsG = nil then 
      result := arbre
 else
   result := PlusPetit( arbre^.filsG ) //on descend à gauche
end;

Le lecteur intéressé par l'écriture avec une classe procédera par traduction des programmes ci-après en remplaçant les variables dynamiques comme nous l'avons écrit plus haut, par des objets de classe TreeBinRech qui hérite de la classe TreeBin.

Remonter


2.4 Suppression dans un arbre binaire de recherche
 

Afin de pouvoir supprimer un élément dans un arbre binaire de recherche, il est necessaire de pouvoir d'abord le localiser, ensuite supprimer le noeud ainsi trouvé et procéder à la réorganisation de l'arbre de recherche éventuellement.

Nous supposons que notre arbre binaire de recherche ne possède que des éléments tous distincts (pas de redondance).

Algorithme de suppression dans un arbre de recherche
supprimer l'élément Elt dans l'arbre Arbre :

Supprimer ( Arbre Elt ) : Arbre
  local Node : Noeud

si Arbre = Æ alors
  Afficher Elt non trouvé dans l'arbre; 
sinon
  si clef ( Elt )  < clef ( Arbre.Racine )   alors
     Supprimer ( Arbre.filsG Elt ) //on cherche à gauche
  sinon
      si clef ( Elt )  >  clef ( Arbre.Racine ) alors
         Supprimer ( Arbre.filsD Elt ) //on cherche à droite
      sinon //l'élément est dans ce noeud
        si Arbre.filsG = Æ alors //sous-arbre gauche vide
           Arbre ¬Arbre.filsD//remplacer arbre par son sous-arbre droit
        sinon 
          si Arbre.filsD = Æ alors //sous-arbre droit vide
           Arbre ¬Arbre.filsG //remplacer arbre par son sous-arbre gauche
          sinon//le noeud a deux descendants
             Node ¬PlusGrand( Arbre.filsG ); //Node = le max du fils gauche
             clef ( Arbre.Racine ) ¬ clef ( Node );//remplacer etiquette
             détruire ( Node ) //on élimine ce noeud
          Fsi
        Fsi
      Fsi
    Fsi
Fsi

Supprimer avec les variables dynamiques  :

function PlusGrand ( arbre  : parbre ) : parbre;
begin
 if arbre^.filsD = nil then 
      result := arbre
 else
   result := PlusGrand( arbre^.filsD ) //on descend à droite
end;

procedure Supprimer (var arbre:parbre; elt:string ) ;
var Node,Loc:parbre;
begin
  if arbre <> nil then 
    if elt < arbre^.info  then 
       Supprimer (arbre^.filsG, elt )
   else
    if elt > arbre^.info  then 
       Supprimer (arbre^.filsD, elt )
    else // elt = arbre^.info
    if arbre^.filsG = nil  then
    begin
       Loc:=arbre;
       arbre := arbre^.filsD;
       dispose(Loc)
    end
    else
       if arbre^.filsD = nil then
       begin
         Loc:=arbre;
         arbre := arbre^.filsG;
         dispose(Loc)
      end
      else
      begin
        Node := PlusGrand ( arbre^.filsG );
        Loc:=Node;
        arbre^.info := Node^.info;
        arbre^.filsG :=Node^.filsG;
        dispose(Loc)
      end
end;

Le lecteur intéressé par l'écriture avec une classe procédera par traduction des programmes ci-après en remplaçant les variables dynamiques par des objets de classe TreeBinRech qui hérite de la classe TreeBin.

Remonter


2.5 Programme Delphi complet

Ci-dessous un programme complet reprenant l'exemple précédent avec des variables dynamiques et à exécuter tel quel avec Delphi en mode console :

program arbre_binaire_Rech;
{remplissage d'un arbre binaire de recherche
aussi dénommé arbre binaire ordonné horizontalement  }

{$APPTYPE CONSOLE}

uses   sysutils;
type
   pointeur = ^noeud;
   noeud = record
                   info:string;
                   filsGauche:pointeur;
                   filsDroit:pointeur
              end;
var
   racine,tree:pointeur;

procedure placer_arbre(var arbre:pointeur; elt:string);
{remplissage récursif de l'arbre binaire de recherche}
begin
 if arbre=nil then
 begin
  new(arbre);
  arbre^.info:=elt;
  arbre^.filsGauche:=nil;
  arbre^.filsDroit:=nil
 end
 else
 { - tous les éléments "info" de tous les noeuds du sous-arbre de gauche
     sont inférieurs ou égaux à l'élément "info" du noeud en cours (arbre)

   - tous les éléments "info" de tous les noeuds du sous-arbre de droite
     sont supérieurs à l'élément "info" du noeud en cours (arbre)
 }
 if elt<=arbre^.info then placer_arbre(arbre^.filsGauche,elt)
 else placer_arbre(arbre^.filsDroit,elt);
end;
 

procedure infixe(branche:pointeur);
{lecture symétrique de l'arbre binaire}
begin
  if branche<>nil then
  begin
   infixe(branche^.filsGauche);
   write(branche^.info,' ');
   infixe(branche^.filsDroit);
  end
end;

function ChercherArbre( arbre:pointeur; elt:string):pointeur;
begin
 if arbre=nil then
 begin
    ChercherArbre:=nil;
    writeln('élément: '+elt+' non trouvé.')
 end
 else
  if elt = arbre^.info then ChercherArbre:=arbre
  else
   if elt < arbre^.info then ChercherArbre:=ChercherArbre(arbre^.filsGauche,elt)
   else ChercherArbre:=ChercherArbre(arbre^.filsDroit,elt)
end;

function PlusGrand ( arbre  : pointeur ) : pointeur;
begin
 if arbre^.filsDroit = nil then  result := arbre
 else  result := PlusGrand( arbre^.filsDroit ) //on descend à droite
end;

procedure Supprimer (var arbre:pointeur; elt:string ) ;
var Node,Loc:pointeur;
begin
  if arbre <> nil then
    if elt < arbre^.info  then
       Supprimer (arbre^.filsGauche, elt )
   else
    if elt > arbre^.info  then
       Supprimer (arbre^.filsDroit, elt )
    else // elt = arbre^.info
    if arbre^.filsGauche = nil  then
    begin
       Loc:=arbre;
       arbre := arbre^.filsDroit;
       dispose(Loc)
    end
    else
       if arbre^.filsDroit = nil then
       begin
         Loc:=arbre;
         arbre := arbre^.filsGauche;
         dispose(Loc)
      end
      else
      begin
        Node := PlusGrand ( arbre^.filsGauche );
        Loc:=Node;
        arbre^.info := Node^.info;
        arbre^.filsGauche :=Node^.filsGauche;
        dispose(Loc)
      end
end;

begin
  racine:=nil;
  {soit la liste entrée : e d f a c b u w }
  placer_arbre(racine,'e');
  placer_arbre(racine,'d');
  placer_arbre(racine,'f');
  placer_arbre(racine,'a');
  placer_arbre(racine,'c');
  placer_arbre(racine,'b');
  placer_arbre(racine,'u');
  placer_arbre(racine,'w');
  {on peut aussi entrer 8 éléments au clavier
  for i:=1 to 8 do
  begin
    readln(entree);
    placer_arbre(racine,entree);
  end; }
  supprimer(racine, 'b');
  writeln('parcours infixé (ou symétrique):');
  infixe(racine);
  writeln;
  tree:=ChercherArbre(racine,'c');
  if tree<>nil then writeln( 'recherche de "c" : ok');
  tree:=ChercherArbre(racine,'g');
  if tree<>nil then writeln( 'recherche de "g" : ok');
  { Notons que le parcours infixé produit une liste des
    éléments info, classée par ordre croissant
  }
end.

Il est conseillé au lecteur de reprendre ce programme en utilisant la classe TreeBinRech décrite plus haut.