Informatique Cours 4.1 Le tri des listes est un des éléments qui permet d'accéder aux données rapidement. Tri par insertion Exemple de requêtes possibles sur des listes triées : - rechercher si un élément est dans un tableau (recherche d'un mot dans une liste de mots clefs pour les métadonnées de pages internet), - déterminer la médiane d’une liste de nombres (exemple : dans un concours, déterminer la note qui départage les candidats en deux groupes de même effectif), - sélectionner une sous-liste d’éléments consécutifs (exemple : afficher seulement les relevés temporels compris entre l'instant 1s et l'instant 2s), 1 Algorithme de recherche dans une liste 1.1 Recherche dans une liste non triée Algorithme Recherche de x dans L Entrées : élément x et liste L Sortie : s=Vrai si x est dans L et Faux sinon n ← Nombre d'éléments de L def recherche (L,x): # Entrées : élément x et liste L # Sortie : s=True si x dans L et False sinon n = len (L) s ← Faux c←0 Tant que (c < n et s=Faux) Faire Si L[c]=x alors s ← Vrai c ← c+1 Fin tant que s = False # s : Faux par défaut c=0 # initialisation de l'indexe while (c<n and s==False): if L[c]==x : s = True c = c+1 return s Renvoyer s Fin de l'algorithme Recherche de x dans L Appel de la fonction recherche: >>> liste = [0,2,1] >>> recherche (liste,2) True Complexité Dans le pire des cas, l'élément n'est pas présent dans la liste, la complexité temporelle correspond à C(n)=n Pour les algorithmes de recherche dans une liste non triée on a une complexité (comptée en nombre d'itérations). Lycée Jules Ferry Cannes Page 1 sur 4 linéaire TSI2 Informatique Cours 4.1 Tri par insertion 1.2 Complexité dans une liste triée Algorithme Recherche dichotomique[2] Entrées : élément x et liste L Sortie : s=Vrai si x est dans L et Faux sinon n ← Nombre d'éléments de L g←0 d ← n-1 Tant que g ≠ d Faire k ← (g+d) div 2 Si L[k]<x Alors g ← k+1 Sinon : Si L[k]>x Alors d←k Sinon : d←k g←k Fin Si Fin Tant que Si L[g]=x Alors s ← True Sinon s ← False Fin Si Renvoyer s Fin de Recherche dichotomique def Recherche_dichotomique (L,x): # Entrée : liste L, x élément cherché # Sortie : s=True si x dans L et False sinon n=len(L) g=0 # premier indice de L : 0 d=n-1 # dernier indice de L : n-1 while g!=d: k=(g+d)//2 # dichotomie if L[k]<x: # x est à droite du milieu g=k+1 else: if L[k]>x: # x est à gauche du milieu d=k else: # x est au milieu g=k d=k if L[g]==x: # Affectation de la sortie s=True else: s=False return s Appel de la fonction Recherche_dichotomique : >>> liste_triee=[0,1,2] >>> Recherche_dichotomique(liste_triee,2) True Complexité : Dans le pire des cas, l'élément n'est pas présent dans la liste. Si m est le nombre d'éléments restants après k itérations : ≤ < jusqu'à m=1. Complexité = < + 1 itérations. Pour un algorithme de recherche dichotomique, on a une complexité logarithmique (comptée en nombre d'itérations). 1.3 Conclusion Pour le traitement de grandes quantités de données (base de donnée internet, relevés à haute fréquence, résultats de calculs par éléments finis…), l'algorithme a un impact important sur les durées de traitement. Exemple pour 10 pages trouvées, un moteur de recherche internet met 0,5 s. Pour une durée unitaire d'opération de 10ns si n=10 données : - Un algorithme linéaire conduit à une durée de traitement de 10s. - Un algorithme logarithmique log 10 ≈ 30 conduit à une durée de traitement de 300ns Pour afficher rapidement des données nombreuses, il est donc indispensable de trier les données avant les requêtes. 2 Tris 2.1 Principe du tri On se donne un tableau t, dont les éléments t[0]; t[1]; t[2]; …; t[n - 1] sont comparables. Les t[i] peuvent être : des entiers, des flottants, des lettres de l’alphabet… Un tableau t est trié par ordre croissant si : t[0] ≤ t[1] ≤…≤ t[n-1]: Exemple : si t = ['C','A','T','A, 'Z','U','M'], on veut transformer t en t0 = ['A','A', 'C','M','T','U', 'Z'] Lycée Jules Ferry Cannes Page 2 sur 4 TSI2 Informatique Cours 4.1 Tri par insertion Trois algorithmes sont au programme : le "tri par insertion", le "tri rapide" et le "tri fusion". D’autres algorithmes hors programme existent : "tri par sélection", "tri à bulles" . . . Chacun de ces tris se base sur une suite de comparaisons d’éléments. Mais ces différents algorithmes ne sont pas équivalents, ils ont des complexités différentes, c’est-à-dire que certains nécessitent plus de comparaisons d’éléments que d’autres, ou plus d’affectations. 2.2 Tri par insertion On insère successivement chaque élément dans l’ensemble des éléments déjà triés. Ce tri s’effectue en place : pas besoin de créer un autre tableau que celui que l’on trie. Le coût en mémoire est constant. Algorithme Tri par insertion Entrées : liste T (tableau de n nombres; n≥ 2) Sortie : liste T triée par ordre croissant n←nombre d'éléments de T Pour i de 1 à n-1 faire x←T[i] j← i Tant que j> 0 et T[j-1] > x faire T[j] ←T[j-1] j← j-1 Fin Tant que T[j] ←x Fin Pour Renvoyer T Fin de Tri par insertion Appel de la fonction Tri_insertion : >>> liste=[5, 8, 3, 2, 9] >>> Tri_insertion (liste) [2, 3, 5, 8, 9] def Tri_insertion (T): """Entrée liste T à n nombres (n≥ 2) Sortie : liste T triée (croissant)""" n = len(T) for i in range(1,n): # tri de T x = T[i] j = i # j : position triée pour x while j>0 and T[j-1] > x : T[j] = T[j-1] # remonter droite j=j-1 T[j] = x return T i=1, x=8 3 2 T[0]=5<x 8 en 1 i=2, x=3 tout remonte x en 0 i=3, x=2 tout remonte x en 0 i=4, x=9 T[4]=8<x 9 en 5 Terminaison Chaque boucle while se termine puisque le variant de boucle j est initialement strictement positif puis décrémenté à chaque itération, éventuellement jusqu'à la valeur 0. Correction[1] L'invariant de la boucle for "P(i) : la liste T[0:i] est triée" permet de prouver la correction de l'algorithme. - Initialisation : i=1 T[0:1] contient un seul élément qui est donc trié. - Récurrence : On suppose que P(i) est vraie, montrons que P(i+1) est vraie. Lycée Jules Ferry Cannes Page 3 sur 4 TSI2 Informatique Cours 4 Si P(i) est vraie alors 0! ≤ 1! ≤ ⋯ ≤ Tri par insertion # − 1!, de plus x=T[i] # − 2! ≤ • si # − 1! ≤ & = #! alors on sort de la boucle while et la proriété P(i+1) est vraie sans itération sur j : 0! ≤ 1! ≤ ⋯ ≤ # − 2! ≤ # − 1! ≤ & = #! • si # − 1! > & alors on réalise des itérations avec le while tant que : o soit T[j-1]≤ & et dans ce cas on obtient la liste 0! ≤ 1! ≤ ⋯ ≤ ' − 1! < ())))))))*))))))))+ '! = & ≤ () ')+ ≤ ⋯)) ≤)))+ #! ))1! ))*) ,- ./01, 23-1 456é8 o P(i+1) est vraie, 5,93-4é8 23-1 456é8 soit j=0 et dans ce cas tous les éléments sont remontés (donc triés) et plus grand que x : & < ()))))))))))*)))))))))))+ 1! ≤ 2! ≤ ⋯ ≤ # − 1! ≤ #! P(i+1) est vraie. 5,93-4é8 23-1 456é8 105 : 6 ,84 ;506, - Correction : la valeur qui met fin à la boucle for est i=n. On a alors P(n) vraie : la liste T[0:n] est triée et contient les n éléments de T donc la liste T est triée. Complexité (en temps) On rappelle les différentes étapes de tri sur la liste [5,8,3,2,9] 3 2 Nombre de comparaisons effectuées pour trier par insertion un tableau de longueur n : • en tout, on fait n - 1 insertions (celle de t[1], t[2] … t[n - 1]). • pour chaque insertion de t[i ] dans t[0 : i ], on fait - 1 comparaison dans le meilleur des cas (déjà trié): o Est-ce que t[i ] > t[i - 1] ? - i comparaisons dans le pire des cas (trié en sens inverse): o Est-ce que t[i ] > t[i - 1] ? o Est-ce que t[i ] > t[i - 2] ? … o Est-ce que t[i ] > t[0] ? o Est-ce qu’on est arrivé en bout de liste ? Total : 1 + … + 1 = n - 1 comparaisons dans le meilleur cas (liste triée). > -?@ A> @ 1 + … + i + … + n-1 = < − 1 ∗ = <−1 ∗ - ~ <→∞ -E comparaisons dans le pire des cas comparaisons affectations (liste triée en sens inverse). Le tri par insertion a donc une complexité meilleur cas pire cas n n n²/2 n²/2 quadratique (en O(n²)), donc médiocre. Néanmoins le tri par insertion reste un des algorithmes les plus performants lorsque la liste est presque triée : complexité linéaire. Ressources : [1] T. Audibert et A. Oussalah, Informatique : Programmation et calcul scientifique en Python et Scilab. Ellipses. [2] P. Beynet, « IPT-2 ». UPSTI. Lycée Jules Ferry Cannes Page 4 sur 4 TSI2