CSI25101 Tri Plus efficace
CSI25102 Tri récursif Le tri récursif divise les données de grande taille en deux presque moitiés et est appelé récursivement sur ces plus petites séries de données. Ceci est appelé le paradigme Diviser pour régner (Divide-and-Conquer). Nous verrons deux tris récursifs: tri par fusion (Merge Sort) tri rapide (Quick Sort)
CSI25103 Diviser pour règner Paradigme diviser pour régner : Diviser: Si la taille des données est trop grande pour les traiter d’une façon directe alors les diviser en deux ou plusieurs sous-ensembles disjoints. Appliquer récursivement: Utiliser l’approche diviser pour régner afin de résoudre les sous-problèmes associés aux sous-ensembles de données. Régner: Prendre les solutions aux sous-problèmes et “fusionner” ces solutions afin d’obtenir la solution au problème initial. Le cas de base pour la récursivité est le sous-problème trivial, souvent de taille 0 ou 1.
CSI25104 Tri par fusion (Mergesort)
CSI25105 Tri par fusion Le tri par fusion est un algorithme de tri basé sur le paradigme diviser pour régner Comme le tri par tas Il utilise un comparateur Il est exécuté en un temps O(n log n) Contrairement au tri par tas Il n'utilise pas une file à priorité auxiliaire Il accède aux données d’une manière séquentielle (convenable pour trier des données sur un disque)
CSI25106 Tri par fusion Le tri par fusion sur une séquence d'entrée S avec n éléments consiste en trois étapes: Diviser: diviser S en 2 groupes d’environ n/2 éléments chacun Appliquer récursivement : trier récursivement S 1 et S 2 Régner: fusionner S 1 et S 2 dans une séquence triée
CSI25107 Fusion de deux séquences triées : L’étape ‘Régner’ fusionne les 2 séquences triées A et B dans une séquence trié S Comment? Comparer l'élément le plus petit de A et celui de B et insérer le plus petit dans S La fusion des deux séquences triées, chacune avec n/2 éléments prend un temps O (n)
CSI25108 Tri par fusion Algorithm mergeSort(S, C) Input séquence S avec n éléments, comparateur C Output séquence S triée selon C if S.size() > 1 (S 1, S 2 ) partition(S, n/2) mergeSort(S 1, C) mergeSort(S 2, C) S merge(S 1, S 2, C) Pas sur-place
CSI A B S
CSI Fusion de deux séquences triées Algorithm merge(A, B,C) Input séquences triées A et B comparateur C Output séquence triée de A B S séquence vide while A.isEmpty() B.isEmpty() if C.isLessThan(A.first().element(), B.first().element()) S.insertLast(A.remove(A.first())) else S.insertLast(B.remove(B.first())) while A.isEmpty() S.insertLast(A.remove(A.first())) while B.isEmpty() S.insertLast(B.remove(B.first())) return S Pas sur-place
CSI Arbre de tri par fusion 7 2 9 4 2 2 79 4 72 29 94 4 L’exécution du tri par fusion est représenté comme un arbre binaire chaque nœud représente un appel récursif du tri par fusion et emmagasine la séquence non triée avant l'exécution et sa partition La séquence triée à la fin de l'exécution la racine représente l’appel initial les enfants sont les appels pour les sous-séquences les feuilles sont les appels pour les séquences de taille 0 ou 1
CSI Tri par fusion – Exemple1 Partition 7 72 29 94 43 38 86 61 CSI Aut.09 - Tris recursifs
CSI Appel récursif + partition 7 2 CSI Aut.09 - Tris recursifs Tri par fusion – Exemple1
CSI CSI Aut.09 - Tris recursifs Tri par fusion – Exemple1 Appel récursif + partition
CSI 2 7 77 CSI Aut.09 - Tris recursifs Tri par fusion – Exemple1 Appel récursif + appel de base
CSI 2 7 77 72 22 CSI Aut.09 - Tris recursifs Tri par fusion – Exemple1 Appel récursif + appel de base
CSI Fusion 7 2 2 77 72 22 CSI Aut.09 - Tris recursifs Tri par fusion – Exemple1
CSI Appel récursif, …, appel de base, fusion 7 2 2 77 72 22 29 94 CSI Aut.09 - Tris recursifs Tri par fusion – Exemple1
CSI Fusion 7 2 9 4 2 77 72 22 29 94 CSI Aut.09 - Tris recursifs Tri par fusion - Example
CSI 9 4 2 77 72 22 29 94 43 33 38 88 86 66 61 11 CSI Aut.09 - Tris recursifs Tri par fusion - Example Appel récursif, …, appel de base, fusion
CSI Fusion 7 2 9 4 2 77 72 22 29 94 43 33 38 88 86 66 61 11 CSI Aut.09 - Tris recursifs Tri par fusion – Exemple1
CSI Tri par fusion – Exemple2
CSI
CSI
CSI
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI
CSI Fusionner 2398
CSI Fusionner 2398
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI
CSI
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI Fusionner
CSI
CSI
CSI Analyse du tri par fusion profondeur#séqstaille 01n 12 n2n2 i2i2i n2in2i ……… Le hauteur h de l'arbre de tri par fusion est O(log n) à chaque appel récursif, nous divisons la séquence en deux La quantité de travail aux nœuds de profondeur i est O(n) on divise et fusionne 2 i séquences de taille n 2 i on fait 2 i 1 appels récurrents Ainsi, le temps total d’exécution du tri par fusion est O(n log n)
Fusion CSI251064
Tri fusion CSI251065
CSI Tri rapide (Quicksort)
CSI Tri rapide Tri rapide est un algorithme de triage aléatoire basé sur le paradigme divide-and-conquer: Diviser: choisir un élément au hasard x (appelé le pivot) et partitionner S en sous-ensembles L: les éléments plus petit que x E: les éléments égaux à x G: les éléments plus grand que x Appliquer récursivement : tri L et G Conquérir : fusionner L, E et G x x L G E x
CSI i PIVOT x S.elemAtRank(i) (L,G) Partition(S,x) QuickSort(L) QuickSort(G) QuickSort(S) x S x L G E Pas sur-Place
CSI Partition Nous partitionnons une séquence d'entrée comme suit : Nous enlevons, un à un, chaque élément y de S et Nous insérons y dans L, E ou G, dépendant du résultat de la comparaison avec le pivot x Chaque insertion et suppression sont au début ou à la fin d'une séquence, et alors il prend un temps O (1) Ainsi, l'étape de partition du tri rapide prend un temps O(n) Algorithm partition(S, p) entrées séquence S, position p du pivot sortie sous-séquences L, E, G des éléments de S plus petits que, égaux à, ou plus grands que le pivot, resp. L, E, G séquences vides x S.remove(p) while S.isEmpty() y S.remove(S.first()) if y < x L.insertLast(y) else if y = x E.insertLast(y) else { y > x } G.insertLast(y) return L, E, G Pas sur-place
CSI Tri rapide - Arbre Une exécution du tri rapide est représentée par un arbre binaire: Chaque nœud représente un appel récursif du tri rapide et emmagasine: La séquence non triée avant l'exécution et son pivot La séquence triée à la fin de l'exécution La racine est l'appel initial Les feuilles sont les appels sur les sous-séquences de taille 0 ou 29 9 70 CSI Aut.09 - Tris recursifs 4 47 7
CSI Sélection du pivot CSI Aut.09 - Tris recursifs Tri rapide – Exemple1
CSI Partition, appel récursif, sélection du pivot CSI Aut.09 - Tris recursifs Tri rapide – Exemple1
CSI 11 CSI Aut.09 - Tris recursifs Tri rapide – Exemple1 Partition, appel récursif, appel de base
CSI 11 14 3 44 4 74 CSI Aut.09 - Tris recursifs Tri rapide – Exemple1 Appel récursif,…, appel de base, joindre, joindre
CSI 11 14 3 44 4 75 CSI Aut.09 - Tris recursifs Tri rapide – Exemple1 Partition, appel récursif,…, appel de base
CSI Partition, …, appel récursif, appel de base 11 14 3 34 44 4 9 99 9 76 CSI Aut.09 - Tris recursifs Tri rapide – Exemple1
CSI Joindre, joindre 11 14 3 34 44 4 9 99 9 77 CSI Aut.09 - Tris recursifs Tri rapide – Exemple1
CSI Pire de cas : temps d'exécution Le pire de cas pour le tri rapide arrive quand le pivot est l’élément unique minimum ou maximum Un des ensembles L et G a la taille n 1 et l'autre a la taille 0 Le temps d’exécution est proportionnel à la somme n (n 1) … 2 Alors, dans le pire des cas, le temps d'exécution du tri rapide est O(n 2 ) profondeurtemps 0n 1 n 1 …… 1 …
CSI Temps moyen d'exécution Considérer un appel récursive au tri rapide sur une séquence de taille s. Soit: Pour la moitié des appels: la taille de L et G est inférieure à 3s 4 Pour l’autre moitié: soit L ou G a une taille plus grande que 3s 4 En moyenne, chaque niveau i traitera une séquence de taille ( 3 4 ) i 2 n Le dernier niveau est atteint lorsque ( 3 4 ) i 2 n = 1. C’est-à-dire i=2log4/3n La hauteur de l’arbre est donc O(log n )
CSI Temps prévu d'exécution Ainsi, nous avons La hauteur prévue de l'arbre de tri rapide est O(log n) La quantité de travail total fait aux nœuds de même profondeur de l'arbre de tri rapide est O(n) Ainsi, le temps prévu d’exécution est O(n log n)
CSI Dans l'étape de partition, nous utilisons des opérations de remplacement pour réarranger les éléments des séquences d’entrées tel que les éléments plus petits que le pivot ont des rangs plus petit que h les éléments égaux au pivot ont des rangs entre h et k les éléments plus grands que le pivot ont des rangs plus grand que k Les appels récursifs considèrent les éléments avec un rang plus petit que h les éléments avec un rang plus grand que k Tri rapide sur place
CSI Étape 1 pour Diviser: l scrute la séquence de la gauche, et r de la droite Un échange est exécuté quand l est à un élément plus grand que le pivot et r est à un élément plus petit que le pivot. Tri rapide sur place
CSI Un échange final avec le pivot complète l’étape pour Diviser Tri rapide sur place
CSI Algorithm inPlacePartition(p,s,e) Entrées: position p du pivot; s et e sont les limites dans la séquence Sorties: l et r tel que : r-1=indice du dernier élément plus petit que le pivot l+1=indice du premier élément plus grand que le pivot l s, r e-1 swap S[p] with S[e], p e while l ≤ r while S[l] l l l+1 while S[r] > S[p] and r > l r r-1 if r > l swap S[r] with S[l] swap S[l] with S[p] return r,l On partitionne la séquence en utilisant deux indices pour la décomposer en L,E et G Répéter jusqu'à ce que l et r se croisent: l parcourt le tableau de gauche à droite jusqu’à trouver un élément ≥ le pivot r parcourt le tableau de droite à gauche jusqu’à trouver un élément < le pivot Échanger les éléments d’indices l et r Tri rapide sur place
CSI Algorithm inPlaceQuickSort(S, l, r) Entrées séquence S, rangs l et r Sortirs séquence S avec les éléments des rangs entre l et r réarrangés dans l'ordre croissant if l r return i entier aleatoire entre l et r x S.elemAtRank(i) (h, k) inPlacePartition(i,l,r) inPlaceQuickSort(S, l, h 1) inPlaceQuickSort(S, k 1, r) Tri rapide sur place
CSI251086
CSI AlgorithmTimeNotes Tri par sélection O(n 2 ) tous les cas sur-place lent (acceptable avec peu de données) Tri par insertion O(n 2 ) pire et moyen sur-place lent (acceptable avec peu de données) Tri rapide O(n 2 ) au pire O(n log n) en moyenne sur-place, partition très simple le plus rapide (bon avec un grand nombre d’entrées) Tri par monceau O(n log n) tous les cas sur-place rapide (bon avec un grand nombre d’entrées) Tri fusion O(n log n) tous les cas accès séquentiel (distribuées) fast (bon avec un très grand nombre d’entrées)