Académique Documents
Professionnel Documents
Culture Documents
La mise en ÷uvre de la stratégie diviser pour régner fait, très souvent, recours au
mécanisme de la récursivité. Ainsi, la résolution du problème est conée à une routine
récursive. Un premier appel récursif est, alors, lancé avec comme objectif la résolution du
problème initial. Si le problème est jugé élémentaire alors une solution est vite calculée
et renvoyée comme résultat de l'appel. Sinon, le problème courant est décomposé en
plusieurs sous-problèmes, qui vont déclencher autant d'appel récursifs. Le rôle de chacun
de ces appels récursifs est de calculer une solution au sous-problème associé. L'ensemble
de ces solutions partielles est, par la suite, assemblé pour former une solution au problème
de départ. En appliquant cette stratégie de manière récursive sur les sous-problèmes on
arrive, au bout du compte, à récupérer une solution au problème initial.
Exemple 1. On voudrait étudier un tri qui soit plus ecace que les tris de complexité
quadratique tel que le tri à bulles, le tri par insertion ou le tri par sélection. Pour ce faire,
on choisit d'étudier le tri par fusion, qui illustre parfaitement l'application de la stratégie
diviser pour régner . Ainsi, pour trier un tableau à n éléments, on procède en le scindant
en deux moitiés, de taille égale, ou diérant de 1 si n est impaire, qu'on trie de manière
1
2 CHAPITRE 2. LA STRATÉGIE DIVISER POUR RÉGNER
indépendante. Une fois, les deux moitiés du tableau triées, il est possible de les fusionner
en un seul tableau trié en un temps linéaire, O(n), comme il sera montré dans ce qui suit.
Pour trier les deux moitiés de tableau, on peut appliquer la même approche, de manière
récursive, et ainsi de suite, jusqu'à ce que l'on atteigne des tableaux de taille 1, qui sont
triés d'oce.
En résumé, le tri par fusion peut être réalisé par une procédure récursive qui décompose
le problème en deux sous-problèmes de taille quasiment égales puis combine les solutions
des deux sous-problèmes en un temps linéaire, O(n). De ceci, on déduit que la complexité
du tri par fusion peut être décrite par une fonction qui vérie la relation de récurrence
suite :
n
f (n) = 2f (d e) + O(n)
2
Un théorème qui va être présenté dans la section suivante permet de dériver l'ordre de la
complexité du tri par fusion, qui est O(n log n).
L'Algorithme 2.1, contient deux procédures qui mettre en ÷uvre le principe du tri par
fusion. La première procédure, TriFusion qui est récursive, applique la stratégie diviser
pour régner en décomposant le problème en deux puis en combinant les solutions des
deux sous-problèmes en faisant appel à la deuxième procédure Fusion. Cette dernière a
pour tâche de fusionner deux tableaux, qui sont supposés être triés, en temps linéaire. Un
exemple d'une telle fusion est le suivant :
Avant fusion
G= 0 3 4 5 7 9 D= 1 2 5 6 7 8
Après fusion
G= 0 1 2 3 4 5 D= 5 6 7 7 8 9
Pour terminer l'étude du tri par fusion, vérions que la procédure de fusion se déroule
bien en un temps linéaire. Pour ce faire, il sut d'examiner le code de cette procédure
pour constater que les trois boucles se répètent, au plus, (nD debD) fois et que, dans le
n
pire des cas, cette diérence vaut d 2 e. Ceci justie que la fusion a une complexité linéaire.
On s'intéresse aux algorithmes du type diviser pour régner qui opèrent en découpant un
n
problème de taille n en a sous-problèmes de taille d e, puis qui combinent les solutions
b
c
des sous-problèmes, en O(n ) étapes, pour des constantes a, b > 1, c ≥ 0. La complexité
2.2. LE THÉORÈME MAÎTRE 3
n
Algorithme 2.1 : Le tri par fusion.
4 CHAPITRE 2. LA STRATÉGIE DIVISER POUR RÉGNER
de ces algorithmes peut être décrite par une fonction f qui vérie la relation de récurrence
suivante :
1 si n=1
f (n) = (2.1)
af (d nb e) + O(nc ) si n≥2
Dans ce qui suit, on énonce le théorème principal, (plus connu sous l'appellation anglaise
de master theorem ), qui permet de dériver l'ordre de grandeur asymptotique, dans le pire
des cas, des fonctions de complexité qui vérient la relation de récurrence (2.1). Ceci veut
dire que la complexité d'un bon nombre des algorithmes qui opèrent selon la stratégie
diviser pour régner peut être calculée en appliquant le théorème qui suit.
Preuve. Pour des raisons de simplicité supposons que n est une puissante de b. Ceci ne
blogb nc
fausse pas les résultats, car n vérie toujours n ≤ b.b , et b est une constante. La
première constatation est que l'indice de la récurrence diminue d'un facteur b, à chaque
étape. Ceci implique que la base de la récurrence, (qui correspond au cas n = 1), sera
atteinte aprèslogb n étapes. D'autre part, et d'après (2.1), à chaque étape de la récurrence,
le terme courant est multiplié par un facteur a. Ceci implique qu'à une étape k quelconque
k k c
de la récursion, on aura à sommer a termes asymptotiques de la forme O((n/b ) ). On
déduit qu'à l'étape k, la somme des terme asymptotiques est donnée par :
n c
ak .O(( ))
bk
En sortant les termes constants, on obtient
a
( c )k .O(nc )
b
An d'obtenir f (n), on doit donc sommer les termes ( bac )k .O(nc ), pour k = 0, . . . , logb n,
on obtient alors :
a a a
+ ( c )2 + . . . + ( c )logb n .O(nc )
1+ c
b b b
c c
Il s'agit d'une suite géométrique de raison a/b et de terme initial O(n ). D'après, le
Théorème 6 du Chapitre 1, on obtient
c c
f (n) = O(1)O(n ), si a/b < 1, et donc, si c > logb a.
c c
f (n) = O(logb n)O(n ) si a/b = 1, et donc, si c = logb a.
c log n c alogb n
f (n) = O((a/b ) b )O(n ) = O(
nc
)O(nc ) = O(alogb n )O(1) = O(nlogb a ) si
a/bc > 1, et donc, si c < logb a.
Application : pour ce qui est de l'ordre de grandeur de la complexité du tri par fusion, il
peut être déduit en appliquant le master theorem. Il sut pour ce-là de trouver les bonnes
valeurs des constantes a, b et c. Selon la démarche du tri par fusion, on a
Exercice 2. Vous avez à choisir entrer trois algorithmes qui appliquent la straté-
gie diviser pour régner an de résoudre le même problème. Les trois algorithmes
opèrent de la manière suivante :
L'algorithme A résout le problème en le décomposant en 5 sous-problèmes
ayant chacun la moitié de la taille et en combinant les solutions partielles en
temps linéaire.
L'algorithme B résout le problème, de taille n, en le décomposant en 2 sous-
problèmes de taille n−1 et en combinant les solutions partielles en temps
constant.
L'algorithme C résout le problème, de taille n, en le décomposant en 9 sous-
problèmes de taille n/3 et en combinant les solutions partielles en temps
quadratique.
Précisez l'ordre de grandeur asymptotique de la complexité de chacun des algo-
rithmes. Lequel des trois algorithme choisiriez-vous pour résoudre le problème ?
Bien que le théorème maître soit applicable pour le calcul de la complexité de nombreux
algorithmes qui opèrent selon la stratégie diviser pour régner, il ne pourra, hélas, pas
s'appliquer dans tous les cas. En eet, il existe bien des algorithmes qui opèrent selon la
stratégie diviser pour régner mais dont la complexité ne vérie pas l'équation (2.1). Par
conséquent, le théorème maître ne pourra pas s'appliquer pour de tels algorithmes.
Exemple 2. Partant d'un exemple concret. L'une des énigmes classiques, qui se résolvent
aisément en utilisant la stratégie diviser pour régner, est celle connue sous le nom des
tours de Hanoi. Il s'agit de faire déplacer un ensemble de n disques, tous de diamètres
diérents, d'un pieu de départ vers un pieu d'arrivée. La diculté de la tâche provient
du fait qu'il est interdit d'empiler un disque de diamètre plus grand sur un disque de
diamètre plus petit. On dispose, néanmoins, d'un pieu supplémentaire qui va permettre de
contourner la diculté.
An de concevoir un algorithme qui permet de déterminer la séquence de déplacement
à eectuer pour résoudre l'énigme, on se propose d'appliquer, encore une fois, la stratégie
diviser pour régner. Ainsi, pour résoudre le problème pour n disques, on peut procéder
comme suit :
On résout le problème pour n-1 disques en déplaçant les n-1 plus petits disques du
pieu A vers le pieu B ;
on déplace le disque le plus large du pieu A vers le pieu C ;
On résout, une seconde fois, le problème pour n-1 disques en déplaçant les n-1 plus
petits disques, qui sont désormais autour du pieu B, vers le pieu C.
1 si n=1
f (n) = (2.2)
2f (n − 1) + 1 si n≥2
Étant donnée une suite de nombres (f (n))n∈N , une équation qui relie le nème terme
aux termes qui le précèdent est appelée équation récurrente. La résolution d'une équation
ème
récurrente consiste à trouver une expression du n terme en fonction du paramètre n.
Les équations récurrentes sont divisées en deux catégories : celles qui sont linéaires et
celles qui ne le sont pas. Dans ce qui suit, on étudie une catégorie restreinte d'équations
récurrentes linéaires.
2.3. RÉSOLUTION DES RÉCURRENCES LINÉAIRES 7
Remarques :
Dans la Dénition 1, les constantes d0 , . . . , dk−1 dénissent ce qu'on appelle les
conditions initiales, qui sont nécessaires au démarrage de toute récursion.
Le nombre de constantes, k, dénissant les conditions initiales, est appelé l'ordre
de la récursion.
Si g(n) = 0 alors la relation (2.3) est dite homogène, sinon, elle est non homogène.
La relation de récurrence (2.1) supposée par le master theorem est non linéaire, à
n
cause du terme .
b
Une équation de récurrence linéaire est homogène si elle a la forme de l'équation (2.3),
avec g(n) = 0, donc, si elle a la forme
La résolution de telles équations s'appuie sur des équations impliquant des polynômes qui
sont dénis comme suit :
8 CHAPITRE 2. LA STRATÉGIE DIVISER POUR RÉGNER
Remarques :
Comme on peut le constater, l'équation caractéristique ne tient pas compte des
conditions initiales.
Le degré du polynôme intervenant dans l'équation caractéristique d'une relation
de récurrence linéaire homogène correspond à l'ordre de la relation.
Exemple 4. La suite de Fibonacci est une suite entière qui peut être dénie comme suit :
1 si n=1
f (n) = 2 si n=2 (2.6)
f (n − 1) + f (n − 2) sinon
Comme on peut le constater, le terme général de la suite de Fibonacci est donnée par une
équation de récurrence linéaire homogène d'ordre 2. Son équation caractéristique est le
suivant :
x2 − x − 1 = 0 (2.7)
i −1
`
( m
)
X X
f (n) = rin ai,j nj (2.8)
i=1 j=0
où
` ≤ k désigne le nombre de racines distinctes de l'équation caractéristique
(2.5).
ri désigne une racine de l'équation caractéristique (2.5).
mi désigne la multiplicité de la racine ri .
Les ai,j sont des constantes qui sont déterminées à partir des conditions
initiales.
Exemple 5. Reprenons le cas de la suite de Fibonacci. On peut vérier que l'équation dé-
nissant le terme général de cette suite est une équation de récurrence linéaire homogène.
Son équation caractéristique à été donnée dans (2.7). Cette équation admet deux racines
distinctes, qui sont :
√ √
1+ 5 1− 5
et
2 2
D'où la solution générale :
√ √
1 + 5 n 1 − 5 n
f (n) = a1 + a2
2 2
2.3. RÉSOLUTION DES RÉCURRENCES LINÉAIRES 9
horizontal
vertical
Enn, les constantes a1 et a2 sont déterminées, à partir des conditions initiale, qui donnent
le système à deux équations et deux inconnues suivant :
f (0) = a1 + a2 = 0
√ √
1 + 5 1 − 5
f (1) = a1 + a2 =1
2 2
1 1
√ et −√
5 5
( √ √ )
1 1 + 5 n 1 − 5 n
f (n) = √ − (2.9)
5 2 2
Exemple 6. On voudrait paver une grille de dimension 2×n (voir Figure 2.1-gauche)
par des dominos verticaux ou horizontaux (voir Figure 2.1-droite). Un exemple d'un tel
pavage est montré dans la Figure 2.2.
Pour concevoir un algorithme qui peut générer tous les pavages possibles, on procède en
scindant le problème en deux sous-problèmes, car il y a deux façons de placer des dominos
dans la grille, qui sont les suivants :
ou bien qu'on place un domino verticalement,
ou bien qu'on en place deux horizontalement.
Signalons que la deuxième possibilité ne peut être appliquée que s'il reste assez d'espace
dans la grille, ce qui se traduit par n ≥ 2.
L'algorithme 2.3 traduit cette démarche, en achant tous les pavages possibles d'une
grille de taille 2 × n, où n est une donnée. Pour que les achages soient correctement
exécutés, on utilise une pile dans laquelle chaque pavage est mémorisé avant d'être af-
ché. L'algorithme achera la lettre v, (resp. h), pour chaque domino vertical, (resp.
horizontal), utilisé.
On peut aussi concevoir une fonction récursive qui calcule le nombre de pavages pour
un n donné (voir Algorithme 2.3). On peut constater que le nombre de pavages possibles,
pour un n donné, vérie la même relation de récurrence que celle vériée par la suite
de Fibonacci. On conclut donc que le nombre de pavage est donné par l'équation (2.9).
Enn, on peut facilement déduire, à partir de l'équation (2.9), que l'ordre de complexité
n
de l'algorithme 2.3 est O(c ), où c > 1 est une constante.
10 CHAPITRE 2. LA STRATÉGIE DIVISER POUR RÉGNER
Une équation de récurrence linéaire est dite non homogène si elle a la forme de (2.3),
avec g(n) 6= 0. An de résoudre de telles équations, on peut les transformer en des équa-
tions homogènes. La démarche décrite dans le paragraphe précédent est alors appliquée
pour obtenir la solution de l'équation transformée. Des transformations d'équations non
homogènes, plutôt simples, sont décrites dans les deux exemples suivant :
f (n) − 2f (n − 1) = 1
f (n + 1) − 2f (n) = 1
f (n + 1) − 3f (n) + 2f (n − 1) = 0
qui est bien une équation de récurrence linéaire homogène d'ordre 2. On a donc besoin des
conditions initiales suivantes :
f (0) = 0, f (1) = 1
f (n) = 2n − 1
Exemple 8. Le présent exemple porte sur l'analyse de la complexité du tri par insertion.
Rappelons que la démarche générale de ce tri consiste à insérer, à chaque étape, le ième
éléments dans le sous-tableau commençant à la première case et de taille i − 1, qui est
supposé être déjà trié. Une version récursive de ce tri (voir Algorithme 2.4), permet de
mettre en évidence une relation de récurrence linéaire non homogène que vérie la fonction
de complexité de ce tri :
f (n) − f (n − 1) = n
qui est aussi vraie pour un tableau de n+1 éléments :
f (n + 1) − f (n) = n + 1
f (n + 1) − 2f (n) + f (n − 1) = 1
f (n + 2) − 2f (n + 1) + f (n) = 1
12 CHAPITRE 2. LA STRATÉGIE DIVISER POUR RÉGNER
En soustrayant, encore une fois, les deux dernières équations, membre à membre, on
obtient :
f (n + 2) − 3f (n + 1) + 3f (n) − f (n − 1) = 0
n(n + 1)
f (n) =
2
2.3. RÉSOLUTION DES RÉCURRENCES LINÉAIRES 13
Exercice 5. Le tri rapide (quick-sort), comme le tri par fusion, s'appuie sur la
stratégie diviser pour régner. Ainsi, pour trier les éléments d'un tableau T[deb..n]
dont les indices sont comprit entre un indice de début et un indice de n, le tri rapide
procède comme suit :
Le tableau T[deb..n] est scindé en deux sous-tableaux T[deb..m-1] et T[m..n], où
m est un entier comprit entre deb et n. Les éléments des deux sous-tableaux sont
réarrangés de telle sorte que :
tous les éléments de T[deb..m-1] sont inférieur ou égal à T[m] qui, à son tour,
doit être inférieur ou égal à tous les éléments de T[m+1..n].
Le tri des deux sous-tableaux T[deb..m-1] et T[m+1..n] sont, ensuite, assuré par
deux appels récursifs au même module de tri rapide. À la diérence du tri par fusion,
le tableau T[deb..n] se trouve trié du moment que les deux sous-tableaux sont triés.
Un point crucial du tri rapide est le choix de l'indice m au niveau duquel le tableau
T[deb..n] est scindé en deux. Pour des raisons de simplicité, on suppose que cet
indice correspond à la position nale de l'élément T[n], qui est alors désigné par
le pivot, dans le tableau T[deb..n].
2. Proposez une procédure récursive qui met en ÷uvre le principe du tri rapide.