Théorie 3.3: efficacité (2) #
-
On peut estimer l’efficacité d’un programme en analysant son pseudo-code
-
Nous allons utiliser les exemples suivants:
- une recherche naïve:
O(n) - un tri naïf:
O(n2) - une recherche de type “diviser pour régner”:
O(log(n)) - le tri fusion:
O(log(n)·n)
- une recherche naïve:
Estimer l’efficacité avec O()
#
-
Il faut se poser la question:
- pour chacun des
néléments en entrée:- combien de fois est-ce que l’élément sera manipulé?
- pour chacun des
-
Voici le pseudo-code d’un recherche naïve:
int trouverIndicePourValeur(liste, valeur):
- POUR TOUS les éléments
elde laliste:- SI
elest égal à lavaleurcherchée:- mémoriser l’indice
ide l’élémentel
- mémoriser l’indice
- SI
- retourner le dernier indice
imémorisé
-
Clairement, on va manipuler chaque élément une fois:
- on fait une boucle sur toute la liste
- on compare chaque élément de la liste à la valeur cherchée
-
Donc, si on a
néléments en entrée, il y aura environsninstructions -
Donc, l’efficacité (complexité) de l’algorithme est estimée à
O(n)
Tri naïf: O(n2)
#
- Voici le pseudo-code d’un algorithme de tri naïf:
Liste<C> trier(Liste<C> entree):
- CRÉER une liste
resultatvide - TANT QUE la liste
entreen’est pas vide- appeler
valeurMinimaleet mémoriser la valeur de retour - retirer cette valeur de la liste
entree - ajouter cette valeur à la fin de la liste
resultat
- appeler
- retourner la liste
resultat
-
Si la liste
entreecontientnéléments, la boucle va s’exécuternfois- à chaque tour de boucle, on retire un élément
- après
ntours,entreesera vide et on va quitter la boucle
-
On va faire au moins
nappels àvaleurMinimale() -
Le nombre d’instructions va être
n·VM- où
VMest le nombre d’instructions pour chaque appel àvaleurMinimale() - le nombre d’instructions total est estimé à
O(n·VM)
- où
-
Regardons le pseudo-code de
valeurMinimale():
Valeur obtenirValeurMinimale(liste):
- considérer que le premier élément de la
listeest la valeur minimale - POUR TOUS les éléments
elde laliste:- SI
elest plus petit que la valeur minimale courante:- mémoriser
elcomme la nouvelle valeur minimale courante
- mémoriser
- SI
- retourner la valeur minimale
-
On visite chaque élément de la liste
- donc on va faire
ninstructions pour chaque appel àvaleurMinimale() - alors
VM == n
- donc on va faire
-
En résumé:
- la boucle de
trierfaitnappels àvaleurMinimale() - chaque appel à
valeurMinimale()faitninstructions - on a donc
O(n·VM)oùVM == n - on a donc
O(n·n) - on a donc
O(n2)
- la boucle de
-
L’efficacité (complexité) de notre tri naïf est
O(n2)
Diviser pour régner: O(log(n))
#
-
On cherche une valeur dans une liste trié de plus petit au plus grand
-
Est-ce qu’on est obligé de visiter tout le tableau?
-
On peut appliquer une technique appelée “diviser pour régner”:
- on choisit un élément au milieu de la liste
- si l’élément est plus petit que la valeur cherchée
- on peut chercher uniquement “haut dessus” de cet élément
- si au contraire l’élément est plus grand que la valeur cherchée
- on peut chercher uniquement “en dessous” de cet élément
-
Et pour chercher dans la moitié de la liste?
- on applique encore “diviser pour régner”
- on cherche uniquement dans la moitié de la moitié de la liste
-
Et ainsi de suite jusqu’à ce qu’on trouve
-
À chaque étape dans notre recherche, on divise la liste en deux
-
Pour estimer le nombre d’instructions, on divise
npar 2 à chaque étape de recherce:- si
n=2048, on a:- éléments restants à visister après la 1ière étape:
2048 - éléments restants à visister après la 2ième étape:
1024 - éléments restants à visister après la 3ième étape:
512 - éléments restants à visister après la 4ième étape:
256 - éléments restants à visister après la 5ième étape:
128 - éléments restants à visister après la 6ième étape:
64 - éléments restants à visister après la 7ième étape:
32 - éléments restants à visister après la 8ième étape:
16 - éléments restants à visister après la 9ième étape:
8 - éléments restants à visister après la 10ième étape:
4 - éléments restants à visister après la 11ième étape:
2 - éléments restants à visister après la 12ième étape:
1
- éléments restants à visister après la 1ière étape:
- on a terminé notre recherche en seulement
12étapes - (pour un programme informatique, c’est ridiculement petit)
- si
-
Il s’agit de
O(log(n)), le contraire d’une explosion exponentielle:
-
Les algorithmes
O(log(n))sont souvents les plus efficaces -
Par exemple, voici des résultats comparant nos deux recherches:
- Ce n’est pas une erreur si la ligne verte est presque invisible!
- la recherche efficace est tellement rapide qu’on arrive à peine à la mesurer
Tri fusion: O(log(n)·n)
#
-
Est-ce qu’on peut appliquer l’idée de “diviser pour régner” au tri?
-
Oui, voici par exemple le tri fusion:
Liste trier(Liste entree):
- CRÉER une liste
resultatvide - SI
entreecontient un seul élément ou moins:- copier
entreedansresultat
- copier
- SINON:
- diviser la liste
entreeen deux sous-listes égales - appeler
trier()pour trier chaque sous-liste - appeler
fusionner()pour fusionner les deux sous-listes - copier la liste fusionné dans
resultat
- diviser la liste
- retourner la liste
resultat
-
À chaque étape, on fait un nouvel appel à
trier- donc à chaque étape on divise
entreeen deux - il va donc avoir
log(n)étapes - on va donc faire
log(n)appels àfusionner()
- donc à chaque étape on divise
-
Chaque appel à
fusionner()demande au moinsninstructions- chaque élément est manipulé une fois
- fusionner prend deux listes triées et les combine en une seule liste triée en comparant les éléments un par un, et en ajoutant le plus petit des deux dans la nouvelle liste
- on continue ensuite en ajoutant les éléments restants des deux listes
-
L’efficacité (complexité) de l’algorithme est donc
O(log(n)·n)- c’est à dire, on fait
log(n)fois une étape qui demandeninstructions
- c’est à dire, on fait
-
En terme d’efficacité, les algorithmes
O(log(n)·n)sont presques aussi bon queO(n):
- Par exemple, voici une comparaison entre le tri naïf et le tri fusion:
- Encore une fois, ce n’est pas une erreur si la ligne verte est presque invisible!
- en comparaison au tri naïf, le tri fusion est preque instantané