Mathématiques Discrètes et Algorithmique - LMPT

publicité
Université François Rabelais de Tours
Laboratoire de Mathématiques et Physique Théorique
Mathématiques Discrètes et Algorithmique
UE 5-4 Option
Semestre 5
4. Algorithmes récursifs
4.1. Quelques exemples instructifs. Un algorithme est dit récursif si il s’appelle lui même. L’exemple
canonique est celui de l’algorithme d’Euclide qui calcule le pgcd de deux entiers a, b. Si a = bq + r où
q = a ÷ b et r = a mod b on a pgcd(a, b) = pgcd(b, r), d’où l’algorithme suivant
Procédure : pgcd
Données : a, b ∈ N, 0 < b < a
si b=0 alors
retourner a
sinon
retourner pgcd(b, a mod b)
fin
Algorithme 10: Calcul recursif du plus grand diviseur commun de a, b (pgcd)
On a par exemple :
pgcd(96, 81) = pgcd(81, 15)
= pgcd(15, 6)
= pgcd(6, 3)
= pgcd(3, 0)
=3
Pour voir qu’un tel algorithme est correct il faut vérifier (1) que le résultat est effectivement le pgcd(a, b) et
(2) que le processus s’arrête après un nombre fini d’étapes. Ici, c’est relativement simple, puisque la suite
des restes est strictement décroissante et que pgcd(a, b) = pgcd(b, a mod b).(On rappelle ici que a mod b
désigne le reste de la division euclidienne de a par b.)
Donnons un autre exemple : la fonction ψ de Ackermann et Péter. Elle définie de la manière suivante
1.
2.
3.
ψ(0, n) =
ψ(m + 1, 0) =
ψ(m + 1, n + 1) =
n+1
ψ(m, 1)
ψ(m, ψ(m + 1, n))
Cette fonction a l’air simple mais pour calculer ψ(1, 1) il faut déjà 4 étapes :
3
ψ(1, 1) = ψ(0, ψ(1, 0))
2
= ψ(0, ψ(0, 1))
1
= ψ(0, 2)
1
= 3.
Pour calculer ψ(2, 2), il faut 27 étapes ! On peut montrer que
2··
·2
ψ(4, y) = 2| 2{z } − 3
y+3-fois
et que pour calculer ψ(4, 3) il faut utiliser l’étape 1 un nombre de fois incroyable (bien plus que le nombre
d’atomes estimé dans l’univers). Mais quelque soit (x, y), le calcul de ψ(x, y) est tout de même fini !
Moralité, il faut faire attention avec la récurrence !
1
2
4.2. Un algorithme de tri récursif : le tri par fusion. Dans cette partie on utilisera l’algorithme
Fusion(L1 , L2 ) qui prend en entrée deux listes triées et qui renvoie une liste L = L1 ∪ L2 triée.
Exemple 4.1. L1 = [2, 3, 5, 6] et L2 = [1, 4]. On procède de la manière suivante pour fusionner L1 et L2 :
L1
[2, 3, 5, 6]
[2, 3, 5, 6]
[3, 5, 6]
[5, 6]
[5, 6]
∅
L2
[1, 4]
[4]
[4]
[4]
∅
∅
L
∅
[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5, 6]
comparaison
1<2
2<4
3<4
4<5
Si L1 est de longueur n et L2 de longueur m alors Fusion fais au plus n + m − 1 comparaisons pour
construire L.
On introduit maintenant l’algorithme récursif de tri par fusion.
Procédure : Tpf
Données : L = (a1 , . . . , an )
si n>1 alors
m := bn/2c
L1 := Tpf(a1 , . . . , am )
L2 := Tpf(am+1 , . . . , an )
L := Fusion(L1 , L2 )
fin
Retourner L
Algorithme 11: Tri par Fusion (Tpf)
Exemple 4.2. Trions à l’aide du tri par fusion la liste [9, 1, 3, 4, 7]. Il est pratique de représenter les
differentes étapes de l’algorithme dans un arbre.
[9,1,3,4,7]
[9,1]
[9]
[3,4,7]
[1]
[3]
[4,7]
[4]
[7]
4.3. Arbres. Un graphe orienté G est la donnée d’un ensemble (en général fini) V , dont les éléments sont
appelés des sommets et d’un ensemble E de couples ordonnés de sommets, dont les éléments sont appelés
arêtes. Un graphe non orienté est un graphe ou on oublie l’orientation des arêtes. On représente un graphe
par un dessin de manière naturelle ! Les courbes qui relient deux sommets sont “fléchées” ou non selon que
le graphe est orienté ou non. Un graphe est dit :
• simple s’il ne contient pas d’arêtes de la forme (a, a) avec a ∈ G et si il y a au plus une arête joignat
deux sommets distincts.
• acyclique si aucune suite d’arêtes ne couple sur les sommets
• connexe s’il existe une représentation géométrique de G dans laquelle il est possible de relier deux points
quelconques du graphe.
• Le degré d’un sommet v ∈ V est le nombre d’arêtes dont v est une des composantes.
Pour plus de détails sur les graphes, on se réferera aux chapitres sur la théorie des graphes ou on trouvera
de nombreux exemples.
3
Définition 4.3. Un arbre est un graphe acyclique connexe dans lequel on distingue un sommet en particulier que l’on appelle racine. Les sommets de degré 1 autres que la racine sont appelés feuilles de l’arbre.
Un arbre est tacitement un graphe orienté dont les arêtes sont orientés en s’éloignant de la racine. Deux
sommets appartenant à une même arête ont un ordre, celui du côté de la racine est appelé le père, celui
du côté des feuilles est appelé le fils. Un arbre binaire est un arbre dans lequel chaque sommet est père
d’au plus 2 fils. On définit les termes suivants
• Le niveau d’un sommet est la “distance de ce sommet” à la racine.
• Le niveau k d’un arbre est l’ensemble des sommets de niveau k
• La hauteur d’un arbre est le niveau maximum
Exemple 4.4. Dans l’arbre suivant, a est la racine. Les feuilles sont g, l, i, j, k. Le sommet d est le père
de g et h. Le niveau 2 est composé des sommets {d, e, f }. Cet arbre est de hauteur 4.
Figure 1. Un arbre binaire
Définition 4.5. Un arbre binaire complet est arbre binaire dans lequel tous les niveaux sont saturés (i.e.
on ne peut pas ajouter de sommets) à l’exception, peut-être du dernier niveau.
On vérifie facilement par récurrence la proposition suivante.
Proposition 4.6.
i) Au niveau k d’un arbre binaire complet de hauteur > k, il y a 2k -sommets.
ii) Soit A un arbre binaire complet de hauteur k et à S sommets. On a
2k ≤ S ≤ 2k+1 − 1
iii) Soit A un arbre binaire de hauteur k à N feuilles. Alors ≤ N ≤ 2k . Si de plus A est complet on a
2k−1 < N ≤ 2k
4.4. Complexité minimale d’un algorithme de tri à base de comparaisons. Dans cette partie on
montre que le tri par fusion est en O(n ln(n)) et que tout algorithme de tri basée sur des comparaisons est
au mieux en O(n ln(n)). En d’autres termes, le tri par fusion est en quelque sorte optimal.
Proposition 4.7. Le tri par fusion nécessite O(n ln n) comparaisons pour trier une liste de longueur n.
Démonstration. Pour estimer la complecité du Tpf on supposera pour simplifier que la liste L est de longueur n = 2m . Dans l’arbre suivant on écrit Tpf(N ) pour dire que l’on applique le Tpf à une liste de
longueur N .
• Au niveau 1 : 2 listes de longueur 2m−1
• Au niveau 2 : 22 listes de longueur 2m−2
• Au niveau k : 2k listes de longueur 2m−k
• Au niveau m : 2m listes de longueur 1
Ensuite, pour remonter du niveau m au niveau m − 1, on fusionne 2m−1 couples de listes de longueur 1
soit 2m−1 comparaisons.
Pour remonter du niveau k au niveau k − 1, on fusionne 2k couples de listes de longueur 2m−k soit
2k−1 (2m−k+1 − 1) comparaisons.
Finalement, en tout, on fait
k
X
i=1
2k−1 (2m−k+1 − 1) =
m
X
(2m − 2k )
k=1
= m2m − 2m + 1
= n log2 (n) − n + 1
Et donc le tri par fusion nécessite O(n ln n) comparaisons.
4
Théorème 4.8. Un algorithme de tri basée sur des comparaisons est au minimum en O(n ln n).
Démonstration. On utilise la notion d’arbre de décision pour le tri d’une liste de longueur L = (a1 , . . . , an ) :
c’est un arbre binaire dont les sommets representent une comparaison ai : aj et les deux fils du sommet
ai : aj représente les cas où a1 > aj et ai < aj . Les feuilles sont donc toutes les manières de trier une liste
à n éléments. (On suppose pour simplifier qu’aucun des ai ne sont égaux). L’arbre de décision A d’une
Figure 2. Arbre de décision pour trier une liste à 3 éléments
liste à n éléments a donc n! feuilles, puisqu’il y a n! manières différentes d’ordonner L. A chaque feuille
correspond une manière d’ordonner L. Le nombre de comparaisons nécessaires pour arriver à cet ordre est
la distance de la feuille à la racine. Soit k la hauteur de l’arbre A. C’est un arbre binaire, on a donc n! ≤ 2k
par la Proposition 4.6. D’où log2 (n!) ≤ k. on obtient le résultat puisque log2 (n!) = O(n log n).
Téléchargement