Sie sind auf Seite 1von 2

UNIVERSITE DE CAEN Licence Informatique L2 2005/2006

U.F.R de Sciences Modélisation Mathématique et Informatique (INF34)

Cours 3 : Grands principes de programmation (2/2)

1 Programmation dynamique

Programmation dynamique : principe algorithmique consistant à éviter de résoudre


plusieurs fois un même sous-problème lors de la résolution d'un problème, en com-
mençant par résoudre les petits problèmes et en stockant les résultats.

2 Nombres de Fibonacci

Suite de Fibonacci : dénie par u0 = u1 = 1 et ∀n ≥ 2, un = un−1 + un−2 .

Calcul naïf : on calcule un de façon récursive, en utilisant la dénition. Par exemple,


pour calculer u4 , on additionnne u3 et u2 , que l'on calcule récursivement. Ainsi, pour
calculer u3 , on additionne u2 et u1 ; on a donc calculé u2 deux fois. De façon générale,
pour calculer un on utilise le nombre d'additions utilisées pour calculer un−1 , auquel
s'ajoutent les additions utilisées pour calculer un−2 et celle utilisée pour sommer
un−1 et un−2 . On voit donc par récurrence que le nombre d'additions √ nécessaires
pour calculer un est un − 1 ; or un croît comme o , où n = (1 + 5/2) est le nombre
n

d'or (on peut en eet voir par récurrence que pour tout n on a on−1 ≤ un ≤ on ).

Calcul en programmation dynamique : on calcule tout d'abord u2 à partir de u0 et


u1 , ce qui nécessite une addition. On stocke alors la valeur de u2 , puis on calcule
u3 à partir de u1 et u2 , en une addition ; on stocke u3 , et ainsi de suite jusqu'à un .
On a alors besoin de seulement n − 1 additions pour calculer un . On peut de plus
utiliser seulement 3 cases mémoires, puisqu'à tout moment on a seulement besoin
de ui−1 , ui−2 et ui : une fois ui calculé, on peut eacer ui−2 . L'algorithme est donc
le suivant :

Entrée : Un entier positif n


Sortie : Le ne nombre de Fibonacci un

Si n = 0 ou n = 1 alors renvoyer 1 nsi ;


/* Sinon ( n ≥ 2) : */

ui−2 = 1 ; /* c'est-à-dire u0 , initialement */

ui−1 = 1 ; /* c'est-à-dire u1 , initialement */

1
Pour i de 2 à n − 1 faire ui = ui−1 + ui−2 , ui−2 = ui−1 , ui−1 = ui Fin pour ;
/* Par construction, ui−1 = un−1 et ui−2 = un−2 : */

renvoyer ui−1 + ui−2 ;

3 Diviser pour régner

Diviser pour régner : principe algorithmique consistant, pour résoudre un problème

de taille n, à le diviser en plusieurs parties, à les résoudre indépendamment (de façon


récursive), puis à combiner leurs solutions.

La complexité d'un algorithme de ce type dépend tout d'abord de la taille des


parties ; en général, on divise un problème de taille n en deux sous-problèmes chacun
de taille n/2. La complexité dépend également de la complexité de l'algorithme de
combinaison des sous-solutions. Si cette phase est trop coûteuse, un algorithme de
ce type n'est pas intéressant.

La phase de combinaison est parfois remplacée par une phase de séparation du


problème, qui se situe alors avant les appels récursifs de l'algorithme sur les sous-
problèmes.

4 Tri fusion

Tri fusion : algorithme de type  diviser pour régner  pour trier un tableau de
nombres.

Séparation et appels récursifs: pour trier un tableau de n nombres, on le sépare en


deux parties de taille n/2 chacune, en  coupant  simplement le tableau au milieu.
On trie chaque partie avec le même algorithme, et on arrête la récursivité quand on
a des tableaux contenant un seul nombre.

Phase de combinaison : puisque chaque moitié est triée, on sait que le minimum du
tableau global est le premier nombre de l'une des deux moitiés. On compare donc
les deux premiers nombres, et on déplace le plus petit vers le résultat. On peut donc
recommencer récursivement jusqu'à épuisement des deux moitiés.

Complexité : la séparation prend un temps constant, puisqu'il sut de diviser la


longueur du tableau par deux et d'utiliser des indices pour délimiter la sous-partie
à trier (pas besoin de recopier le tableau). La fusion prend un temps linéaire O(n),
puisque pour placer un nombre dans le résultat il sut d'une comparaison entre
deux nombres. En notant c(n) la complexité du tri d'un tableau à n éléments, on
a donc la relation de récurrence c(n) = 2c(n/2) + kn (aux constantes près), et
c(1) = ` (constant). On voit que c(n) = `n + kn log n satisfait la relation et donc, la
complexité est en O(`n + kn log n) = O(n log n).

Das könnte Ihnen auch gefallen