Fiche Tri Fusion

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 3

MP2I — 2023 – 2024 Fiche Memo Tri Fusion - Gérard Rozsavolgyi LIV, Valbonne

Principe du tri fusion 1 let rec fusion x y = OCaml


2 match x,y with
[1, 5, 2, 8, 3, 1, 2] 3 | [], li -> li
4 | li, [] -> li
divise 5 | h1::t1, h2::t2 ->
6 if h1 < h2
[1, 5, 2] [8, 3, 1, 2] 7 then h1 :: fusion t1 (h2::t2)
8 else h2 :: fusion (h1 :: t1) t2
tri_fusion tri_fusion
Puis le tri fusion s’écrit alors :
[1, 5, 2] [1, 2, 3, 8]
1 let rec tri_fusion liste = OCaml
2 match liste with
fusion
3 | [] -> []
[1, 1, 2, 2, 3, 5, 8] 4 | [x] -> [x]
5 | _ -> let lg = (List.length liste / 2) in
6 let gauche = take lg liste in
FIGURE 1 – Tri fusion appliqué à [1, 5, 2, 8, 3, 1, 2] 7 let droite = drop lg liste in
8 fusion (tri_fusion gauche) (tri_fusion droite)

On commence par diviser la liste [1, 5, 2, 8, 3, 1, 2] en deux moitiés sensiblement de même


taille. On peut aussi prendre un élément sur deux dans la liste pour constituer les deux sous-
listes. Ensuite, on utilise deux appels récursifs à tri_fusion pour trier les deux sous-listes Programme du tri fusion en C
obtenues, et enfin on fusionne les deux listes pour retrouver la liste triée.
Quelques structures et déclarations utiles en C tout d’abord, avec une structure de tableau
qui connait sa taille :
Programme du tri fusion en OCaml C
1 #include <stdbool.h>
On peut s’aider de deux petites fonctions utilitaires qui vont nous permettre de conserver ou 2 #include <stdlib.h>
de supprimer les 𝑛 premiers éléments d’une liste : 3 #include <stdio.h>
4

1 let rec take n liste = OCaml 5 struct intarray {


2 if n = 0 then [] else match liste with 6 int * data;
3 | [] -> failwith "can not take from empty list" 7 int length;
4 | hd::tl -> hd :: take (n - 1) tl 8 };
9

et 10 typedef struct intarray intarray_t;


11

1 let rec drop n liste = OCaml 12 intarray_t* new_intarray(int size)


2 if n = 0 then liste else match liste with 13 {
3 | [] -> failwith "can not take from empty list" 14 intarray_t * t = malloc(sizeof(intarray_t));
4 | hd::tl -> drop (n - 1) tl 15 t->data = malloc(sizeof(int) * size);
16 t->length = size;
La fusion s’écrit alors : 17 return t;
MP2I — 2023 – 2024 Fiche Memo Tri Fusion - Gérard Rozsavolgyi LIV, Valbonne

18 } 6 if (t1->data[i1] < t2->data[i2])


19 7 { res->data[i++] = t1->data[i1++]; }
20 void free_intarray(intarray_t* t) 8 else res->data[i++] = t2->data[i2++];
21 { 9

22 free(t->data); 10 while (i1 < t1->length) res->data[i++] = t1->data[i1++];


23 free(t); 11

24 return ; 12 while (i2 < t2->length) res->data[i++] = t2->data[i2++];


25 } 13

14 return res;
Pour remplir aléatoirement une telle structure : 15 }

1 intarray_t* randarray(int size) C Nous sommes prêts à lancer le tri fusion !


2 {
3 intarray_t* res = new_intarray(size); 1 intarray_t* trifusion(intarray_t * t) C
4 2 {
5 for (int i=0; i<size;i++) 3 if (t->length <=1) { return subarray(t, 0, t->length) ;}
6 { 4 int m = t->length/2;
7 res->data[i] = rand()%100; 5 intarray_t* left = subarray(t, 0, m);
8 } 6 intarray_t* right = subarray(t, m, t->length);
9 7 intarray_t* tleft = trifusion(left);
10 return res; 8 intarray_t* tright = trifusion(right);
11 } 9 free_intarray(left);
10 free_intarray(right);
Pour extraire un sous-tableau de taille donnée : 11

12 intarray_t* res = fusion( tleft,tright );


1 intarray_t* subarray (intarray_t* t, int debut, int fin) C 13 free_intarray(tleft);
2 { 14 free_intarray(tright);
3 int size = fin-debut; 15 return res;
4 intarray_t* res = new_intarray(size); 16 }
5 for (int i = 0; i < size; i++)
6 {
7

8 }
res->data[i] = t->data[debut+i];
Complexité du tri fusion
9 return res ; Supposons d’abord que la taille du tableau initial est 𝑁 = 2𝑝 une puissance de 2. On obtient
10 } alors une complexité (évaluée par le nombre de tests) :
On fusionne deux tableaux déjà triés selon la méthode standard. Ne pas oublier de compléter
1 si N = 1(p = 0)
à la fin par les éléments du tableau non encore totalement consommé. 𝐶(𝑁) = {
2𝐶 ( 𝑁2 ) + 𝑁 sinon
1 intarray_t* fusion(intarray_t* t1, intarray_t* t2) C
(deux appels récursifs avec des tableaux de taille divisée par 2, plus le coût de la fusion).
2 {
Si on réécrit :
3 intarray_t* res = new_intarray(t1->length + t2->length);
4 int i=0, i1=0, i2=0;
1 si p = 0
5 while (i1 < t1->length && i2 < t2->length) 𝐶 (2𝑝 ) = {
2𝐶 (2𝑝−1 ) + 2𝑝 sinon
MP2I — 2023 – 2024 Fiche Memo Tri Fusion - Gérard Rozsavolgyi LIV, Valbonne

Ou encore, si on divise par 2𝑝 :

𝐶 (2𝑝 ) ⎧1 si p = 0
= ⎨ 𝐶(2𝑝−1 )
2𝑝
⎩ 2𝑝−1 + 1 sinon
𝐶(2𝑝 )
En posant 𝑢𝑝 = 2𝑝
on a alors :

1 si p = 0
𝑢𝑝 = {
𝑢𝑝−1 + 1 sinon
On reconnaît une suite arithmétique, dont on peut calculer le terme général 𝑢𝑝 = 1 + 𝑝, d’où
il vient 𝐶 (2𝑝 ) = 2𝑝 𝑢𝑝 = 𝑝 ⋅ 2𝑝 + 𝑜 (2𝑝 ). Pour repasser ”en N ”, il suffit de s’apercevoir que
𝑝 = log(𝑁), et donc on a finalement :

𝐶(𝑁) = 𝑂(𝑁 ⋅ log(𝑁))


Si maintenant le tableau n’est pas de taille 2𝑝 , il suffit de mettre 𝑁 en sandwich entre deux
puissances de 2 sucessives :

2𝑝 < 𝑁 < 2𝑝+1


La fonction de complexité étant croissante, on a donc

𝐶 (2𝑝 ) ≤ 𝐶(𝑁) ≤ 𝐶 (2𝑝+1 )


soit encore

𝑝.2𝑝 ≤ 𝐶(𝑁) ≤ (𝑝 + 1)2𝑝+1


et donc

𝑘1 𝑁 log(𝑁) ≤ 𝐶(𝑁) ≤ 𝑘2 log(𝑁)


et finalement

𝐶(𝑁) = 𝑂(𝑁 ⋅ log(𝑁))

Vous aimerez peut-être aussi

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy