Vous êtes sur la page 1sur 41

Drcursivation

Dfinition : Drcursiver, cest transformer un


algorithme rcursif en un algorithme quivalent
ne contenant pas dappels rcursifs.
Dfinition : Rcursivit terminale : Un algorithme
est dit rcursif terminal sil ne contient aucun
traitement aprs un appel rcursif.
medbecha 2010

Drcursivation (suite)
Rcursivit terminale

Drcursivation

ALGORITHM P(U)
Begin
if C(U) then D(U);P((U))
else T(U)
End
U est la liste des paramtres ;
C(U) est une condition portant sur U ;
D(U) est le traitement de base de lalgorithme
(U) reprsente la transformation des
paramtres
T(U) est le traitement de terminaison

Avec ces notations, lalgorithme P quivaut


lalgorithme suivant :
ALGORITHM P(U)
Begin
while C(U) do
D(U);
U = (U)
T(U)
End
Lalgorithme P est une version drcursive
de lalgorithme P.

medbecha 2010

Drcursivation (suite)
Version rcursive
DIVIDE (a , b)
Begin
if a = 0 then Error
else if a b then return a
=b
else
return DIVIDE(a , b-a)
End

Version drucrsive

DIVIDE (a , b)
Begin
if a = 0 then Error
while( b > a) do
b= b-a
return (a=b)
End

medbecha 2010

Drcursivation (suite)
Version rcursive

Drcursivation

Factorial (n)
Begin
if n = 0 then
return 1
else
return
NFactorial(n-1)
End

Factorial (n)
Begin
F=1
for i = n step -1 to 1 do
F = F*i
End

medbecha 2010

Drcursivation (suite)
Dfinition : Rcursivit non terminale : La rcursivit
est dite non terminale si et seulement si lappel rcursif
est suivi dun traitement. Cela implique quil reste un
traitement reprendre ultrieurement.
Pour drcursiver une rcursivit non terminale, il va
falloir sauvegarder, sur une pile, le contexte de lappel
rcursif, typiquement les paramtres de lappel
engendrant lappel rcursif.
medbecha 2010

Drcursivation (suite)
Rcursivit non terminale

Drcursivation

ALGORITHM Q(U)
Begin
if C(U) then
D(U);Q((U));F(U)
else T(U)
End

ALGORITHM Q(U)
Begin
Stack.init()
while C(U) do
D(U)
Stack.push(U)
U = (U)
T(U)
while not Stack.empty() do
Stack.pop(U)
F(U)
End

medbecha 2010

Drcursivation (suite)

Exemple dexcution de Q/Q :


Appel Q(U0)
C(U0) vrai
D(U0)
Appel Q((U0))
C((U0)) vrai
D((U0))
Appel Q(((U0)))
C(((U0))) faux
T(((U0)))
F((U0))
F(U0)
medbecha 2010

Drcursivation (suite)
Version rcursive

Drcursivation

Foo (n)
Begin
if n > 0 then
display(\n IN n=+n+\n)
Foo(n-1)
display(\n OUT n=+n+\n)
else
display(\n Terminated \n)
End

Foo (n)
Begin
Stack.init()
while n>0 do
display(\n IN n=+n+\n)
Stack.push(n)
n = n-1
display(\n Terminated \n)
while not Stack.empty() do
Stack.pop(n)
display(\n OUT n=+n+\n)
End

medbecha 2010

Drcursivation (suite)
Remarques :
Les programmes itratifs sont souvent plus efficaces, mais
les programmes rcursifs sont plus faciles crire.
Les compilateurs savent, la plupart du temps, reconnatre
les appels rcursifs terminaux, et ceux-ci nengendrent pas
de surcot par rapport la version itrative du mme
programme.
Il est toujours possible de drcursiver un algorithme
rcursif.
medbecha 2010

Paradigme Diviser pour rgner


Principe : Nombres dalgorithmes ont une structure rcursive : pour
rsoudre un problme donn, ils sappellent eux-mmes rcursivement
une ou plusieurs fois sur des problmes trs similaires, mais de tailles
moindres, rsolvent les sous problmes de manire rcursive puis
combinent les rsultats pour trouver une solution au problme initial. Le
paradigme diviser pour rgner donne lieu trois tapes chaque
niveau de rcursivit :
Diviser : le problme en un certain nombre de sous-problmes ;
Rgner : sur les sous-problmes en les rsolvant rcursivement ou, si la taille
dun sous-problme est assez rduite, le rsoudre directement ;
Combiner : les solutions des sous-problmes en une solution complte du
problme initial.
medbecha 2010

Paradigme Diviser pour rgner (suite)


Exemple: multiplication de matrices (ci-dessous solution naf)
MULTIPLY-MATRIXES(A, B) given A,B squared maxtrixes of size n
Begin
for i = 1 to n do
for j = 1 to n do
C(i,j) = 0
for k = 1 to n do
C(i,j) = C(i,j) +A(i,k) * B(k,j)
return C
End
Cet algorithme effectue (n3) multiplications et autant dadditions.
medbecha 2010

Paradigme Diviser pour rgner (suite)

Algorithme diviser pour rgner naf


Dans la suite nous supposerons que n est une puissance exacte de 2. Dcomposons les matrices A,
B et C en sous-matrices de taille n 2 n 2 . Lquation C = A x B peut alors se rcrire :
r s a b e



t
u
c
d

En dveloppant cette quation, nous obtenons :


r ae bg ; s af bh ; t ce dg ; u cf dh

Chacune de ces quatre oprations correspond deux multiplications de matrices carrs de taille
n/2 et une addition de telles matrices. partir de ces quations on peut aisment driver un
algorithme diviser pour rgner dont la complexit est donne par la rcurrence :

T (n) 8T ( n ) (n 2 )
2

laddition des matrices carrs de taille n 2 tant en (n).


medbecha 2010

Paradigme Diviser pour rgner (suite)


Analyse des algorithmes diviser pour rgner
Lorsquun algorithme contient un appel rcursif
lui-mme, son temps dexcution peut souvent
tre dcrit par une quation de rcurrence qui
dcrit le temps dexcution global pour un
problme de taille n en fonction du temps
dexcution pour des entres de taille moindre.
medbecha 2010

Paradigme Diviser pour rgner (suite)


Analyse des algorithmes diviser pour rgner (suite)
La rcurrence dfinissant le temps dexcution dun algorithme diviser pour
rgner se dcompose suivant les trois tapes du paradigme de base :
1. Si la taille du problme est suffisamment rduite, n c pour une certaine
constante c, la rsolution est directe et consomme un temps constant (1).
2. Sinon, on divise le problme en a sous-problmes chacun de taille 1/b de la taille
du problme initial. Le temps dexcution total se dcompose alors en trois
parties :
a) D(n)
b) aT(n/b)
c) C(n)

: le temps ncessaire la division du problme en sous-problmes.


: le temps de rsolution des a sous-problmes.
: le temps ncessaire pour construire la solution finale partir des solutions aux sousproblmes.
medbecha 2010

Paradigme Diviser pour rgner (suite)


La relation de rcurrence prend alors la forme :
(1) si n c

T ( n)
aT ( n ) D(n) C (n) si non

o lon interprte b soit comme b , soit comme


n

medbecha 2010

n
b

Paradigme Diviser pour rgner (suite)


Thorme 1 (Rsolution des rcurrences diviser pour rgner ).
Soient a 1 et b>1 deux constantes, soit f(n) une fonction et soit T(n) une
fonction dfinie sur les entiers positifs par la rcurrence:
T(n) = a T(n/b)+f(n),
n
o lon interprte n/b soit comme n b , soit comme
b
T(n) peut alors tre borne asymptotiquement comme suit:
Si f(n) = O(n(logba)-) pour une certaine constante > 0,
alors T(n) = (nlogba).
Si f(n) = (nlogba), alors T(n) = (nlogba log2(n))
Si f(n) = (n(logba)+) pour une certaine constante > 0, et si a f(n/b) c f(n)
pour une constante c<1 et n suffisamment grand, alors T(n) = (f(n)).

medbecha 2010

Paradigme Diviser pour rgner (suite)


Pour une dmonstration de ce thorme voir Rivest-Carmen-Etal
Il existe d autres mthodes de rsolution des rcurrences : par
substitution, changement de variables etc.
n
Le remplacement des termes T(n/b) par T n b ouT b naffecte pas
le comportement asymptotique de la rcurrence. On omettra donc
en gnral les parties entires.
Le thorme 1 ne couvre pas toutes les possibilit pour f(n). Par
exemple, il y a un trou entre les cas 1 et 2 quand f(n) est plus
petite que nlogba, mais pas polynomialement. Dans un tel cas, on ne
peut tout simplement pas appliquer le thorme 1.
medbecha 2010

Paradigme Diviser pour rgner (suite)


Thorme 2
Soient a 1, b>1 et c>0 trois constantes, soit T(n) une
fonction dfinie sur les entiers positifs par la rcurrence:
T(n) = a T(n/b)+c nk, (kIN)
alors:
Si a>bk alors T(n) = (nlogba)
Si a=bk alors T(n) = (nk log2(n))
Si a<bk alors T(n) = (nk)

medbecha 2010

Paradigme Diviser pour rgner (suite)


Utilisons le thorme 1 pour calculer la complexit de
notre algorithme de multiplication de matrices
diviser pour rgner naf. Ici, a = 8, b = 2 et f (n) =
(n2). Donc logb a = 3, nous nous trouvons dans le cas
1 du thorme (avec = 1), lalgorithme a une
complexit en (n3) et nous navons rien gagn...
Pour une solution plus efficace voir lalgorithme de
Strassen pour la multiplication de matrices creuses ou
plus rcemment Coppersmith & Winograd (1987).
medbecha 2010

Paradigme Diviser pour rgner (suite)


Exemple (1) avec thorme 2

Exemple (2) avec thorme 2

T(n) = 9 T(n/3) + n
Ici a = 9, b = 3, c = k = 1.
a = 9 > bk = 31
Donc on applique le cas 1 du
thorme 2 :
T(n) = (nlog39) = (n2)

T(n) = T(2n/3) + 1
Ici a = 1, b = 3/2, c = 1 et k = 0
a = 1 = bk = (3/2)0 = 1
Donc on applique le cas 2 du
thorme 2 :
T(n) = (n0log2n) = (log2n)

medbecha 2010

Paradigme Diviser pour rgner (suite)


Autre exemple avec le thorme 1 :
T(n) = 3T(n/4) + n.log(n)
Ici, a = 3, b = 4 et f (n) = n.log(n).
nlogba = nlog43 = O(n0,793) f(n) = (nlog43+) avec 0,2
Pour n suffisamment grand on a:
af(n/b) = 3(n/4)log(n/4) (3/4) nlog(n) = c.f(n) avec c =
On applique donc le cas 3 du thorme:
T(n) = (nlog(n))
medbecha 2010

Paradigme Diviser pour rgner (suite)


Equations de rcurrence linaires :
1er cas : quations homognes
Une quation de rcurrence est dite homogne si elle a la forme
suivante:
a0tn + a1tn-1+ ... + aktn-k = 0 (1)
pour trouver sa solution gnrale, on procde comme suit:
a) Etablir son quation caractristique (un polynme de degr k)
a0xk + a1xk-1+ ... ak = 0
calculer ses racines: r1, r2, ... ,rk
medbecha 2010

Paradigme Diviser pour rgner (suite)


b) Si toutes les racine ri sont distinctes, alors la solution
gnrale de (1) est donne par :
tn = C1r1n + C2r2n + ... Ckrkn (2)
o les Ci sont des constantes que lon peut dterminer avec
les conditions initiales de lquation de rcurrence.
c) Si rj est une solution multiple (de multiplicit m : apparat
m fois comme solution de lquation caractristique), alors
la solution gnrale de (1) est donne en remplaant dans
(2) le terme Cjrjn par la somme : Cj1rjn + Cj2nrjn + Cj3n2rjn ...
Cjmnm-1rjn
medbecha 2010

Paradigme Diviser pour rgner (suite)

Exemples :
1) Soit :

tn - 3 tn-1 - 4 tn-2 = 0
(forme gnrale)
t 0 = 0 , t1 = 1
(conditions initiales)
son quation caractristique est : x2 3x 4 = 0
2 racines distinctes : r1 = -1 et r2 = 4
donc la solution gnrale est : tn = C1(-1)n + C2 4n (4n)
en appliquant les conditions initiales on trouve C1=1/5 et C2=1/5
2) Soit :
tn - 5 tn-1+ 8 tn-2 - 4 tn-3 = 0 (forme gnrale)
t0 = 0 , t1 = 1 , t2 = 2 (conditions initiales)
son quation caractristique est : x3 5 x2 + 8 x 4 = 0 ou alors : (x-1)(x-2)2 = 0
3 racines : 1, 2 et 2 (2 est une solution multiple de multiplicit = 2)
donc la solution gnrale est : tn = C11n + C22n + C3n2n (2n)
les conditions initiales donnent : C1 = 2, C2 = 2 et C3 =
medbecha 2010

Paradigme Diviser pour rgner (suite)


2me cas : quations non homognes:
Une quation de rcurrence est dite non homogne si elle a la
forme suivante:
a0tn + a1tn-1+ ... + aktn-k= b1nP1(n) + b2nP2(n) +b3nP3(n)+ ... (3)
o les bi sont des constantes distinctes et les Pi(n) des polynmes en
n de degr di
La rsolution dune telle quation suit le mme schma que celui
des quations homognes en partant de lquation caractristique
suivante :
(a0xk + a1xk-1+ ... +ak) (x-b1)d1+1 (x-b2)d2+1 (x-b3)d3+1 ... = 0
medbecha 2010

Paradigme Diviser pour rgner (suite)


Exemple:
Soit :

tn 2tn-1 = n +2n (forme gnrale)


t0 = 0
(conditions initiales)
cest une quation non homogne avec :
b1 = 1 , P1(n) = n , d1 = 1
b2 = 2 , P2(n) = 1 , d2 = 0
son quation caractristique est donc : (x-2)(x-1)2 (x-2)= 0 dont les racines
sont : 2, 1, 1, 2
donc les racines 1 et 2 sont, chacune, de multiplicit 2
La solution gnrale est alors donne par : tn = C11n + C2n1n + C32n + C4n2n
(2n)
medbecha 2010

Paradigme Diviser pour rgner (suite)


Illustration : Cas du tri par fusion
Principe du tri par fusion : Lalgorithme de tri par fusion est construit
suivant le paradigme diviser pour rgner :
1. Il divise la squence de n nombres trier en deux sous-squences de
taille n/2.
2. Il trie rcursivement les deux sous-squences.
3. Il fusionne les deux sous-squences tries pour produire la squence
complte trie.
La rcursion termine quand la sous-squence trier est de longueur 1 car
une telle squence est toujours trie.
medbecha 2010

Paradigme Diviser pour rgner (suite)


FUSION-SORT given A,l,r
Begin
if l<r then
m = |(l+r)/2|
FUSION-SORT(A,l,m)
FUSION-SORT(A,m+1,r)
FUSIONNER(A,l,m,r)
End
medbecha 2010

Paradigme Diviser pour rgner (suite)


Complexit
Pour dterminer la formule de rcurrence qui nous donnera la complexit
de lalgorithme FUSION-SORT, nous tudions les trois phases de cet
algorithme diviser pour rgner :
Diviser : cette tape se rduit au calcul du milieu de lintervalle [l..r]
Rgner : lalgorithme rsout rcursivement deux sous-problmes de
tailles respectives n/2
Combiner : la complexit de cette tape est celle de lalgorithme de
fusion qui est de (n) pour la construction dun tableau solution de
taille n.
medbecha 2010

Paradigme Diviser pour rgner (suite)


Par consquent, la complexit du tri par fusion est donne par la
(1) si n c

rcurrence :

T ( n)
2T ( n ) (n) si non

Pour dterminer la complexit du tri par fusion, nous utilisons de nouveau


le thorme.
Ici a=2 et b=2 donc logba = 1, et nous nous trouvons dans le deuxime cas du
thorme f(n) = (nlogba) = (n)
par consquent :
T(n) = (n.log2(n))
Pour des valeurs de n suffisamment grandes, le tri par fusion avec son temps
dexcution en (n.log(n)) est nettement plus efficace que le tri par insertion
dont le temps dexcution est en (n2).
medbecha 2010

Conclusion
Il existe plusieurs solutions algorithmique un mme
problme (ou classe de problmes).
Le but de lalgorithmique cest de trouver une
solution optimale chaque classe de problmes
considrs.
Lalgorithmique propose des outils pour atteindre ce
but: lanalyse de la complexit, la drcusivation, et
le paradigme diviser pour rgner
medbecha 2010

Annexe 1 : Complexit, comparatif


Notation

Type

n=20

n=50

n=250 n=104 n=106 Exemple dalgo

(1)

Constante

10ns

10ns

10ns

10ns

10ns

Accs tableaux

(log(n))

logarithmique

10ns

20ns

30ns

40ns

60ns

Dichotomie

(n)

linaire

200ns 500ns 2.5s

100s 10ms

Parcours de liste

(nlog(n))

quasi-linaire

260ns 850ns 6s

400s 60ms

Tri Fusion

(n2)

quadratique

4s

25s

625s 1s

2h48

(n3)

Cubique

80ms

1.25ms

156ms

2h42

316ans

(nlog(n))

quasi-polyno.

492ns 7s

5ms

3.2ans

1020ans

(en)

Exponentielle

10ms

130j

1059ans

Fact. premiers

(n!)

Factorielle

770ans

1048ans

Voyag. Commer.

medbecha 2010

Tri insertion

Annexe 2: Illustration
Problme : la plus grande somme contigu
Le but est dlaborer un algorithme permettant de calculer
la plus grande somme contigu dentiers placs dans un
tableau.
tant donn un tableau A[0..n-1] de n nombres entiers
positifs ou ngatifs, comment dterminer la valeur
maximale des sommes correspondantes aux sections de la
forme A[i..j[ ??
On notera que 0 est la somme de nimporte quelle section
vide A[i..i[
medbecha 2010

Annexe 2: Illustration (suite)


Exemple:
i 0 1 2 3 4 5 6 7 8 9
A 31 -41 59 26 -53 58 97 -93 -23 84

la somme maximale est:


A[2..7[ = A[2..6] = 187

medbecha 2010

Annexe 2: Illustration (suite)


Solution triviale:
PGSC_1
given n > 0 and A an array of integers
Begin
Maximum = 0;
for i = 0 to n-1 do
for j=i to n-1 do
Sum = 0
for k = i to j do
Sum = Sum + A[k]
if(Sum>Maximum)
Maximum = Sum
return Maximum;
END

Complexit en (n3) !

medbecha 2010

Annexe 2: Illustration (suite)

Une meilleure ide consiste


ne
pas
recalculer
systmatiquement les sommes
mais utiliser la relation:
j 1

a a
k i

k i

a j 1

Do le nouveau programme
en (n2) :

PGSC_2 given n>0 and A an array


Begin
Maximum = 0;
for i = 0 to n-1 do
Sum = 0
for j=i to n-1 do
Sum = Sum + A[j]
if(Sum>Maximum)
Maximum = Sum
return Maximum;
END

medbecha 2010

Annexe 2: Illustration (suite)


On peut essayer une approche dichotomique
en coupant le tableau en deux parties de
tailles quivalentes et en disant que la somme
maximale est ralise soit totalement dans la
partie droite, soit totalement dans la partie
gauche, soit cheval. Cette ide nous conduit
lalgorithme rcursif suivant:
medbecha 2010

Annexe 2: Illustration (suite)


PGSC_3 given A, l, r
Begin
if (l>r) then return 0
if (l=r) then
if(A[l] > 0) return A[l]
else return 0
m= (l+r)/2;
max_1 = 0; sum = 0;
for i=m to l step -1 do
sum = sum + A[i];
if(sum > max_1) then
max_1 = sum;
max_2 = 0; sum = 0;

for i= m +1 to r do
sum = sum + A[i];
if(sum> max_2) then
max_2 = sum;
maximum = max1 + max2;
sum = PGSC_3(A,l,m);
if(sum>maximum) then
maximum = sum;
sum = PGSC_3(A,m+1,r);
if(sum>maximum) then
maximum = somme;
return maximum;
END
medbecha 2010

Annexe 2: Illustration (suite)


Complexit de PGSC_3
Paradigme Diviser pour rgner
On invoque cette version par lappel PGSC_3(A,0,n-1)
do lquation de rcurrence: T(n) = 2T(n/2) + (n)
Ici a=2, b=2 et f(n) = (n), nous sommes dans le cas 2
du thorme 1 car f(n) = (nlogba) = (nlog22) = (n)
Conclusion T(n) = (nlog(n))
medbecha 2010

Annexe 2: Illustration (suite)


Mais on peut encore mieux faire. Lide cette fois
est de parcourir une seule fois le tableau et de
maintenir simultanment deux maximums: la
plus grande somme max_1 et un max2 qui
est remis zro chaque fois quil devient ngatif.
La plus grande somme recherche est gale soit
max_1 soit max_2 do lalgorithme en
(n):
medbecha 2010

Annexe 2: Illustration (suite)


PGSC_4
given n > 0 and A an array of integers
Begin
Max_1 = 0, Max_2 = 0
for i = 0 to n-1 do
Max_2 = Max_2 + A[i]
if(Max_2<0) then
Max_2 = 0
if( Max_2 > Max_1) then
Max_1 = Max_2
return Max_1;
END
medbecha 2010