Algorithmique Avancee Et Complexite

  • Uploaded by: امين نفيد
  • 0
  • 0
  • March 2021
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Algorithmique Avancee Et Complexite as PDF for free.

More details

  • Words: 10,420
  • Pages: 101
Loading documents preview...
Université Mohammed Premier Ecole Nationale des Sciences Appliquées Al Hoceima

Algorithmique avancée et complexité E.W. DADI [email protected] Année universitaire : 2014/2015

Plan du Cours Chapitre 1: Introduction à l’algorithmique Chapitre 2: Complexité algorithmique Chapitre 3: Etude de quelques algorithmes

Chapitre 4: Programmation dynamique Chapitre 5: Calcul Haute Performance

ENSAH

Introduction générale

E.W. DADI – page : 2

Références : Thomas Cormen, Charles Leiserson, Ronald Rivest, Clifford Stein, « INTRODUCTION À L’ALGORITHMIQUE », Dunod, Paris, 2004. Rémy Malgouyres, Rita Zrour, Fabien Feschet, « INITIATION À L’ALGORITHMIQUE ET À LA PROGRAMMATION EN C », Dunod, Paris, 2008, 2011 Bruno Baynat, «EXERCICES ET PROBLEMES D’ALGORITHMIQUE », Dunod, Paris. Donald E. Knuth « THE ART OF COMPUTING PROGRAMMING » Des supports de cours sur le Web

ENSAH

Introduction générale

E.W. DADI – page : 3

Objectifs du cours

Acquérir les notions nécessaires pour : analyser et classer les problèmes de différents domaines. construire la ou les solutions. évaluer les différentes solutions en terme de temps du calcul. Choisir la meilleure solution.

ENSAH

Introduction générale

E.W. DADI – page : 4

Utilisation des algorithmes Plusieurs domaines et applications reposent sur des algorithmes intelligents qui permettent de gérer et manipuler de grosses masses de données, à savoir : L’accès rapide à toutes sortes de données sur Internet. Réseau Informatique: Recherche de routes optimales pour l’acheminement des données; Un nœud de routage Internet peut avoir à déterminer le chemin le plus court à travers le réseau pour minimiser le délai d’acheminement d’un message. Moteur de recherche: utilisation d’un moteur de recherche pour trouver rapidement les pages contenant tel ou tel type de données; Sécurité Informatique: Le commerce électronique permet de négocier et échanger, de manière électronique, biens et services. Les clients exigent la confidentialité de données telles que numéros de carte de crédit, mots de passe et relevés bancaires. La cryptographie et les signatures numériques qui font partie des technologies fondamentales employées dans ce contexte, s’appuient sur des algorithmes numériques et sur la théorie des nombres. etc..

ENSAH

Introduction générale

E.W. DADI – page : 5

Pour quoi chercher des algorithmes efficaces? Le temps machine est une ressource limitée, et il en est de même de l’espace mémoire. La loi de Moore attient ses limites (G. Moore a prévu un doublement du nombre de transistors tous les 24 mois). L'augmentation de la puissance de calcul en élevant la fréquence du processeur s’est heurtée à plusieurs problèmes généralement liées à la surchauffe. Les contraintes économiques obligent à toujours produire dans l'urgence. Les entreprises cherchent toujours à maximiser leur profit. Il existe beaucoup de solutions à priori, mais la plupart d’entre elles ne sont pas celles que nous voulons. Trouver une solution qui convienne vraiment, n’est pas toujours évident.

ENSAH

Introduction générale

E.W. DADI – page : 6

…. la suite

Problèmes nécessitant un grande temps d’exécution L'exploration de grande volume de données(Big Data) Les prédictions météorologique La modélisation et simulation de problèmes de dimensions plus grandes, la modélisation et la simulation sur ordinateur ont pour objet de créer une représentation virtuelle d’un objet, d’un phénomène ou d’un concept afin de l’analyser et de le comprendre, de façon à pouvoir prévoir son comportement, voire le contrôler. l’étude de systèmes et de phénomènes complexes. Elle repose désormais sur la gestion et l'utilisation d’une masse d’information qu’il faut systématiser, recueillir, distribuer et exploiter l'intelligence artificielle Le décryptage de messages et la recherche de mots de passe

ENSAH

Introduction générale

E.W. DADI – page : 7

Chapitre 1: Introduction à l’algorithmique

Plan du chapitre I.

Notion d’algorithme

II.

Un langage pour décrire les algorithmes

III. Algorithmes itératifs et récursifs

IV. Preuve d’un algorithme

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 9

I. Notion d’algorithme 1. Qu'est-ce qu'un algorithme ? Un algorithme est une suite finie d’opérations élémentaires constituant un schéma de calcul ou de résolution d’un problème. La résolution d’un problème algorithmique par un algorithme commence par la spécification des données en entrée (Input) et des données en sortie (Output). Données en entrée: l'ensemble complet des instances (Input) de l’algorithme sur lesquelles il va travailler; Données en sortie : Sa production (Output) après son exécution sur une de ces instances. Exemple: Le problème algorithmique connu sous le nom du problème de tri est défini comme suit : Problème : le tri. Input : une liste de n clés . Output : une permutation de la liste d'entrée qui soit ordonnée : a1'  …  an'. Une instance du problème de tri pourrait être : Une liste de numéros comme <14, 25, 58, 34, 64, 34>; Une liste de noms comme <nom1, nom2, nom3, nom4>;

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 10

2. Pluralité des solutions algorithmiques Pour un même problème algorithmique, il peut exister plusieurs algorithmes différents : Certains itératifs, d’autres récursifs; Certains sont plus rapides que les autres; Certains utilisent moins d’espace mémoire que d’autres; …etc. Par exemple pour trier un tableau il y a beaucoup d’algorithmes différents : tri par sélection, tri par insertion, tri à bulles, tri par fusion, tri rapide, tri par tas, …etc.

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 11

3. Propriétés d’un bon algorithme

Il y a trois propriétés désirables pour un bon algorithme : Correction; Efficacité; Facilité à mettre en œuvre;

Ces trois objectifs ne peuvent pas toujours être tous atteints simultanément.

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 12

II. Un langage pour décrire les algorithmes 1. Structure générale d’un algorithme Pour la définition d'un problème on utilise un langage scientifique. Pour des raisons de simplicité, on utilise une langue naturelle(le français par exemple) Algorithme Fonction Nom_Fonction(Input) : Output Var … // variables Début … // actions Fin

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 13

2. Les différents éléments d’un algorithme

     

Type de données Entier; Réel; Caractère; Chaînes de caractères; Booléen (vrai / faux); Tableau;

    

ENSAH

Opérations de base  +-*/%  , , , , = et   Non, Et, Ou  := (affectation)  Afficher  Lire

Structures de contrôle Si … Alors … Sinon … FinSi Pour … Faire … FinPour Tant Que … Faire … FinTQ Répéter … Jusqu’à … FinRép Retourner …

Introduction à l’algorithmique

E.W. DADI – page : 14

III. Algorithmes itératifs et récursifs 1. Algorithmes itératifs Un algorithme itératif résout un problème en calculant son résultat par une méthode d’approximation successive. Ses composants sont : Initialisation : préciser la valeur adéquate de départ. Approximation : décrire la manière de s’approcher du résultat. Progression : indiquer la façon d’aller d’une étape à une autre.

Les boucles sont un moyen pour décrire un algorithme itératif.

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 15

2. Algorithmes récursifs Un algorithme récursif est constitué d’une fonction récursive. Une fonction est dite récursive si elle s’appelle elle-même. L’appel d’une fonction à l’intérieur d’elle-même est nommé appel récursif. Un appel récursif doit obligatoirement être dans une instruction conditionnelle (sinon la récursivité est sans fin). Ses composants sont : Cas de base (condition d’arrêt) : le problème peut se résoudre d’une manière directe. La donnée est suffisamment petite pour qu’elle puisse traitée de façon simple. Appel récursif (récurrence) : le problème se résout en utilisant un algorithme identique mais sur une donnée plus petite.

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 16

…. la suite

Exemple 1 : un exemple concrète d’une fonction récursive est la suite de Fibonacci qui définien   par :

 U n  1, n  2  U n  U n2  U n1 , n  1

ENSAH

Introduction à l’algorithmique

Cas de base

Appel récursif

E.W. DADI – page : 17

…. la suite

Les étapes à suivre pour programmer une fonction récursive sont : On décompose le problème en un ou plusieurs sousproblèmes du même type. On résout les sous-problèmes par des appels récursifs. Les sous-problèmes doivent être de taille plus petite que le problème initial.

Enfin, la décomposition doit en fin de compte conduire à un cas élémentaire, qui, lui, n’est pas décomposé en sousproblème. (condition d’arrêt).

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 18

…. la suite

Exemple 2 : Problème de calcule de factorielle n! Fact(n)= n! ( n - 1 )! * n =Fact(n-1) * n ( n - 2 )! * ( n-1 ) * n =Fact(n-2) * ( n-1 ) * n ( n - 3 )! * ( n-2 ) * ( n-1 ) * n =Fact(n-3) * ( n-2 )* ( n-1 ) * n . . . 0! * ….* ( n-2 )* ( n-1 ) * n =Fact(0)*….* ( n-2 )* ( n-1 ) * n

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 19

3. Des exemples: algorithmes itératifs et récursifs Pour montrer la différence et comment se fait le passage entre un algorithme itératif vers un algorithme récursif, on va utiliser quatre exemples, pour chacun on va donner la version itérative et récursive. Exemple 1: un algorithme qui calcule la somme des entiers entre 1 jusqu'à N. Exemple 2: un algorithme qui calcule le factorielle (N!). Exemple 3: un algorithme qui calcule x à la puissance N. Exemple 4: un algorithme qui permet trouver le plus grand élément d’un tableau de N entiers.

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 20

…. la suite

Exemple 1: Algorithme itératif Fonction somme(N : Entier) : Entier; Var i, S : Entier; Début S := 0; // Initialisation Pour i allant de 1 jusqu'a N Faire // Progression S := S + i; // Approximation Fin Retourner S; Fin

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 21

…. la suite

Exemple 1: Algorithme récursif Fonction somme(N : Entier) : Entier; Début Si (N=0) Alors Retourner N; Sinon Retourner somme(N-1)+N; FinSi Fin Idée de la récursivité : SN = 1 + 2 + … + N SN = (1 + 2 + … + N - 1) + N SN = SN-1 + N // appel récursif S0 = 0 // cas de base

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 22

…. la suite

Exemple 2: Algorithme itératif Fonction factorielle(N : Entier) : Entier; Var i, f : Entier; Début f := 1; // Initialisation Pour i allant de 1 jusqu'a N Faire // Progression f := f * i; // Approximation Fin Retourner f; Fin

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 23

…. la suite

Exemple 2: Algorithme récursif Fonction factorielle(N : Entier) : Entier; Début Si (N=0) Alors Retourner 1; Sinon Retourner factorielle (N-1) * N; FinSi Fin

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 24

…. la suite

Exemple 3: Algorithme itératif Fonction puissance(x: Réel, N : Entier) : Réel; Var i, p : Entier; Début p := 1; // Initialisation Pour i allant de 1 jusqu'a N Faire // Progression p := p * x; // Approximation Fin Retourner p; Fin

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 25

…. la suite

Exemple 3: Algorithme récursif Fonction puissance(x: Réel, N : Entier) : Réel; Début Si (N=0) Alors Retourner 1; Sinon Retourner puissance (x, N-1) * x; FinSi Fin

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 26

…. la suite

Exemple 4: Algorithme itératif Fonction MaxTableau(A: Tableau, N : Entier) : Entier; Var i, max : Entier; Début max := A[1]; // Initialisation Pour i allant de 2 jusqu'a N Faire // Progression Si (A[i] > max) Alors max:=A[i]; FinSi Fin Retourner max; Fin

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 27

…. la suite

Exemple 4: Algorithme récursif Fonction MaxTableau(A: Tableau, N : Entier) : Entier; Début Si (N=1) Alors Retourner A[1]; Sinon Retourner max(MaxTableau(A, N-1) , A[N]); FinSi Fin Idée de la récursivité : Cas de base : si le tableau a un seul élément (N = 1), son plus grand élément est A[1]. Appel récursif : si n > 1, le plus grand élément de A[1…N] est le plus grand entre A[N] et le plus grand élément de A[1…N-1]. ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 28

IV. Preuve d’un algorithme 1. Présentation Prouver un algorithme c’est de: Vérifier qu’il se termine (preuve de terminaison) : l’algorithme effectue un traitement qui nécessite un nombre fini d’opérations élémentaires c’est-à-dire qu’il aboutit au résultat au bout d’un nombre fini d’étapes. Vérifier qu’il est correct (preuve de correction) : l’algorithme fait bien ce qu’il est supposé faire dans sa spécification c’est-à-dire qu’il produit toujours le bon résultat pour toutes les instances du problème.

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 29

2. Preuve de terminaison La première qualité attendue d'un algorithme est bien sur sa terminaison c’est-à-dire qu'il n'admette aucune instance pour laquelle l’exécution rentre dans une boucle infinie. Ce n’est pas toujours évident de prouver qu'un algorithme se termine. Par exemple, la communauté scientifique n'a pas réussi à prouver la terminaison de l'algorithme suivant: Fonction syracuse(n : Entier) : mot; Début Tantque ( N  1) Faire Si (N est pair ) Alors N:=N/2; Sinon N:=3*N+1; FinSi FinTq Retourner fini; Fin

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 30

…. la suite

Comment prouver qu’un algorithme se termine? Il n’y a pas de méthodes exactes pour prouver la terminaison car dans la plupart des cas ça dépend de la nature de l’algorithme.

Pour le cas des algorithmes itératifs, on analyse généralement la condition d’arrêt de la boucle. Pour le cas des algorithmes récursifs on procède par récurrence. Pour prouver la terminaison d’une fonction récursive, il faut montrer que la fonction parvient toujours au traitement de cas de base en un nombre fini d’appels récursifs.

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 31

3. Preuve de correction Pour le cas des algorithmes itératifs, la méthode générale consiste à utiliser une propriété, dite « invariant de boucle » liant les éléments variables d’une boucle et qui reste vraie quelque soit le nombre de passage dans celle-ci. Cette propriété se démontre par récurrence. Pour le cas des algorithmes récursifs, on doit déterminer la fonction calculée par l’algorithme. Pour prouver que l’algorithme est correct on applique aussi la démonstration par récurrence.

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 32

4. Exemples Exemple 1: Preuve de l’algorithme itératif suivant : Fonction somme(N : Entier) : Entier; Var i, S : Entier; Début 1. 2. 3. 4. 5. Fin

S := 0; Pour i allant de 1 jusqu'à N Faire S := S + i; Fin Retourner S;

Preuve de terminaison : L’instruction (1) se termine. La boucle (Pour) sera exécutée N fois. Le corps de la boucle est formé de l’instruction (3) qui se compose d’une somme et d’une affectation, donc elle se termine. Par conséquent, l’algorithme se termine.

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 33

…. la suite

Preuve de correction : a.

Trouver un invariant de boucle : On notera par « xi » la valeur de la variable « x » à la fin de l’itération « i ». Les faits : - S0 = 0; i0 = 1; Sj = Sj-1 + ij-1; pour j > 0 - ij = ij-1 + 1; pour j > 0 alors ij = j + 1; pour j >= 0. D’après ce qui précède on déduit l’invariant de boucle : Sj = 1 + 2 + … + j; pour j > 0. b. Démonstration par récurrence : N Pour notre exemple, nous allons considérer la propriété : « P(N) : S N   i » i 1 On va vérifier que la propriété est vraie tout N≥0 : Cas de bas P(0): S0 = 0 (correspond à la phase d’initialisation). Donc P(0) est vraie. Cas récursifs : soit N ≥ 1 et supposons que la propriété P(N) est vraie. Montrons qu’elle est vraie pour N+1. Après l’itération (N+1), on a N N 1 S N 1  S N  N  1   i  ( N  1)   i , ce qui vérifier que l’algorithme est correct i 1

ENSAH

i 1

Introduction à l’algorithmique

E.W. DADI – page : 34

…. la suite

Exemple 2: Preuve de l’algorithme itératif suivant : Fonction f(n : Entier) : Entier; Var x, y : Entier; Début 1. x := n; 2. y := n; 3. Tant Que (y  0) Faire 4. x := x + 2; 5. y := y - 1; 6. FinTQ 7. Retourner x; Fin

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 35

…. la suite

Preuve de terminaison : La condition de continuation de la boucle « Tant Que » est y ≠ 0. La valeur initiale de y est n ≥ 0. Après chaque itération, la valeur de y décroît d’une unité jusqu’à devenir 0. À ce moment, la boucle « Tant Que » se termine après avoir été exécutée n fois. Par suite, l’algorithme se termine. Preuve de correction : a. Trouver un invariant de boucle : D’après les faits: Les faits :  xj = xj-1 + 2  x0 = n; = xj-2 + 2 + 2  y0 = n; = x0 + 2j = n + 2j  xj = xj-1 + 2; pour j > 0  yj = yj-1 – 1 = yj-2 – 1 – 1  yj = yj-1 - 1; pour j > 0 = y0 – j = n – j Déduire l’invariant de boucle :  xj + 2yj = n + 2j + 2n – 2j = 3n  Alors l’invariant de boucle est xj + 2yj = 3n

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 36

…. la suite

b. Démonstration par récurrence : les contenues des variables x et y après l’itération j de la boucle. Définissons la propriété suivante : « P (j) : xj + 2yj = 3n » où n est l’argument de l’algorithme. Montrons qu’il s’agit bien d’un invariant de boucle. Cas de bas : on a x0 + 2y0 = n+2n=3n Donc la propriété P(0) est vraie. Cas récursifs : soit i ≥ 1 et supposons que la propriété P(i) est vraie, c’est-à-dire que xj + 2yj = 3n . Montrons que P(i +1) est vraie. À la fin de l’itération (i +1), on a : xj+1 + 2yj+1 = xj + 2 + 2yj – 2 = xj + 2yj = 3n Ce qui prouve P(i +1) est vérifiée. L’invariant de boucle est alors prouvé. Après la terminaison de l’exécution de la boucle, on a : yn = 0, xn = 3n - 2yn = 3n, Donc, l’algorithme retourne 3n.

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 37

…. la suite

Exemple 3: Preuve de l’algorithme récursif suivant : Fonction F(n: entier) :Entier Début 1. Si (n = 0) Alors Retourner 2 ; 2. Sinon Retourner F(n −1) * F(n −1) ; 3. FinSi Fin

Preuve de terminaison : Cas de base : l’appel de la fonction F avec le paramètre n = 0 retourne directement 2 sans faire aucun appel récursif. Dans ce cas l’algorithme se termine immédiatement. Cas récursifs : soit n ≥ 1 un entier et supposons que l’appel de la fonction F avec le paramètre n se termine c’est-à-dire F(n)=F(n-1)*F(n-1). L’appel de la fonction F avec le paramètre (n+1) entraîne deux appels récursifs à F avec le même argument n (F(n+1)=F(n)*F(n)). Ces deux derniers appels se terminent par hypothèse. Le résultat sera obtenu après multiplication de ces deux appels et puisqu’il s’agit d’une opération élémentaire qui se termine, alors, l’appel de F avec l’argument (n+1) se termine aussi. Par conséquent, l’algorithme se termine.

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 38

…. la suite

Preuve de correction :

Pour ce faire, il faut savoir tout d’abord que calcule cet algorithme pour un entier n donné en entrée. Deux méthodes sont possibles pour cet algorithme: Par le calcul des premières valeurs pour F :     

F(0) = 2 F(1) = F(0) * F(0) = 22 F(2) = F(1) * F(1) = 22 * 22 = 24 F(3) = F(2) * F(2) = 24 * 24 = 28 2n On peut faire la conjecture suivante : F (n)  2

Par décomposition :  F(n) = F(n −1)2 = (F(n −2)2)2 = ((F(n −3)2)2)2

 F (0)  2 2n

ENSAH

2n

Introduction à l’algorithmique

E.W. DADI – page : 39

…. la suite

Il reste à prouver que l’algorithme calcule bien F n  22 pour tout n et ceci en utilisant la démonstration par récurrence. n

D’après l’algorithme on a : F (0)  2   2         F n  F n  1  F n  1  F n  1 , n  1 

Montrons par récurrence pour tout entier naturel n on a : F n  2

2n

Cas de base : la propriété est vraie pour n = 0, car F 0  22  2 2n Cas récursifs : soit n ≥ 1 et supposons que la propriété F n   2 est vraie. Montrons qu’elle vraie pour n+1: 0

On a : F n  1  F n F n  F n 2n 2 2 n 2 2n1 Alors : F n  1  (2 )  2  2 D’où, la propriété est vraie pour n+1. Conclusion : l’algorithme est correct. 2

ENSAH

Introduction à l’algorithmique

E.W. DADI – page : 40

Chapitre 2: Complexité algorithmique

Plan I. Notion de la complexité algorithmique II. Outils mathématiques pour la complexité III.Calcul de la complexité d’un algorithme

ENSAH

Complexité algorithmique

E.W. DADI – page : 42

I. Notion de la complexité algorithmique 1. Activité Problème: Rechercher dans un tableau l’existence d’un élément. Il est très fréquent qu’il soit nécessaire de chercher un élément dans un tableau (exemple recherche d’un mot dans dictionnaire) . Etant donné un tableau trié T de n entiers, on veut vérifier si un entier x se trouve dans ce tableau. Plusieurs solutions pour ce problème sont possibles. Solution 1 (recherche séquentielle version 1) : Une solution très simple consiste à parcourir le tableau A de 1 jusqu’à n et à chaque parcours i on test si x=T[i].

ENSAH

Complexité algorithmique

E.W. DADI – page : 43

…. la suite

Algorithme Recherche Séquentielle Version 1 Fonction Rech_séq_v1 (T : Tableau, n, x : Entier) : Entier Var i : Entier; Début test:=0; Pour i := 1 à n Faire Si(T[i] = x) Alors test :=1 FinSi FinPour Retourner(test ); Fin L'algorithme ci-dessus fonctionne mais à le défaut de continuer à parcourir le tableau même quand l'élément a été trouvé. C’est-à-dire qu’il va parcourir tout le tableau même si l’élément qu’on cherche peut être existe au début du tableau ou avant d'être sûr qu’il ne se trouve pas dans le tableau.

ENSAH

Complexité algorithmique

E.W. DADI – page : 44

…. la suite

Solution 2 ( Recherche séquentielle version 2) : Une amélioration de l’algorithme précédent consiste à arrêter d’avancer lorsqu'un premier élément de tableau satisfaisant la condition T[i]=x est trouvé. Algorithme Recherche Séquentielle Version 2 Fonction Rech_séq_v2 (T : Tableau, n, x : Entier) : Entier Var i : Entier; Début i := 1; trouve:=faux; i:=1; Tant que( i<=n et trouve = faux) Faire Tant que(T[i]≠ x et i<=n) Faire Si(T[i] = x) Alors i++; trouve:=vraie; FinTQ Retourner(i); Si(i>n) alors Retourner(-1); FinSi Sinon Retourner(i); i++; FinSi FinTQ Retourner(-1); Fin

ENSAH

Complexité algorithmique

E.W. DADI – page : 45

…. la suite

L’inconvénient de l’utilisation de l’algorithme recherche séquentielle pour la recherche d’une valeur dans un tableau trié est lorsque la valeur qu’on cherche se trouve à la fin de ce tableau; dans ce cas il faut traverser tout le tableau avant de trouver la valeur ou avant d'être sûr qu’elle ne se trouve pas dedans. Par exemple : lors de la recherche dans un tableau de 1000 éléments: la recherche séquentielle peut entraîner 1000 exécutions de la boucle si la valeur qu’on cherche se trouve à la fin de tableau.

ENSAH

Complexité algorithmique

E.W. DADI – page : 46

…. la suite

Solution 3 (Recherche dichotomique) : Lors de la recherche dichotomique, on élimine la moitié des éléments du tableau à chaque exécution de la boucle. Ainsi, la recherche se termine beaucoup plus rapide comparé à l’algorithme séquentielle. A noter que cet algorithme ne fonctionne que pour les tableaux triés. Algorithme Recherche Dichotomique Version récursive Fonction R_dicho(T: Tableau, debut, fin : Entier) : Entier Var m : Entier; // indice du milieu Début Si(debut > fin) Alors Retourner(0); FinSi m := (debut+fin)/2; Si(x= T[m]) Alors Retourner(m); FinSi Si(x > T[m]) Alors Retourner(R_dicho(T, m+1, fin)); Sinon Retourner(R_dicho(T, debut, m-1)); FinSi Fin

ENSAH

Complexité algorithmique

E.W. DADI – page : 47

3. Complexité d’un algorithme Pour un problème donné il se peut qu’il existe plusieurs algorithmes permettant de le résoudre, mais souvent le temps de calcul pris par chaque algorithme n’est pas le même, certaines algorithmes sont moins rapides que d’autres. Par exemple si on compare le temps d’exécution des deux algorithmes (séquentielle et dichotomique) sur un même tableau et sur une même machine dans le cas où la valeur se trouve à la fin du tableau on trouverai que l’algorithme de recherche dichotomique est plus rapide que la recherche séquentielle. Les questions qui se pose est est-ce qu’il existe des outils pour comparer théoriquement le temps d’exécution pour dire qu’algorithme est efficace par rapport à l’autre ? On mesure l'efficacité d'un algorithme par l’analyse de sa complexité( c’est-à-dire on passe par le contraire :efficace # complexe). La complexité d'un algorithme c’est la quantité de ressources qu'il exige (mémoire ou temps-processeur) pour son exécution. Dans ce cours une intérêt particulier est donnée à l’étude de l’efficacité d’un algorithme en terme de temps d’exécution (Complexité temporelle).

ENSAH

Complexité algorithmique

E.W. DADI – page : 48

…. la suite

L’analyse de la complexité algorithmique permet de prédire l'évolution en temps calcul nécessaire pour amener un algorithme à son terme, en fonction de la quantité de données à traiter. La complexité c’est une mesure qui permet de faire différencier les algorithmes, elle permet également de caractériser la classe de famille de l’algorithme. Cette complexité est indépendante de la vitesse de la machine sur laquelle est exécuté l’algorithme. Elle donne une estimation du temps d’exécution de l’algorithme sans tenir compte de son environnement (système d’exploitation, compilateur, technologie, …). Cette estimation se détermine en fonction du nombre d’opérations de base effectuées par l’algorithme c’est-à-dire en fonction de la taille des données en entrée de cet algorithme.

ENSAH

Complexité algorithmique

E.W. DADI – page : 49

…. la suite

Le temps d’exécution de l’algorithme est proportionnel au nombre d’opérations qu’il effectue. Parmi ses opérations, on en considère les plus importantes, celles qui sont représentatives de l’effort de calcul. Exemples : Problème de recherche d’un élément : la comparaison à cet élément. Algorithme de tri : la comparaison entre les éléments du tableau, mais aussi le déplacement des éléments. Problème de calcul de la puissance : la multiplication. La complexité exacte d’un algorithme est plus difficile à déterminer. On ne s’intéresse qu’à la complexité dite asymptotique.

ENSAH

Complexité algorithmique

E.W. DADI – page : 50

II. Outils mathématiques pour la complexité 1. Notations asymptotiques Notation grand O (Grand-O) : Une fonction g(n) est une borne supérieure asymptotique de f(n), si et seulement si: ( C  0), ( n0  0) : f(n)  Cg(n), ( n  n0). On note alors : f(n) = O(g(n)). Notation grand  (Grand-Omega) : Une fonction g(n) est une borne inférieure asymptotique de f(n), si et seulement si : ( C  0), ( n0  0) : f(n)  Cg(n), ( n  n0). On note alors : f(n) = (g(n)). Notation grand  (Grand-Theta) : Deux fonctions f(n) et g(n) ont même ordre de grandeur asymptotique, si et seulement si : ( C1  0), ( C2  0), ( n0  0) : C1g(n)  f(n)  C2g(n), ( n  n0). On note alors : f(n) = (g(n)). Remarques : f(n) = (g(n))  f(n) = O(g(n)) et f(n) = (g(n)). La notation « f(n) = O(g(n)) » (resp (g(n)), ou (g(n))) n’est pas une égalité mathématique ce sont des conventions d’écriture.

ENSAH

Complexité algorithmique

E.W. DADI – page : 51

…. la suite

ENSAH

Complexité algorithmique

E.W. DADI – page : 52

…. la suite Exemple 1: f(n)=a*n+b, g(n)=n, on a : f(n) = O(g(n)). En effet : comme a*n+b  a*n+b*n  (a+b)n ,  n  1, alors : ( C = a+b  0), ( n0 = 1  0) : f(n)  Cg(n), ( n  n0). Exemple 2: Pour f(n) = n3 + 5n2 - 7n + 18 et g(n) = n3, on a : f(n) = O(g(n)). En effet : comme 5n2  5n3, -7n  7n3 et 18  18n3,  n  1, alors : f(n) = n3 + 5n2 - 7n +18  n3 + 5n3 + 7n3 +18n3. f(n)  31n3 = 31g(n). ( C = 31  0), ( n0 = 1  0) : f(n)  Cg(n), ( n  n0). Exemple 3: Pour f(n) = 5n2log(n) + 1 et g(n) = n, on a : f(n) = (g(n)). En effet : 5n2  5n, ( n  0). log(n)  1, ( n  e = 2.7182883). f(n) = 5n2log(n) + 1  5n + 1  4n, ( n  3). f(n)  4g(n), ( n  3). ( C = 4  0), ( n0 = 3  0) : f(n)  Cg(n), ( n  n0). Exemple 4: Pour f(n) = 3n2 + 2n + 1 et g(n) = n2, on a : f(n) = (g(n)). En effet : 3n2 + 2n + 1  3n2 + 2n2 + n2 = 6n2 ( n  1). 3n2 + 2n + 1  2n2 ( n  0). ( C1 = 2  0), ( C2 = 6  0), ( n0 = 1  0) : C1g(n)  f(n)  C2g(n), ( n  n0).

ENSAH

Complexité algorithmique

E.W. DADI – page : 53

2. Propriétés des notations asymptotiques Réflexivité : f(n) = O(f(n)). f(n) = (f(n)). f(n) = (f(n)). Symétrie de  : f(n) = (g(n))  g(n) = (f(n)) Symétrie transposée de O et  : f(n) = O(g(n))  g(n) = (f(n)) Transitivité : f(n) = O(g(n)) et g(n) = O(h(n))  f(n) = O(h(n)). f(n) = (g(n)) et g(n) = (h(n))  f(n) = (h(n)). f(n) = (g(n)) et g(n) = (h(n))  f(n) = (h(n)).

ENSAH

Complexité algorithmique

E.W. DADI – page : 54

3. Formules de sommations Soit une suite numérique (an)n0. La somme finie de cette suite est notée : i=1,…,n(ai) = a1 + … + an Exemples : n(n  1) i   2 i 1

n

n

i2  i 1

n 2 (n  1) 2 i   4 i 1 n

3

n

(2n  1)(n  1)n 6

i4  i 1

n (n  1)(2n  1)(3n 2  3n  1) 30

x n 1  1 x  , si x  1  x  1 i 0 n

i

ENSAH

Complexité algorithmique

E.W. DADI – page : 55

4. Fonctions classiques Fonction logarithmique : (∀a > 0)(∀b > 0)(∀c > 0)(∀n∈ IN), la fonction logarithme f(n) = logb(n) = log(n)/log(b); où b est la base du logarithme. Quelques propriétés: logc(ab)=logc(a)+logc(b), logban =nlogba, logban =nlogba , log a log n log a log b a  , a  n , a  blog a log b b

b

b

Fonction polynomiale : P(n) = adnd + … + a2n2 + a1n + a0, avec la condition ad  0. Théorème : f(n) = adnd + … + a1n + a0 = (nd). Fonction exponentielle : f(n) = an; où a  1 (a c’est la base de l’exponentielle).

Remarques : Une fonction polynomiale (asymp. positive) croît plus vite que n’importe quelle fonction logarithmique. Une fonction exponentielle quelconque avec une base > 1 croît plus vite que n’importe quelle fonction polynomiale.

ENSAH

Complexité algorithmique

E.W. DADI – page : 56

5. Classes de complexité Les algorithmes usuels peuvent être classés en un certain nombre de classes de complexité. Un algorithme est dit optimal si sa complexité est la complexité minimale parmi les algorithmes de sa classe. Les complexités les plus utilisées sont : Constante O(1) : Accéder au premier élément d'un ensemble de données Logarithmique O(log n) : Couper un ensemble de données en deux parties égales, puis couper ces moitiés en deux parties égales, etc. Linéaire O(n) : Parcourir un ensemble de données Quasi-linéaire O(nlog n) : Couper répétitivement un ensemble de données en deux et combiner les solutions partielles pour calculer la solution générale Quadratique O(n2) : Parcourir un ensemble de données en utilisant deux boucles imbriquées Polynomiale O(np) : Parcourir un ensemble de données en utilisant p boucles imbriquées Exponentielle O(an) : Générer tous les sous-ensembles possibles d'un ensemble de données

ENSAH

Complexité algorithmique

E.W. DADI – page : 57

…. la suite

Comparaison des classes de complexité

Une année comporte à peu prés 3.109 Secondes

On considère que toute instruction possède une durée de 10-6 secondes.

ENSAH

Complexité algorithmique

E.W. DADI – page : 58

II.Calcul de la complexité 1. Généralités Le temps d’exécution d’un algorithme pour une entrée particulière est le nombre d’opérations élémentaires, ou « étapes », exécutées. Une opération élémentaire est une opération qui s’effectue en temps constant (O(1)) sur tous les calculateurs usuels. Exemples : Comparaisons; Affectations; Opérations arithmétiques et logiques; Entrée-sortie; lecture ou écriture d’une variable simple; accès à un tableau. La complexité d’un algorithme est la somme des complexités de chacune de ces instructions.

ENSAH

Complexité algorithmique

E.W. DADI – page : 59

2. Quelques règles Pour les instructions conditionnelles (Si…Alors… Sinon …), on considère la complexité maximale entre chaque branche et la condition. La complexité de l’instruction : Si (C) alors I1 sinon I2 est max(O(f(n)), O(f1(n)), O(f2(n))), tels que O(f(n)), O(f1(n)), O(f2(n)) sont respectivement les complexités de la condition,des instructions I1 et I2. Boucle simple : O(n) si le corps de la boucle est O(1) Double boucle : O(n2) si le corps de la boucle est O(1) Généralement pour une boucle de type suivant : Pour i:=0 à n Faire I1 FinPour

Sa complexité est donnée en (n*f1(n)), f1(n) c’est la complexité de I1.

Dans le cas de la boucle « Tant que » et au cas où la complexité de la condition testée par cette boucle est (f(n)). Dans ce cas la complexité est en (g(n)*max(f(n),f1(n))). (g(n)) complexité en nombre d’itérations, (f1(n)) complexité de l’instruction exécutée par la boucle.

ENSAH

Complexité algorithmique

E.W. DADI – page : 60

…. la suite

Exemples Algorithme 1 Début Réaliser l'opération a + b Fin Complexité = O(1) (constant)

Algorithme 2 Début Pour i =1 à n faire Afficher i FinPour Fin Complexité = O(n) (linéaire)

Algorithme 3 Début Pour i = 1 à n faire Pour j = i à n faire Afficher i*j FinPour FinPour Fin Complexité = O(n2) (quadratique)

Algorithme 4 Début Pour i =1 à n faire Pour j = i à n faire Pour k = i à n faire Afficher i*(j+k) FinPour FinPour FinPour Fin Complexité = O(n3) (cubique)

ENSAH

Complexité algorithmique

E.W. DADI – page : 61

3. Complexité des algorithmes itératifs Les étapes à suivre pour calculer le temps d’execution d’un algorithme itératif sont : On considère que chaque ligne de l’algorithme s’exécute en un temps constant indépendant de la taille de données. On note ci le temps d’exécution de l’instruction numéro i. Chaque instruction de l’algorithme est suivi de son coût ci ainsi que du nombre de fois où elle est exécutée. Le temps total d’exécution d’un algorithme traitant une donnée de taille n, noté T(n) est égal à la somme des coûts pondérés par le nombre d’exécution de chaque instruction. Exemple 1: Pour i: =1 à n faire - Les instructions de cet exemple sont, i<=n, i=i+1; I1 - On considère c1, c2 et c3 respectivement les couts des trois instructions. I1 - La boucle “Pour” s’exécute n fois et donc les 3 instructions s’exécutent Fin aussi n fois. - T(n)= (c1+c2 + c3 )n

ENSAH

Complexité algorithmique

E.W. DADI – page : 62

…. la suite

Exemple 2 : complexité d’un algorithme itératif Prenant de calculer la complexité de l’algorithme de recherche d’un élément dans un tableau (Rech_séq_v1) Algorithme Rech_séq_v1 Coût Fois Var i : Entier; Début Pour i := 1 à n Faire c1 , c2 n+1, n Si(T[i] = x) Alors c3 n Retourner(i); c4 n FinSi FinPour Retourner(-1); c5 Fin T(n) = c1(n+1)+(c2+c3+c4)n +c5 T(n) = a*n+b D’où T(n)= O(n)

ENSAH

Complexité algorithmique

E.W. DADI – page : 63

4. Complexité des algorithmes récursifs Les étapes à suivre pour le calcul de temps d’exécution d’un algorithme récursif sont : Transformation de l’algorithme sous forme d’une équation de récurrence. Résolution de l’équation en utilisant les techniques de résolutions de récurrence. Il existe deux types d’équations de récurrences : a)Equation de récurrence de partitions : c’est une équation de la forme suivante :  d ; si n  n0  T ( n)   n aT (  b )  f (n) a c’est le nombre d’appels récursifs, f(n) c’est la complexité de regroupement entre les différents appels. Elle est utilisée pour les algorithmes où il y a la division de l’entrée à chaque appel récursif.

ENSAH

Complexité algorithmique

E.W. DADI – page : 64

…. la suite

Méthodes de résolution de la récurrence de partitions : Méthode par itérations : on explore T(n) suivant des itérations jusqu’au cas de base. Théorème de Master. Méthode par itérations : pour montrer comment résoudre une équation de récurrence de partition on va utiliser l’exemple suivant : T(n) = 2T(n/2)+n = 2[2T(n/4) + n/2]+n = 2[2(2T(n/8) + n/4) + n/2]+n = 23T(n/8)+ 3n = 2iT(n/ 2i)+ i * n Quand (n/ 2i)= 1  log2i = log n  i =(log n / log2)  i= log2n

T (n)  2log2 n  n log 2 n T (n)  n  n log 2 n

D’où T (n)  (n log 2 n)

ENSAH

Complexité algorithmique

E.W. DADI – page : 65

…. la suite

Théorème de Master : Selon ce théorème on a :

Si f (n)  cn k , k  0, c  0  (n k ); a  b k  T (n)  (n k log b n); si a  b k  (n logb a ); si a  b k 

Si f (n)  cn k (log b n)q , k  0, c  0  (n k ); si a  b k et q  0  k q 1 k  (n (log b n) ); si a  b et q  1 T ( n)   k k  ( n log log n ); si a  b et q  1 b b  (n logb a ); si (a  b k et q  1)ou a  b k

ENSAH

Complexité algorithmique

E.W. DADI – page : 66

…. la suite

Théorème de Master : Exemples Exemple 1 : T(n) = 2T(n/2) + n a = 2; b = 2; k = 1. a= bk T(n) = (n log2(n)). Exemple 2 : T(n) = 9T(n/3) + n2 a = 9; b = 3; k = 2. T(n) = (n2log3(n)).

Exemple 3: T(n) = 2T(n/2) + n3 a = 2; b = 2; k = 3. T(n) = (n3).

ENSAH

Complexité algorithmique

E.W. DADI – page : 67

…. la suite

Exemple : complexité d’un algorithme récursif Prenant de calculer la complexité de l’algorithme recherche dichotomique (la version R_dicho) Fonction R_dicho(T: Tableau, debut, fin : Entier) : Entier Var m : Entier; // indice du milieu Début Si(debut > fin) Alors Retourner(0); FinSi m := (debut+fin)/2; Si(x = T[m]) Alors Retourner(m); FinSi Si(x > T[m]) Alors Retourner(R_dicho(T, m+1, fin)); Sinon Retourner(R_dicho(T, debut, m-1)); FinSi Fin

Coût c1 c2 c3 T(n/2) T(n/2)

Soit n= debut+fin-1 la taille du tableau L’équation de récurrence correspondante à cet algorithme est T(n) = c1+c2+ c3+ T(n/2) = T(n/2) +cte. On a k=0, a=1 et b=2 => a=bk D’après le théorème de master T(n)=O(n0log2n)= O(log2n)

ENSAH

Complexité algorithmique

E.W. DADI – page : 68

…. la suite

b) Récurrence linéaire La forme générale d’une équation de récurrence linéaire est comme suite: T(n)-a1T(n-1)- a2T(n-2)-…- akT(n-k)=cte. A une telle équation, on peut l’associer un polynôme: P(x)=xk - a1xk-1 - a2xk-2 -…- ak La résolution de ce polynôme nous donne m racines ri (avec m<=k). La solution de l’équation de récurrence est ainsi donnée par : T(n)=c1r1n +c2r2n +c3r3n +…+cmrmn

ENSAH

Complexité algorithmique

E.W. DADI – page : 69

…. la suite

Exemple : utilisation de la récurrence linéaire pour calculer la complexité de la suite récursive de Fibonacci {F(n)=F(n1)+F(n-2), F(0)= F(1)=1} L’équation de récurrence correspondante à F est T(n)=T(n1)+T(n-2)+cte. Le polynôme correspondant à l’équation de recurrence T est : P(x)= x2 – x – 1, la résolution de cette équation donne: r1 

1 5 1 5 , r2  2 2 n

1 5  1 5  n n   b  T (n)  a  r1  b  r2  a     2   2 

n

  1  5 n    T (n)     2     

ENSAH

Complexité algorithmique

E.W. DADI – page : 70

4. Niveaux de complexité Soit D l'ensemble des données de taille n et T(d) le coût de l'algorithme sur la donnée de taille d. Complexité au meilleur : C’est le plus petit nombre d’opérations qu’aura à exécuter l’algorithme sur un jeu de données de taille fixée, ici à n. C’est une borne inférieure de la complexité de l’algorithme sur un jeu de données de taille n. Tmin(n)=min dєDT(d) Complexité au pire : C’est le plus grand nombre d’opérations qu’aura à exécuter l’algorithme sur un jeu de données de taille fixée, ici à n. Tmax(n)=max dєDT(d) Complexité en moyenne : C’est la moyenne des complexités de l’algorithme sur des jeux de données de taille n en tenant compte de la probabilité d’apparition de chacun des jeux de données(p(d)). Tmoy(n)=∑ dєDp(d)T(d)

ENSAH

Complexité algorithmique

E.W. DADI – page : 71

…. la suite

Exemple : Prenant de calculer la complexité de l’algorithme de recherche séquentielle dans un tableau (la version 2 Rech_séq_v2). Le calcul de la complexité de Rech_séq_v2 se fait selon trois niveau : Complexité au meilleur: le meilleur des cas est lorsque la valeur qu’on cherche se trouve au début de tableau, dans ce cas l’algorithme va faire qu’une seule itération d’où la complexité = O(1) . Complexité au pire: le pire des cas est lorsque la valeur qu’on cherche n’existe pas dans le tableau ou bien elle se trouve à la fin. Dans les deux cas on doit parcourir le tableau de début jusqu’à la fin d’où la complexité = O(n) . Complexité en moyenne: la moyenne des cases est lorsque la valeur qu’on cherche se trouve au milieu ou à une position i proche du milieu. Le nombre de comparaison dans ce cas est i tels que 1
ENSAH

Complexité algorithmique

n

E.W. DADI – page : 72

Chapitre 3: Étude de la complexité de quelques algorithmes

Plan I. Algorithmes itératifs II. Algorithmes « diviser pour régner » III.D’autres algorithmes

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 74

I. Algorithmes de tri itératifs 1. Généralités Problème de tri : étant donné un tableau T non trié, le problème de tri consiste à utiliser un algorithme de tri pour ranger les valeurs de tableau T dans un ordre (un sens) donné(croissant/décroissant). Exemple A={3, 7, 9, 2, 4, 6, 8} le trie de ce tableau dans l’ordre croissant donne A={1, 2, 3, 4, 6, 7, 8, 9} Plusieurs situations nécessite le tri à savoir : établir le classement de certains élèves, mettre en ordre un dictionnaire, faire une sortie lisible d'un correcteur d'orthographe, etc …

Il existe plusieurs algorithme de tri dans la littérature, à savoir : tri par sélection, tri par insertion, tri rapide, tri fusion… Dans la suite on va traiter le cas de trie d’un tableau dans l’ordre croissant.

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 75

2. Tri par sélection L’idée de cette algorithme est basée sur un autre algorithme; celui qui permet de trouver la valeur minimale ou maximale d’un tableau. On peut choisir d’utiliser l’un des deux algorithme (min ou max), si l’algorithme choisit est min, le tri commence par le début de tableau le contraire est vrai. À chaque itération de l’algorithme tri par sélection, les étapes à suivre sont :

Chercher le minimum (resp. maximum) du la partie de tableau non encore trié. Échanger le minimum (resp. maximum) avec le premier (resp. dernier) élément de la partie du tableau non encore trié.

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 76

…. la suite

Algorithme de tri par sélection (le cas d’utiliser l’algorithme min_tableau) Fonction Tri_sélection(T : Liste, n : Entier) Var i, imin : Entier; Début Pour i : = 1 à n-1 Faire imin := Obtenir_min(T, i, n); Si(imin i) Alors Échanger(T, i, imin) FinSi FinPour Fin Source :wikipedia.org

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 77

…. la suite

Fonction Obtenir_min(A : Liste, d, f : Entier) : Entier Var i, j : Entier; Début j := d; Pour i : = d + 1 à f Faire Si(A[i] < A[j]) Alors j := i; FinSi FinPour Retourner(j); Fin Fonction Echanger(A : Liste, i, j : Entier) Var t : Entier; Début t := A[i]; A[i] := A[j]; A[j] := t; Fin

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 78

…. la suite

Exemple: 51

2

3

4

5

5

9

7

3

8

i=1

3

9

7

5

8

imin= 4, changement

i=2

3

5

7

9

8

imin= 4, changement

i=3

3

5

7

9

8

imin= 3, pas de changement

i=4

3

5

7

8

9

imin= 4, changement

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 79

…. la suite

Etude de la complexité de l’algorithme Tri_sélection :

La complexité de l’algorithme tri_selection = (n-1)*(complexité de Obtenir_min + complexité de Echanger) La complexité de l’algorithme Obtenir_min est linéaire; il dépend directement de la taille de l’entrée. Si on considère la taille de l’entrée est k alors C(k)=k La complexité de l’algorithme Echange est constante.

D’où C(n) = (n+c)+((n-1)+c)+ …+(2+c)

= n+(n-1)+…+2+n*c = n*c+ n*(n-1)/2 = n(c+(n-1)/2)

= n((n-1+2c)/2) ≤ (1+c) n2 Ce qui implique que C(n)= O(n²).

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 80

3. Tri par insertion

Idée : À chaque itération de l’algorithme : on place le

premier élément dans le tableau non encore trié dans sa place convenable dans la partie déjà trié du tableau, comme un joueur tiens des cartes à jouer. 51

2

3

4

5

i=2

5

9

7

3

8

5

9

7

3

8

i=3

5

9

7

3

8

5

7

9

3

8

i=4

5

7

9

3

8

3

5

7

9

8

i=5

3

5

7

9

8

3

5

7

8

9

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 81

…. la suite

Fonction Tri_insertion(T : Tableau, n : Entier) Var i, j, clé : Entier; Début Pour i : = 2 à n Faire clé:= T[i]; // sauver a[i] j := i - 1; Tant Que((j > 0) et (T[j] > clé)) Faire T[j + 1] := T[j]; // Décalage j--; FinTQ T[j+1] = clé; FinPour Fin

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 82

…. la suite

Soit C(n) le nombre de comparaisons effectuées par le tri par sélection. Dans le pire des cas : Configuration : un tableau trié dans l’ordre décroissant.

Placer T[i] dans T[1…i-1] nécessite (i-1) comparaisons. C(n) = 1 + … + (n-1) = i=2,..,n(i-1) = (n-1)n/2 C(n) = O(n2).

Dans le meilleur des cas : Configuration : un tableau trié dans l’ordre croissant. Placer T[i] dans T[1…i-1] nécessite 1 comparaison. C(n) = i=2,..,n(1) = (n-1) C(n) = (n).

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 83

4. Tri à bulles Idée : Consiste à permuter les éléments adjacents s’ils ne sont pas ordonnés. Continuer ce processus jusqu’à ce que le tableau soit entièrement trié. À chaque itération i, on parcourt le tableau de droite à gauche pour placer le minimum dans la position i par une suite d’échange d’éléments adjacents.

ENSAH

51 5

2 9

3 7

4 3

5 8

i=1

3

5

9

7

8

i=2

3

5

7

9

8

i=3

3

5

7

8

9

i=4

3

5

7

8

9

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 84

…. la suite

Algorithme : Fonction Tri_bulles(T : Tableau, n : Entier) Var i, j : Entier; Début Pour i : = 1 à (n - 1) Faire Pour j := n à (i + 1) Faire Si(T[j] < T[j - 1]) Alors Échanger(T, j - 1, j); FinSi FinPour FinPour Fin Complexité : Soit C(n) le nombre de comparaisons effectuées par le tri à bulles. À chaque itération i (de 1 à n-1), on effectue (n - i) comparaisons. C(n) = (n-1) + … + 1 = i=1,..,n-1(n-i)= (n-1)n/2 C(n) = (n2).

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 85

5. Tri PRAM C’est un algorithme de tri très adapté à la parallélisation. Il permet de faire le tri de façon très rapide sur des machines multi-cœurs, Stations multiprocesseurs, Grille de calculs…

Idée : Le tableau à trier est placé sur la première ligne d'une grille. Son transposé (Le même tableau) est aussi placé en colonne. Puis, de 1 jusqu’à n, on compare chaque élément avec les n autres de tableau (les comparaisons entre chaque couple formé par une valeur ligne et une valeur colonne). Si la comparaison est vraie on met à l'emplacement correspondant de la grille, la valeur 1, sinon 0. Après avoir terminé, on somme les éléments des lignes de la grille (matrice de 0 et 1) dans un nouveau vecteur. Ces sommes donnent la position (l’ordre de tri) de chacune des valeurs du tableau à trier.

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 86

…. la suite

Exemple :



5

9

7

3

8

P

5

1

0

0

1

0

2

9

1

1

1

1

1

5

7

1

0

1

1

0

3

3

0

0

0

1

0

1

8

1

0

1

1

1

4

T[ ]=

5

9

7

3

8

P[ ]=

2

5

3

1

4

i=1, TT[2]=T[1] i=2, TT[5]=T[2] TT[P[i]]= T[i] => i=3, TT[3]=T[3] i=4, TT[1]=T[4] i=5, TT[4]=T[5]

ENSAH

=>

3

On obtient l’ordre de tri

Tableau trié

5

Étude de la complexité de quelques algorithmes

7

8

9

E.W. DADI – page : 87

…. la suite

Algorithme : Fonction Tri_PRAM(T : Tableau, n : Entier) Var i, j : Entier; Début Pour i : = 1 à n Faire S:=0; Pour j := 1 à n Faire Si(T[i] ≥ T[j]) Alors S+:=1; FinSi FinPour P[i]=S; FinPour Pour i : = 1 à n Faire TTrie[P[i]]:=T[i] FinPour //T:=TTrie; Fin Il est bien clair que la complexité de Tri_PRAM est en O(n²).

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 88

II. Algorithmes «diviser pour régner» 1. Présentation Ce sont les algorithmes récursifs qui utilisent une stratégie de type Diviser pour régner « D&R ». Elle suit une approche de décomposition descendante d’un problème en sous-problèmes de tailles plus petites. Elle repose sur trois étapes fondamentales : Diviser : on partitionne le problème initial en un certain nombre de sous-problèmes identiques, mais de tailles plus petites. Régner : on résout les sous-problèmes d’une manière récursive. Cependant, un sous-problème peut être résolu directement si sa taille est suffisamment réduite. Combiner : on combine les solutions partielles des sous-problèmes pour construire la solution globale du problème initial. La complexité d’un algorithme de type D&R est donnée par la résolution de l’équation de récurrence de partitions T(n) = aT(n/b) + О(f(n)) correspondante. Exemples: Recherche dichotomique, Tri par fusion, Algorithme de Karatsuba, Algorithme de Strassen…

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 89

2. Algorithme de tri par fusion Idée : Diviser le tableau de taille n, en 2 sous-tableaux de taille n/2 chacun. Trier chacun des 2 sous-tableaux séparément (par appel récursif). Interclasser les deux sous-tableaux déjà triés pour obtenir un seul tableau trié. 51 2 3 4 5

Algorithme :

5

9

7

Fonction Tri_fusion(T : Tableau, d, f : Entier) 5 9 7 Var m : Entier; Début 5 9 7 Si(d < f) Alors m := (d + f) / 2; 5 9 7 Tri_fusion(T, d, m); Tri_fusion(T, m + 1, f); 5 9 7 Fusion(T, d, f, m); FinSi 5 7 9 Fin 3

ENSAH

Étude de la complexité de quelques algorithmes

5

3

8

3

7

8

3

8

3

8

8

3

8

3

8 9

E.W. DADI – page : 90

…. la suite Algorithme : Fonction Fusion(T : Tableau, d, f, m : Entier) Var i, j, k : Entier; A : Tableau; Début Pour i := d à m Faire A[i] := T[i]; FinPour Pour i := (m + 1) à f Faire A[i] := T[f-i+m+1]; FinPour i := d; j := f; k := d; Tant Que(i < j) Faire Si(A[i] < A[j]) Alors { T[k] := A[i]; i++; } Sinon { T[k] := A[j]; j--; } FinSi k++; FinTQ Fin

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 91

…. la suite

Complexité de l’algorithme Tri_Fusion: Pour déterminer la formule de récurrence qui nous donnera la complexité de cet algorithme, nous étudions ses trois phases « diviser pour régner » : Diviser: cette étape se réduit au calcul du milieu de l’intervalle [p; r], sa complexité est donc en O(1). Régner: l’algorithme résout récursivement deux sous-problèmes de tailles respectives n/2, d’où une complexité en 2*T(n/2). Combiner: la complexité de cette étape est celle de l’algorithme de fusion qui est de O(n) pour la construction d’un tableau solution de taille n.

Par conséquent, la complexité du tri_Fusion est donnée par la récurrence :  1; si n  1  T ( n)   n 2 T ( )  ( n )  2  En utilisant le théorème de Master, la complexité de l’algorithme est en O(nlog2 n).

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 92

3. Algorithme de Karatsuba C’est un algorithme permettant de calculer le produit de deux grands nombres entiers avec un temps d’exécution réduit par rapport à l’algorithme scolaire. Soient deux entiers x et y, ayant chacun n chiffres. On veut calculer leur produit x × y. On s’intéresse aux nombres de multiplications élémentaires (par pair de chiffres). Avec un algorithme scolaire (algorithme naïf), on effectue n2 multiplications  algorithme en (n2). L’algorithme scolaire en mode D&R : On divise les deux nombres x et y en deux sous-nombres, chacun ayant n/2 chiffres : x = a.10(n-1) + b et y = c.10(n-1)+ d xy = ac.102(n-1) + (ad + bc).10(n-1)+ bd Avec ce mode opératoire, on a un algorithme diviser pour régner dont la complexité est T(n) = 4T(n/2) => T(n) = (n2)

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 93

…. la suite Algorithme Multiplication scolaire

Fonction Multi_scolaire(x, y : Entiers ) Entier Var a, b, c , d , m : Entiers; Début m:=min(size(x),size(y))-1; Si (m = 0) alors Retourner x*y; Sinon p:=puissance(10,m); a :=x/p; b := x%p; c :=y/p; d :=y%p; s0 := Multi_scolaire (a, c); s1 := Multi_scolaire (a, d); s2 := Multi_scolaire (b, c); s3 := Multi_scolaire (b, d); Retourner s0*102m+(s1+s2)*10m + s3;

FinSi Fin

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 94

…. la suite

Amélioration de Karatsuba :

Le mathématicien A.A. Karatsuba a proposé une amélioration de l’algorithme de multiplication en mode D&R : la remarque qu’il a fait est la suivante : « Faire 3 multiplications pour le calcul de xy au lieu de 4 ». Explications : On a xy = ac.102(n-1) + (ad + bc).10(n-1)+ bd On remarque que ad + bc = (a + b)(d + c) - ac - bd. Alors xy= ac.10n + ((a + b)(d + c) - ac - bd).10n/2 + bd. Cela signifie qu’au lieu de faire 4 multiplications (ac, ad, bc et bd) on peut faire que 3 (ac, (a + b)(d + c), bd) On diminuera la complexité de cet algorithme au lieu d’avoir 4 appel récursif, n’utiliser que 3 (a = 3).

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 95

…. la suite

Exemple :

Pour calculer le produit 12345×6789, on choisit B = 10 et m = 3. Puis on décompose les deux nombres comme suit : 12345 = 12 · 1000 + 345

6789 = 6 · 1000 + 789

k0 = 12 × 6 = 72 k1 = (12 + 345) × (6 + 789) = 357 × 795 = 283815 k2 = 345 × 789 = 272205 k1 - k0 - k2 = 283815 − 72 − 272205 = 11538

12345×6789 = k0 ·B2m + k1 - k0 - k2 ·Bm + k2 = 72 × 10002 + 11538 × 1000 + 272205 = 83810205.

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 96

…. la suite Algorithme : Fonction karatsuba(x, y : Entiers ) Entier Var a, b, c , d , m,k0,k1,k2,p : Entiers; Début m=min(size(x),size(y))-1; Si (m = 0) alors Retourner x*y; Sinon p:=puissance(10,m); a :=x/p; b := x%p; c :=y/p; d :=y%p;

Complexité : T(n) = 3T(n/2). La solution de cette équation est : T(n) = (nlog(3)/log(2)) = (n1.59).

k0 := karatsuba(a , c); k1 := karatsuba((a +b), (c +d)); k2 := karatsuba (b , d) Retourner k0*102m+(k1-k0-k2)*10m + k2; FinSi Fin

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 97

4. L'algorithme de Strassen C’est un algorithme de type « diviser pour régner » qui permet la multiplication de deux matrices en un temps rapide par rapport à l’algorithme de multiplication naïf. La multiplication de deux matrices carrées de taille n×n, A=(aij) et B=(bij) est définie par C=A×B avec : cij = ∑ aij× bij Algorithme diviser pour régner naïf: Nous supposerons que n est une puissance exacte de 2. On décompose chaque matrice en sous-matrices de taille n/2 . L'équation peut alors se récrire C=A×B :  C11 C12   A11 A12   B11 B12           C21 C22   A21 A22   B21 B22  C11  A11B11  A12B21 C12  A11B12  A12B22 C21  A21B11  A22B21 C22  A21B12  A22B22

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 98

…. la suite Fonction Multi_Matrice(A, B : Matrices) : Matrice

Var : Entiers; Début Si (n = 1) alors Retourner A×B;

Sinon C11:= Multi_Matrice(A11, B11) + Multi_Matrice(A12, B21); C12 := Multi_Matrice(A11, B12) + Multi_Matrice(A12, B22 ); C21 := Multi_Matrice(A21, B11) + Multi_Matrice(A22 , B21);

C22 := Multi_Matrice(A21, B12) + Multi_Matrice(A22 , B22 ); FinSi Fin Avec cet algorithme diviser pour régner, on obtient un coût : T(n) = 8T(n/2)+ (n2). T(n) = (n3)

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 99

…. la suite

L'algorithme de Strassen : est un algorithme « diviser pour régner » qui n'effectue que 7 multiplications de matrices, contrairement à 8 de l'algorithme précédent mais qui effectue plus d'additions et de soustractions de matrices, ce qui est sans conséquence une addition de matrices étant « gratuite » par rapport au coût d'une multiplication. S1=A11(B12 - B22) S2=(A11+A12)B22 S3=(A21 +A22)B11 S4=A22 (B21- B11)

S5=(A11 + A22) (B11 + B22) S6=(A12 - A22)(B21 + B22) S7=(A11 - A21 )(B11 + B12)

S1  S2  S5  S 4  S 2  S 6   A  B   S1  S5  S3  S7   S3  S 4

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 100

…. la suite

Algorithme de multiplication naïf : Fonction Matrice_Strassen(A, B : Matrices) : Matrice Var : Entiers; Début Si (n = 1) alors Retourner A×B; Sinon S1 := Matrice_Strassen(A11,(B12 - B22)); S2 := Matrice_Strassen((A11+A12),B22); S3 := Matrice_Strassen((A21 +A22),B11); S4 := Matrice_Strassen(A22, (B21- B11)); S5 := Matrice_Strassen( (A11 + A22), (B11 + B22)); S6 := Matrice_Strassen( (A12 - A22),(B21 + B22)); S7 := Matrice_Strassen( (A11 - A21 ),(B11 + B12)); Retourner(S5 +S4 - S2 + S6 , S1 - S2 , S3 + S4 , S1 + S5 - S3 + S7); FinSi Fin

Avec cet algorithme diviser pour régner, on obtient un coût :

T(n) = 7T(n/2)+ (n2). T(n) = (n2.8)

ENSAH

Étude de la complexité de quelques algorithmes

E.W. DADI – page : 101

Related Documents

Complexite
March 2021 0
Algorithmique
January 2021 0
4-complexite
March 2021 0
4-complexite
March 2021 0