Exercice corrigé Arbre de décision - Ensiwiki

publicité
Exercice corrigé
Arbre de décision
Le tri d’un ensemble d’éléments (par exemple des entiers) peut être vu de manière abstraite à l’aide d’un
arbre de décision. Un arbre de décision est un arbre binaire représentant les comparaisons entre éléments lors
du tri. Chaque nœud interne de l’arbre correspond à la comparaison de deux éléments a et b, et on note ce
nœud a?b. Chaque feuille correspond à un ordre, i.e. une permutation, sur les éléments de l’ensemble, qu’on
note ha1 , a2 , . . . , an i pour signifier a1 < a2 , etc. L’exécution de l’algorithme de tri correspond à un chemin
entre la racine et une feuille dans l’arbre de décision. La figure 1 illustre par exemple le déroulement de
l’algorithme de tri par insertion sur un ensemble de trois éléments {a, b, c}. Si on prend par exemple a = 27,
b = 42 et c = 5, l’algorithme va suivre le chemin surligné en rouge.
Fig. 1 – Arbre de décision pour l’algorithme de tri par insertion sur trois éléments a, b et c.
Exercice 1. Montrer qu’un arbre de décision est forcément localement complet. En déduire que tout algorithme de tri d’un ensemble de n éléments nécessite Ω(n log n) comparaisons dans le cas le pire.
Démonstration. Soit A un arbre de décision. Un nœud interne de A correspond à la comparaison de deux
éléments a et b, et possède donc forcément deux fils : soit a < b, soit a ≥ b. A est donc bien localement
complet.
Soit N le nombre total de nœuds de A : N = ni+f , avec ni et f respectivement le nombre de nœuds internes
et le nombre de feuilles de A. Comme A est localement complet, on sait que f = ni + 1 (cette propriété se
démontre par récurrence sur ni). On a donc N = 2f − 1.
Si A est l’arbre de décision d’un algorithme de tri d’un ensemble de n éléments, en supposant que cet
algorithme est correct, chaque feuille doit correspondre à une permutation différente de ces éléments, et
toutes les permutations doivent être représentées dans A. Comme il y a n! permutations possibles, on a
f = n!, et donc
N = 2n! − 1.
(1)
Remarquons à présent que le nombre de comparaisons dans le cas le pire correspond au nombre de nœuds
internes traversés par le chemin le plus long allant de la racine à une feuille de l’arbre de décision. Autrement
dit, c’est exactement la hauteur h de l’arbre. Que vaut cette hauteur ? Par définition d’un arbre binaire, on
a
N ≤ 2h+1 − 1
(2)
Grenoble-INP Ensimag, 1ère année, 2010-2011
Algo 2 — Exercice corrigé
(avec égalité si et seulement si l’arbre est complet).
En combinant les équations (1) et (2), on obtient
2n! ≤ 2h+1
ou encore
log(n!) ≤ h.
(3)
La formule bien connue de Stirling nous donne une approximation de la factorielle de n :
n! =
On a donc :
√
n
1
2πn( )n (1 + Θ( )).
e
n
n
∃A > 0, n! ≥ A( )n
e
ce qui nous donne :
log(n!) ≥ log A + n log n − n log e.
On peut vérifier que
∀n ≥ e2 , n log n − n log e ≥
1
n log n.
2
Grâce à l’équation (3), on a donc bien
∃B > 0, ∃N0 > 0, ∀n ≥ N0 , h ≥ Bn log n.
On a donc bien montré que le nombre de comparaisons dans le cas le pire est en Ω(n log n).
Bibliographie indicative
[1] T. Cormen, C. Leiserson, R. Rivest, C. Klein. Introduction à l’algorithmique : cours et exercices. Dunod,
2002.
Disponible à la B.U. Sciences et à la bibliothèque MI2S, en français et en anglais.
Grenoble-INP Ensimag, 1ère année, 2010-2011
Algo 2 — Exercice corrigé
Exercice 2. Soit T un tableau contenant n entiers positifs ou nuls. Supposons que nous codons un arbre
de décision, associé à un certain algorithme de tri sur T, de la façon suivante. Chaque nœud contient deux
entiers, correspondant aux deux indices des valeurs du tableau comparées dans le cas d’un nœud interne,
et égaux à 0 dans le cas d’une feuille. Il contient également un tableau de n éléments, correspondant à la
permutation résultat dans le cas d’une feuille et contenant une unique valeur −1 dans le cas d’un nœud
interne (on prend cette valeur car elle n’est pas présente dans T). Ceci donne en Ada :
type Tab is array(1..n) of Integer;
type Noeud;
type ArbreDecision is access Noeud;
type Noeud is record
Indice1, Indice2 : Integer; -- vaut 0 si feuille
Permutation : Tab; -- vaut [-1,-1,...,-1] si noeud interne
Gauche, Droit : ArbreDecision; -- vaut null si feuille
end record;
Ecrire une fonction GetPermutation(T : in Tab, A : in ArbreDecision) return Tab ; qui parcourt un
arbre de décision (supposé construit) A et renvoie la permutation correspondant aux valeurs stockées dans T.
Démonstration. L’algorithme sera bien sûr récursif. Le principe est le suivant : on part de la racine ; tant
qu’on est sur un nœud interne on compare T[Indice1] et T[Indice2], et on descend dans l’arbre en fonction
du résultat. Une fois arrivé sur une feuille, il suffit de renvoyer le tableau Permutation.
function GetPermutation(T : in Tab, A : in ArbreDecision) return Tab is
begin
if (A.Indice1 == 0) then
-- on est sur une feuille
return A.Permutation;
end if;
-- sinon on est sur un noeud interne
if (A.T[A.Indice1] < A.T[A.Indice2]) then
-- on descend à gauche
return GetPermutation(T,A.Gauche);
end if;
-- sinon on descend à droite
return GetPermutation(T,A.Droit);
end GetPermutation;
Grenoble-INP Ensimag, 1ère année, 2010-2011
Algo 2 — Exercice corrigé
Téléchargement