Sunteți pe pagina 1din 6

Maximier - Définition Maximier - Exemple

➻ Un arbre vide est considéré comme un maximier.


9
Structures de Données ➻ Un arbre binaire non vide est un maximier si et seulement si
et Complexité ➠ sa racine porte la valeur maximale.
➠ ses 2 sous-arbres principaux sont des maximiers.
➻ À la racine des 2 sous-arbres principaux on trouve donc les 2ème et
7 8
Maximier – Tri Arbre
3ème valeurs selon l’ordre décroissant.
N.E. Oussous
➻ On a un ordre partiel :
oussous@lifl.fr
➠ Le père est plus grand que ses deux fils. 6 3 7 5
FIL – USTL ➠ Pas d’ordre entre les frères.

2 3 2 1 6

SDC - Licence – p.1/32 SDC - Licence – p.2/32 SDC - Licence – p.3/32

Maximier - Utilité Maximier - Cueillette Cueillette - Code


➻ La structure de maximier n’est pas utilisée pour implémenter les La suppression de l’élément maximal est, par contre, plus efficace.
procedure Supprimer_Max(var T : Maximier) ;
primitives usuelles (recherche, insertion, suppression) sur les ➻ On remplace cet élément par le plus grand de ses successeurs. X : Curseur ;
ensembles.
➻ On recommence l’opération avec le successeur utilisé. Begin
➻ Par exemple, la recherche d’une valeur particulière peut amener à X := Racine(T) ;
parcourir tout l’arbre (donc être en (n)). ➻ On supprime la feuille utilisée en dernier.
While not Est_Feuille(X) Do Begin
Elle nécessite de plus la gestion d’une pile dont la hauteur est celle 9 8
Determiner quel successeur possède
de l’arbre lui-même. la valeur maximale ;
Cette recherche serait donc inefficace. 7 8 7 7 Recopier cette valeur;
➻ Un maximier est par contre utilisé pour extraire le maximum parmi Descendre X du coté où se trouvait
un ensemble de valeurs. 6 3 7 5 6 3 6 5 la valeur maximale ;
end ; // while
2 3 2 1 6 2 3 2 1 Supprimer(X);
End ; // Supprimer_Max

SDC - Licence – p.4/32 SDC - Licence – p.5/32 SDC - Licence – p.6/32


Pré-Maximier Pré-Maximier ! Maximier Réorganisation - Exemple
➻ Un Pré-Maximier est un arbre dont les 2 sous-arbres principaux sont ➻ Si le pré-maximier n’est pas un maximier, il faut 2 9
des maximiers. ➠ Échanger la valeur portée à la racine avec la valeur maximale de
➻ Un pré-maximier n’est pas nécessairement un maximier, cela ses successeurs, 9 8 7 8
dépend de la valeur portée à la racine. ➠ Réorganiser le successeur avec lequel a eu lieu l’échange.
➻ La transformation en maximier (Réorganisation) se fait par ➻ La réorganisation nécessite le parcours d’une seule branche, avec un 7 3 7 5 6 3 7 5
une méthode analogue à celle utilisée pour la suppression du traitement en (1) à chaque nœud parcouru.
maximum. 6 3 2 1 6 2 3 2 1 6

SDC - Licence – p.7/32 SDC - Licence – p.8/32 SDC - Licence – p.9/32

Réorganisation - Code
procedure Reorganiser(var T : Maximier) ;
Fabrication d’un maximier Fabrication - Exemple
X : Curseur ; ➻ Un arbre binaire quelconque contient des maximiers : toutes ses 2 9
Begin
X := Racine(T) ; feuilles.
➻ Les sous-arbres de hauteur 2 sont donc des pré-maximiers.
Repeat
if not Est_Vide(sag(X)) then begin 9 6 7 8
G := X; G := sag(G) ;
➻ Par réorganisations successives, on peut transformer tous les
sous-arbres de hauteur 2 en maximiers, puis ceux de hauteur 3, etc
if not Est_Vide(sad(X)) then begin
D := X; D := sad(D) ; 6 1 7 5 6 3 7 5
if Valeur(D) > Valeur(G) and Valeur(D) > Valeur(X) then begin
Changer_Valeur(X, Valeur(D)); X := D; :::
end else
if Valeur(G) > Valeur(D) and Valeur(G) > Valeur(X) then begin ➻ Il faudra donc parcourir les sous-arbres par hauteurs croissantes (les 7 3 2 3 8 2 3 2 1 6
Changer_Valeur(X, Valeur(G)); X := G; sous-arbres les plus profonds en premier).
end else exit;
end else begin
Changer_Valeur(X, Valeur(G)); X := G;
end;
end else
if not Est_Vide(sad(X)) then begin
Changer_Valeur(X, Valeur(D)); X := D;
end else exit;
until false ; // Repeat
End ;

SDC - Licence – p.10/32 SDC - Licence – p.11/32 SDC - Licence – p.12/32


Fabrication - Code récursif Fabrication - Code itératif Tri-Arbre : Heapsort
Cet algorithme s’exprime facilement de façon récursive Cet algorithme peut aussi s’exprimer (informellement) de façon itérative L’utilisation des maximiers peut amener à une méthode de tri appelée
procedure Fabriquer_maximier(C : Curseur) par Tri-arbre ou Heapsort.
Begin for h := 2 to hauteur(arbre) do begin Description informelle de l’algorithme :
if not Est_Vide(sag(X)) then begin Réorganiser tous les sous-arbres de hauteur h ;
G := X; G := sag(G) ; end; // for Tri_Arbre(var T : Tableau)
Begin
Fabriquer_maximier(G) ; Constituer un arbre contenant les valeurs de T;
end; // if Mais l’interface d’arbre proposée jusqu’ici ne permet Fabriquer un maximier à partir de cet arbre;
if not Est_Vide(sad(X)) then begin pas d’implémenter aisément cette version itérative, for i:=low(T) to high(T) do begin
D := X; D := sad(D) ; faute de moyen efficace pour parcourir tous les Ranger le maximum dans T[i] ;
Fabriquer_maximier(D); sous-arbres d’une hauteur donnée. Retirer le maximum de l’arbre ;
end; // for
end; // if End ; // Tri_Arbre
// on a maintenant un pré-maximier
Reorganiser(C); En pratique, cette méthode de tri est employée dans le
End ; // Fabriquer_maximier cas d’une implémentation d’arbre bien particulière : le tas.

SDC - Licence – p.13/32 SDC - Licence – p.14/32 SDC - Licence – p.15/32

La structure de Tas Tas - Exemple Tas dans 1 tableau d’indices 1..n


➻ La structure de tas permet de représenter, dans un tableau, un arbre 9 T(1)
quasi-équilibré, dont les feuilles à profondeur maximale sont situées
le plus à gauche possible.
7 8 T(2) T(3)
➻ Elle consiste à ranger les valeurs portées par les nœuds
T(4) T(5) T(6) T(7)
➠ par profondeur croissante 6 3 7 5
➠ de gauche à droite (pour une profondeur donnée). T(8) T(9) T(10) T(11) T(12)

un arbre = un tableau 2 3 2 1 6 Racine 1


Successeur gauche 2 i
un curseur = un indice du tableau
1 2 3 4 5 6 7 8 9 10 11 12 Successeur droite 2 +1 i
un nœud = une case du tableau i
Prédecesseur 2
Est_Feuille 2 i > n

9 7 8 6 3 7 5 2 3 2 1 6 Possède 2 successeurs 2 i < n

Possède 1 seul successeur 2 =n i n

Dernier nœud interne 2

SDC - Licence – p.16/32 SDC - Licence – p.17/32 SDC - Licence – p.18/32


Tas - Cas général La structure de Tas Réorganiser un Tas : Itératif
T[low(T)] ➻ Les moins procedure Reorganiser( C : Curseur ) ;
I : Curseur ;
➠ Les arbres auront une taille maximale, celle du tableau. begin
T[low(T)+1] T[low(T)+2]
➠ Un nœud est associé à une case (fixée) du tableau. I := C ;
T[low(T)+3] T[low(T)+4] T[low(T)+5] T[low(T)+6] repeat
➻ Les plus if Possede_2_Successeurs(I) then begin
... ... ... ... T[high(T)] if T[sag(I)] > T[sad(I)] and T[sag(I)] > T[I] then begin
➠ Pas besoin de pointeurs. Echanger(T[I],T[sag(I)]);
Racine ( ) low T ➠ Le passage d’un nœud à ses successeurs se fait par adressage
I := sag(I);

2 ( )+1
end else
Successeur gauche i low T calculé. if T[sad(I)] > T[sag(I)] and T[sad(I)] > T[I] then begin
Successeur droite 2 ( )+2
i low T
➠ Possibilité de calculer également l’emplacement du
Echanger(T[I],T[sad(I)]);

2( + ( ) 1)
1 I := sad(I);
Prédecesseur i low T end else // T[I] est la plus grande des 3 valeurs
Est_Feuille 2 i ( )+1
low T > high T ( ) prédécesseur. exit;

Possède 2 successeurs 2 i ( )+1


low T < high T ( ) ➠ Possibilité de parcourir l’arbre de bas en haut. end else

2 ( )+1= ( )
if Possede_1_Seul_Successeur(I) and T[sag(I)]>T[I] then begin
Possède 1 seul successeur i low T high T Echanger(T[I],T[sag(I)]);

2( ( )+ ( ) 1)
1 exit;
Dernier nœud interne high T low T
end else exit;
Until false ;
end; // Reorganiser

SDC - Licence – p.19/32 SDC - Licence – p.20/32 SDC - Licence – p.21/32

Réorganiser un Tas : Récursif Réorganiser Tas : Complexité Réorganiser Tas : Complexité


Reorganiser(T, C) ➻ Le temps d’exécution de Reorganiser sur un sous-arbre de taille ➻ On aboutit à la relation de récurrence suivante :
n enraciné en un nœud i est la somme du temps (1) et le temps 
2  + (1)
g : Curseur ;

() 6
d : Curseur ; n
d’exécution de Reorganiser sur un sous-arbre enraciné sur l’un
3
Begin T n T
g := sag(C) ; des deux fils du nœud i.
d := sad(C) ;
2n
// on détermine max(T[C], T[g], T[d]) ➻ Les sous-arbres des fils ont chacun une taille au plus égale à 3 .
if g <= high(T) and T[g] > T[C] then
max := g ➻ Le pire des cas est atteint lorsque le dernier niveau est rempli ➻ On est dans le cas 2 du théorème général avec
else

= 32 ( ) = (1)
exactement à moitié.
= 1
max := C ;
if d <= high(T) and T[d] > T[max] then max := d ; a b f n
if max <> C then begin // c’est un pré-maximier
Echanger(T[C], T[max]) ;
Reorganiser(T, max) ;
end; // if
Ainsi log a = 0 = 1 et
n b n ( ) = ( log a)
f n n b

End; // Reorganiser
➻ La solution est donc ( ) = O(log2 )
T n n

SDC - Licence – p.22/32 SDC - Licence – p.23/32 SDC - Licence – p.24/32


Fabriquer un Tas Exemple Exemple
➻ Les feuilles
  sont situées dans les dernières cases du tableau : ➻ Soit le tableau suivant : 1 1

T[( n2 +1)..n]. 1 2 3 4 5 6 7 8 9 10 4 16

2 3 2 3
4 1 3 2 16 9 10 14 8 7
➻ On parcourt les sous-arbres par hauteurs croissantes en parcourant 1 3 14 10

les cases du tableau en ordre inverse. 4 5 6 7 4 5 6 7

➻ Il lui correspond l’arbre suivant : 2 16 9 10 8 7 9 3

procedure Fabriquer_Tas(var T : Arbre) ; 1 8 9 10 8 9 10

begin 14 8 7 2 4 1
4
for i:=Dernier_arbre_h2 downto Racine do begin
Reorganiser(i); // Reorganiser(T,i) 2 3
end;
1 3
end Fabriquer_Tas;
4 5 6 7

➻ Le temps d’exécution de Fabriquer_tas : Chaque appel à


Reorganiser coûte O(log2 n). Il existe O(n) appels de ce
2 16 9 10

type. Donc, le temps d’exécution est au plus O(n log n).


8 9 10

14 8 7

SDC - Licence – p.25/32 SDC - Licence – p.26/32 SDC - Licence – p.27/32

Fabriquer Tas : Complexité Fabriquer Tas : Complexité Le tri par tas : Heapsort
➻ Une analyse plus fine est basée sur les propriétés des tas : ➻ On a l’égalité : ➻ On construit un tas par Fabriquer_Tas à partir de T[1..n],
➠ La hauteur d’un tas à n éléments est h = blog2 n . 1 n=length(T).
X 12
➠ 2h i sous-arbres de hauteur i.
2i = (1 1 2)2 = 2
i =
➻ L’élément maximum de T se trouve à la racine T[1].
=
i=0 ➻ On le place à sa position finale en l’échangeant avec T[n].
➻ Le temps de calcul de Reorganiser sur un nœud de hauteur h est
O(h). ➻ On décrémente la taille du tableau en ne considérant que le
➻ Le coût total pour Fabriquer_tas sera ➻ Donc, le temps d’exécution de Fabriquer_tas peut être borné sous-tableau T[1..(n-1)].
! par ➻ On transforme T[1..(n-1)] en tas puisque les fils de la racine
h
X h
X 0 1
( )=
T n 2h i  O( ) = O 2h
i
i

2i
blog
X 2 n 1
X
! restent des tas. Il y aura éventuellement à descendre la nouvelle
i=0 i=0 O n
i

2i
A = O n
2i = O(  2) = O( )
i
n n
racine à sa place.
i=0 i=0

➻ Ainsi, on peut construire un tas à partir d’un tableau non ordonné en


un temps linéaire.

SDC - Licence – p.28/32 SDC - Licence – p.29/32 SDC - Licence – p.30/32


Exemple Tri Tas : Code
1 Tri_Tas(T)
Begin
1 Fabriquer_Tas(T) ;
2 3 n := Length(T) ;
for i:=n downto 2 do begin
2 i 3 Echanger(T[1], T[i]) ;
4 5 6 7 Reorganiser(T[1..n-1], 1) ;
end;
4 7 8 9 End ;
8 9 10 ➻ L’appel à Fabriquer_Tas prend un temps en O(n).
➻ Chacun des n 1 appels à Reorganiser prend un temps en
O(log n).
10 14 16

1 2 3 4 5 6 7 8 9 10 ➻ La complexité de Tri_Tas est donc en O(n log n).


1 2 3 4 7 8 9 10 14 16

SDC - Licence – p.31/32 SDC - Licence – p.32/32

S-ar putea să vă placă și