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 à l'un des sous-problèmes. L'ensemble
des solutions partielles ainsi obtenues 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
1
2 CHAPITRE 2. LA STRATÉGIE DIVISER POUR RÉGNER
en deux moitiés, de taille égale, ou diérant de un si n est impaire, qu'on trie de manière
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, permettra alors 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 mettent 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.
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 puissance 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ès logb (n) étapes. D'autre part, et d'après (2.1), à chaque étape de la récur-
rence, le terme courant est multiplié par un facteur a. Ceci implique qu'à une étape k
quelconque de la récursion, le terme asymptotique O((n/bk )c ) sera multiplié par ak , ce
qui donne
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
Il s'agit d'une suite géométrique de raison a/bc et de terme initial O(nc ). 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
a = 2, car à chaque étape, le problème courant donne lieu à deux sous-problèmes,
qui sont résolus par les deux appels récursifs.
b = 2, car à chaque étape, le tableau est scindé en deux moitiés.
c = 1, car la fusion de deux tableaux triés se déroulent en temps linéaire, O(n1 ).
La formule donne alors O(n log n).
Exemple 2. La puissance de la stratégie diviser pour régner peut être illustrée par une
méthode de multiplication récursive, qui est plus ecace que la méthode de multiplication
1 2
usuelle . Rappelons que cette dernière demande un nombre d'opérations élémentaires
égal au produit du nombre de chires dans le code décimal, (ou autre), de chacun des
deux nombres à multiplier. Donc, si chacun des deux nombres est codés sur n chires
2
alors la multiplication usuelle demande O(n ) opérations élémentaires. Une addition, par
contre, demande autant d'opérations élémentaires que de chires dans le code du plus
grand des deux entiers, donc O(n).
Supposons que a et b sont deux entiers codés, en binaire, sur n bits chacun. Pour des
raisons de simplicité, on suppose aussi que n est une puissance de 2. La première étape
de la méthode de multiplication récursive de a par b consiste à scinder chacun des codes
binaires de a et de b en deux moitiés, une moitié gauche et une moitié droite :
a= â ǎ b= b̂ b̌
On a, alors
a = â.2n/2 + ǎ et b = b̂.2n/2 + b̌
Il s'ensuit que
le produit ab. La complexité de cette méthode de multiplication récursive peut donc être
exprimée par une fonction f qui vérie la relation de récurrence suivante :
Donc, au lieu de calculer les quatre produits âb̂, âb̌, ǎb̂ et ǎb̌, on calculera le produit
(â + ǎ)(b̂ + b̌), qui est sur n/2 bits, et les deux produits âb̂ et ǎb̌, qui sont aussi sur n/2
bits. Pour résumer, en utilisant l'identité (2.3), on aura besoin de calculer 3 produits sur
n/2 bits, n + n/2 décalages et 6 additions sur n bits, à chaque appel récursif. L'équation
de récurrence que doit vérier la complexité de la méthode de multiplication récursive
modiée est donc la suivante :
Exercice 4. Soit une matrice m×n d'entiers où les éléments de chaque ligne sont
triés dans l'ordre croissant de gauche à droite et les éléments de chaque colonne
sont triés dans l'ordre croissant du haut vers le bas. Proposez un algorithme ecace
qui eectue la cherche d'un élément donné dans une telle matrice puis évaluez sa
complexité.
p1 = a(f − h)
p2 = (a + b)h
p3 = (c + d)e
p4 = d(g − e)
p5 = (a + d)(e + h)
p6 = (b − d)(g + h)
p7 = (a − c)(e + f )
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 3. 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
8 CHAPITRE 2. LA STRATÉGIE DIVISER POUR RÉGNER
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.
É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
récurrente consiste à trouver une expression du nème terme en fonction du seul 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 9
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.5) 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.5),
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 :
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 5. La suite de Fibonacci est une suite entière qui peut être dénie comme suit :
0 si n=0
f (n) = 1 si n=1 (2.8)
f (n − 1) + f (n − 2) sinon
10 CHAPITRE 2. LA STRATÉGIE DIVISER POUR RÉGNER
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 la
suivante :
x2 − x − 1 = 0 (2.9)
i −1
`
( m
)
X X
f (n) = rin ai,j nj (2.10)
i=1 j=0
où
` ≤ k désigne le nombre de racines distinctes de l'équation caractéristique
(2.7).
ri désigne une racine de l'équation caractéristique (2.7).
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 6. 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.9). 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
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
La résolution de ce système donne les valeurs suivantes :
1 1
√ et −√
5 5
Le terme général de la suite de Fibonacci est donc égal à :
( √ √ )
1 1 + 5 n 1 − 5 n
f (n) = √ − (2.11)
5 2 2
2.3. RÉSOLUTION DES RÉCURRENCES LINÉAIRES 11
horizontal
vertical
Exemple 7. 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.11).
Enn, on peut facilement déduire, à partir de l'équation (2.11), que l'ordre de complexité
n
de l'algorithme 2.3 est O(c ), où c > 1 est une constante.
Une équation de récurrence linéaire est dite non homogène si elle a la forme de (2.5),
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
12 CHAPITRE 2. LA STRATÉGIE DIVISER POUR RÉGNER
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 9. 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
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
Il s'agit là d'une équation de récurrence linéaire homogène d'ordre 3. On a donc besoin
des conditions initiales suivantes :
n(n + 1)
f (n) =
2
14 CHAPITRE 2. LA STRATÉGIE DIVISER POUR RÉGNER
An de homogénéiser (c-à-d annuler le terme g(n) de l'équation (2.5)) des équations
linéaires plus complexes, on fait recours à un opérateur noté E , qui est déni comme suit.
On peut alors combiner l'opérateur d'avancement E avec lui même ou/et avec des opéra-
teurs de constantes, pour obtenir de nouveaux opérateurs. La combinaison d'opérateurs
peut s'exprimer comme la somme ou le produit de deux opérateurs et on a :
Exemple 10.
(E − 1)(c) = 0, pour toute constante c.
(E − 2)(2n ) = E(2n ) − 2(2n ) = 2n+1 − 2n+1 = 0.
(E − 1)3 (n2 ) = (E − 1)2 (2n + 1) = (E − 1)(2) = 0.
g(n) Opérateur
c E−1
Pk (n) (E − 1)k+1
αn E−α
αn Pk (n) (E − α)k+1
homogène suivante :
0 si n=0
f (n) =
f (n − 1) + n2 sinon
Pour calculer le terme général de cette fonction complexité, on procède à son homogénéi-
3
sation. On applique alors l'opérateur (E − 1) qui, d'après l'exemple précédant annule la
2 3 2 3
fonction g(n) = n , c-à-d, (E − 1) (n ) = 0. L'application de l'opérateur (E − 1) aux
deux membres de l'équation de récurrence, on obtient :
f (n + 4) − 4f (n + 3) + 6f (n + 2) − 4f (n + 1) + f (n) = 0
Il s'agit d'une équation de récurrence linéaire homogène d'ordre 4. On a donc besoin des
conditions initiales suivantes :
n(n + 1)(2n + 1)
f (n) =
6
Nous terminons l'étude des équations de récurrence linéaire non homogène en donnant,
dans le Tableau 2.1, les opérateurs à appliquer pour éliminer les fonctions g(n) les plus
courantes quand il s'agit de fonctions exprimant des complexités. Dans le Tableau 2.1, c
désigne une constante, Pk (n) un polynôme de degré k et α un réel.
16 CHAPITRE 2. LA STRATÉGIE DIVISER POUR RÉGNER
Exercice 6. 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 algorithmes choisiriez-vous pour résoudre le problème ?
Exercice 7. 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.
k
T[i] < m m T[j] > m
Figure 2.3 Etat du tableau après réarrangement par rapport à la médiane des médianes
(m).
Il s'agit de trouver le ième plus petit élément d'un tableau d'entiers T[1..n] donné pour
un i donné. Par exemple, si i = 1 alors il s'agit de trouver le plus petit élément du tableau
T et si i = n alors c'est le plus grand élément qu'il faut trouver. Enn, si i = (n + 1) div 2
alors il s'agit de trouver l'élément médian du tableau, c'est-à-dire celui qui occuperai la
case du milieu si le tableau été trié. Notons que si n est pair et que, par conséquent, le
tableau n'admet pas une case du milieu proprement dite alors on conviendra que l'élément
médian sera celui qui occupe la case (n div 2) = (n + 1) div 2. Ce choix sera désigné
par la médiane inférieure.
Une première démarche possible pour résoudre le problème consiste à trier le tableau
puis renvoyer comme résultat l'élément qui occupe la ième case du tableau trié. Cette ap-
proche a une complexité, dans le pire des cas, qui est égale à celle du tri utilisé, O(n log n)
donc, si on utilise un tri ecace. Mais peut-on faire mieux ? La réponse est oui, car l'identi-
cation du ième élément ne requiert pas le tri de tout le tableau. Cependant, ceci demande
une démarche plus sophistiquée qui est du type diviser pour régner . Les grandes lignes
de cette démarche sont les suivantes :
3. A l'aide d'un appel récursif, déterminer l'élément médian des dn/5e éléments mé-
dian sélectionnés dans l'étape précédente. Désignons par m la médiane (des mé-
dianes) obtenue.
4. Réarranger le tableau de telle sorte que la médiane des médianes (m) soit dans la
case qu'elle occuperait si le tableau été trié, c'est-à-dire que, après réarrangement,
toutes les éléments précédant m dans le tableau seront plus petit que m et tous
ceux qui succèdent à m dans le tableau seront plus grands que m (voir Figure 2.3).
Désignons par k l'indice de la case contenant m dans le tableau réarrangé.
5. Si i = k alors retourner m, sinon
si i < k alors retourner le résultat de l'appel récursif avec T [1..k − 1] et i, sinon
retourner le résultat de l'appel récursif avec T [k + 1, n] et i − k .
La complexité de l'algorithme 2.5 peut être étalblie en inférant une relation de ré-
currence vériée par la fonction de complexité de l'algorithme. Une telle relation peut
être déduite en analysant chacune des étapes de l'algorithme. La division des élément
en des groupes de 5, (qui constitue la première étape de l'algorithme), peut se faire en
temps linéaire en déterminant une paire d'indices pour chacun des dn/5e sous-tableaux.
La deuxième étape de l'algorithme peut également être exécutée en temps linéaire en
18 CHAPITRE 2. LA STRATÉGIE DIVISER POUR RÉGNER
triant les dn/5e sous-tableau de taille ne dépassant pas 5 et en sélectionnant les éléments
médians de chacun des sous-tableaux.
Pour l'étape suivante, qui contient un appel récursif, on constate que la taille du
tableau qui sera traité par l'appel récursif est bornée par dn/5e. Cette remarque sera
prise en compte lors de l'établissement de la relation de récurrence recherchée. Pour ce
qui est de réarranger le tableau, cette étape peut se faire en temps linéaire, O(n), comme
on peut le déduire du pseudo-code de la fonction Rearranger(), qui est détaillée dans
l'Algorithme 2.5.
La dernière étape de l'algorithme implique des appel récursifs sur une partie des don-
nées de départ. Il s'agit des éléments qui vont se trouver avant la médiane ou après, dont
il va falloir borner supérieurement le nombre an d'établir la relation de récurrence que
va vérier le fonction de complexité de l'algorithme. Chaque sous-tableau de taille 5 dont
la médiane est plus petite que m contient, au moins, 3 éléments plus petits que m. De
même, chaque sous-tableau de taille 5 dont la médiane est plus grande que m contient, au
n
moins, 3 éléments plus grands que m. De plus, il y a d e sous-tableaux de taille 5, parmi
5
1 n 1 n
lesquels, au moins, d d ee − 1 ont une médiane plus petite que m et, au moins d d ee ont
2 5 2 5
une médiane plus grande que m. Il s'ensuit que l'on peut borner supérieurement la taille
des sous-tableaux T [1..k − 1] et T [k + 1..n] qui interviennent dans les appels récursifs de
l'étape 5, par
3n 7n
n− +3 = +3
10 10
.
On peut, à présent, établir une relation de récurrence que doit vérier la fonction de
complexité de l'Algorithme 2.5 :
7n n
f (n) ≤ f ( + 3) + f (d e) + c0 n
10 5
où le terme c0 n sert à borner la fonction de complexité de toutes les étapes linéaires de
l'algorithme.
Par ailleurs, on peut constater que la relation explicitée ci-dessus n'a pas la forme de
la relation de récurrence du master theorem ni celle des équations de récurrence linéaire.
On va alors faire recourt à une autre technique de calcul pour déduire la complexité de
l'Algorithme 2.5. Tout d'abord, on peut facilement vérier que pour des données de taille
< 41, la complexité des calcul est constante. Le choix de la constante n0 = 41 sera justié
par la suite. On fait alors l'hypothèse que l'algorithme en question a une complexité
0 0
linéaire pour des tailles de données n telle que n < n et on montre que sa complexité est
0 0 0
linéaire pour des données de taille n. Admettant donc que f (n ) ≤ cn , pour tout n < n,
7n n
où c est une constante. Or, pour tout n ≥ 41, on a + 3 < n et d 5 e < n. Il s'ensuit,
10
d'après l'hypothèse ci-dessus, que
7n n 7n n
f (n) ≤ f ( + 3) + f (d e) + c0 n ≤ c( + 3) + c( + 1) + c0 n
10 5 10 5
Ceci implique que
−cn
f (n) ≤ cn + ( + 7c + c0 n)
10
Il sut donc que le terme ( −cn
10
+4c+c0 n) soit nul ou négatif pour déduire que f (n) ≤ cn et
10c0 n n
donc que f (n) est linéaire. On doit alors avoir c ≥ . Or, pour n ≥ 41, on a ≤ 41
n−40 n−40
2.5. L'ENVELOPPE CONVEXE EN TEMPS SUPER-LINÉAIRE 19
10c0 n
(d'où le choix de n0 = 41),
ce qui veut dire que la quantité
n−40
est constante. On déduit
0
que f (c) ≤ cn, pour toute constante c ≥ 410c , ce qui implique que f (n) est bien d'ordre
linéaire.
Dénition 4.
Un polygone du plan est dit convexe si chaque segment délimité par deux
points du polygone est entièrement dans le polygone.
L' enveloppe convexe d'un ensemble de points du plan est le plus petit poly-
gone convexe contenant tous les points de l'ensemble.
La Figure 2.5 montre deux polygones, un qui est convexe et l'autre pas. Elle montre aussi
un ensemble de points avec leur enveloppe convexe.
Les sommets de l'enveloppe convexe d'un ensemble de points E sont forcement des
points de E, et il se trouve qu'une enveloppe convexe, qui est un polygone convexe, est
complètement déterminée par l'ensemble de ses sommets. Il s'ensuit que la détermination
de l'enveloppe convexe d'un ensemble de point revient à l'identication des sommets de
cette enveloppe. Les points de l'ensemble qui ne sont pas des sommets de l'enveloppe
convexe sont appelés points intérieurs. D'après un théorème bien connu, (the Carathéo-
rady theorem ), un point est intérieur, si et seulement si, il s'écrit comme une combinaison
3
convexe des autres points de l'ensemble. Cette dernière remarque donne l'idée d'un algo-
3. Une combinaison convexe est une combinaison linéaire impliquant exclusivement des coecients
positifs dont la somme vaut 1.
20 CHAPITRE 2. LA STRATÉGIE DIVISER POUR RÉGNER
rithme naïf, (brute-force algorithm ), qui élimine tous les points intérieurs et ne garder que
les sommets, déterminant ainsi l'enveloppe convexe. Mais un tel algorithme est coûteux
en temps de calcul, car il serait question de résoudre autant de programme linéaire que
de points dans l'ensemble de départ. Or, la complexité de la résolution d'un programme
linéaire est plus que cubique.
La détermination des points intérieurs, lors de la phase de fusion des enveloppes gauche
et droite, (la troisième étape), constitue la tâche la plus délicate. Elle est réalisée par une
technique qui a donné son nom à l'algorithme : algorithme des deux pont s. Il s'agit d'un
pont supérieur et d'un pont inférieur, qui sont en réalité deux droites. Chacune de ces
droites passe par un sommet de l'enveloppe gauche et un sommet de l'enveloppe droite.
Le pont supérieur est obtenu comme suit : Soit G le point le plus à droite de l'enveloppe
gauche et D le point le plus à gauche de l'enveloppe droite. Si le point qui succède à
G, en parcourant les sommets de l'enveloppe gauche suivant le sens trigonométrique,
est au dessus de la droite (G, D) alors G est remplacé par son successeur. De même,
si le point qui précède D, en parcourant les sommets de l'enveloppe droite suivant le
sens trigonométrique, est au dessus de la droite (G, D) alors D est remplacé par son
prédécesseur. On itère ces deux actions autant que possible. A la n du processus, la
droite (G, D) fournit le pont supérieur. La Fonction 2.6 met en langage algorithmique
cette démarche.
Pour avoir le pont inférieur, on procède de manière symétrique. Désignons par (G0 , D0 )
les deux points qui dénissent le pont inférieur. L'enveloppe convexe nale sera formée
0
par les sommets de l'enveloppe gauche compris entre G et G (inclus) et ceux de l'en-
0
veloppe droite compris entre D et D , toujours en suivant le sens trigonométrique (voir
Figure 2.5). L'algorithme des ponts pour le calcul de l'enveloppe convexe d'un ensemble
de points est détaillée dans l'Algorithme 2.7.
Évaluant, à présent, la complexité de l'algorithme des deux ponts. Comme étape préa-
lable, on procède au tri du tableau contenant les points de l'ensemble E, selon l'ordre
croissant des abscisses. Ceci peut se faire en O(n log n) par un tri fusion, par exemple.
L'algorithme des deux ponts est un algorithme récursif qui applique la stratégie diviser
pour régner en subdivisant le problème en deux, (deux appels récursifs), et les données
22 CHAPITRE 2. LA STRATÉGIE DIVISER POUR RÉGNER
Figure 2.5 Deux polygnes, le premier est convexe (haut gauche) et l'autre pas. Enve-
loppe convexe d'un ensemble de points du plan (bas).
également en deux (le tableau T est scindé en deux moitiés). Pour fusionner les deux enve-
loppes convexes, solutions des deux sous-problèmes, l'algorithme des deux ponts procède
au calcul des deux ponts. Cette tâche s'exécute en O(n), car il faut parcourir les sommets
des deux enveloppes convexes, dont le nombre ne peut dépasser n. De plus, le teste de la
position d'un point par rapport à une droite, (au-dessus ou au-dessous), peut se faire en
temps constant en déterminant l'équation de la droite. Il en résulte de cette analyse que
la complexité de l'algorithme des deux pont vérie la récursion non linéaire suivante :
n
f (n) = 2f (d e) + O(n)
2
En appliquant le Théorème 1, on obtient une complexité en O(n log n) ; un temps super-
linéaire, donc.
2.6 Conclusion
Figure 2.6 Illustration de la méthode des deux ponts. Le schéma montre les deux ponts
obtenus à la convergence de la technique de construction des ponts. L'étape de fusion des
deux enveloppes convexes entraîne l'élimination de trois points intérieurs.