Le tri fusion d’un tableau
Description du tri
Dans cette partie, nous allons essayer de comprendre les principes sur lesquels s’appuie ce tri. Son implémentation, pour des tableaux ou des listes chaînées, sera développée dans les prochaines sections.
Le tri fusion s’appuie sur la méthode Diviser pour régner pour trier les $n$ éléments d’une séquence $S$ :
-
Diviser : Si la séquence $S$ est composée de 0 ou un élément, retourner $S$ immédiatement ; cette séquence est déjà triée. Si la séquence $S$ est composée de plus de deux éléments, la diviser en deux sous-séquences $S_1$ et $S_2$ contenant chacune environ la moitié des éléments de $S$ ; donc $S_1$ est formée des $\left\lfloor \dfrac{n}{2} \right\rfloor$ premiers éléments de $S$ contient les $\left\lceil \dfrac{n}{2} \right\rceil$ derniers éléments de $S$.
-
Régner : Trier récursivement $S_1$ et $S_2$.
-
Combiner : Reformer la séquence $S$ en combinant, dans l’ordre, les éléments des séquences triées $S_1$ et $S_2$.
- $\left\lfloor \dfrac{n}{2} \right\rfloor$ est la notation mathématique pour l’opération en Python
n // 2
, c’est à dire le plus grand entier inférieur au résultat de la division de $n$ par 2. - $\left\lceil \dfrac{n}{2} \right\rceil$ est la notation mathématique pour l’opération en Python
n // 2 + 1
, c’est à dire pour le plus petit entier supérieur au résultat de la division de $n$ par 2.
Pour bien comprendre la méthode employée, le plus simple est de construire un arbre binaire dans lequel chaque nœud est le résultat d’un appel récursif.
flowchart TD S("85 24 63 45 17 31 96 50") --> S1("85 24 63 45") S --> S2("17 31 96 50") S1 --> S11("85 24") S1 --> S12("63 45") S11 --> S111(("85")) S11 --> S112(("24")) S12 --> S121(("63")) S12 --> S122(("45")) S2 --> S21("17 31") S21 --> S211((17)) S21 --> S212((31)) S2 --> S22("96 50") S22 --> S221((96)) S22 --> S222((50))
Résultats des différents appels récursifs (Partie Diviser).
flowchart BT S111((85)) --> S11("24 85") S112((24)) --> S11 S121((63)) --> S12("45 63") S122((45)) --> S12 S11 --> S1("24 45 63 85") S12 --> S1 S1 --> S("17 24 31 45 50 63 85 96") S211((17)) --> S21("17 31") S212((31)) --> S21 S221((96)) --> S22("50 96") S222((50)) --> S22 S21 --> S2("17 31 50 96") S22 --> S2 S2 --> S
Résultats progressifs après les étapes Régner et Fusionner.
Décomposition de l’exécution de l’algorithme
Légende
- Chaque nœud représente un appel récursif ;
- Nœud avec une bordure en pointilles : appels récursifs non encore effectués ;
- Nœud avec une bordure en gras : appel récursif en cours ;
- Nœud vide avec une bordure : partie déjà traitée ;
- Nœud en partie vide (contenant tout de même des valeurs) : appels récursifs en attente.
flowchart TD S("85 24 63 45 17 31 96 50") -.- S1("— — — —") S -.- S2("— — — —") S1 -.- S11("— —") S1 -.- S12("— —") S11 -.- S111(("—")) S11 -.- S112(("—")) S12 -.- S121(("—")) S12 -.- S122(("—")) S2 -.- S21("— —") S21 -.- S211(("—")) S21 -.- S212(("—")) S2 -.- S22("— —") S22 -.- S221(("—")) S22 -.- S222(("—")) classDef pointillet stroke-dasharray: 5 5; class S1,S2,S11,S12,S21,S22,S111,S112,S121,S122,S211,S212,S221,S222 pointillet; classDef gras stroke-width:3px; class S gras;
flowchart TD S("— — — — 17 31 96 50") --> S1("85 24 63 45") S -.- S2("— — — —") S1 -.- S11("— —") S1 -.- S12("— —") S11 -.- S111(("—")) S11 -.- S112(("—")) S12 -.- S121(("—")) S12 -.- S122(("—")) S2 -.- S21("— —") S21 -.- S211(("—")) S21 -.- S212(("—")) S2 -.- S22("— —") S22 -.- S221(("—")) S22 -.- S222(("—")) classDef pointillet stroke-dasharray: 5 5; class S2,S11,S12,S21,S22,S111,S112,S121,S122,S211,S212,S221,S222 pointillet; classDef gras stroke-width:3px; class S1 gras;
flowchart TD S("— — — — 17 31 96 50") --> S1("— — 63 45") S -.- S2("— — — —") S1 --> S11("85 24") S1 -.- S12("— —") S11 -.- S111(("—")) S11 -.- S112(("—")) S12 -.- S121(("—")) S12 -.- S122(("—")) S2 -.- S21("— —") S21 -.- S211(("—")) S21 -.- S212(("—")) S2 -.- S22("— —") S22 -.- S221(("—")) S22 -.- S222(("—")) classDef pointillet stroke-dasharray: 5 5; class S2,S12,S21,S22,S111,S112,S121,S122,S211,S212,S221,S222 pointillet; classDef gras stroke-width:3px; class S11 gras;
flowchart TD S("— — — — 17 31 96 50") --> S1("— — 63 45") S -.- S2("— — — —") S1 --> S11("— 24") S1 -.- S12("— —") S11 --> S111(("85")) S11 -.- S112(("—")) S12 -.- S121(("—")) S12 -.- S122(("—")) S2 -.- S21("— —") S21 -.- S211(("—")) S21 -.- S212(("—")) S2 -.- S22("— —") S22 -.- S221(("—")) S22 -.- S222(("—")) classDef pointillet stroke-dasharray: 5 5; class S2,S12,S21,S22,S112,S121,S122,S211,S212,S221,S222 pointillet; classDef gras stroke-width:3px; class S111 gras;
flowchart TD S("— — — — 17 31 96 50") --> S1("— — 63 45") S -.- S2("— — — —") S1 --> S11("85 —") S1 -.- S12("— —") S11 <--> S111(("—")) S11 --> S112(("24")) S12 -.- S121(("—")) S12 -.- S122(("—")) S2 -.- S21("— —") S21 -.- S211(("—")) S21 -.- S212(("—")) S2 -.- S22("— —") S22 -.- S221(("—")) S22 -.- S222(("—")) classDef pointillet stroke-dasharray: 5 5; class S2,S12,S21,S22,S121,S122,S211,S212,S221,S222 pointillet; classDef gras stroke-width:3px; class S112 gras;
flowchart TD S("— — — — 17 31 96 50") --> S1("— — 63 45") S -.- S2("— — — —") S1 --> S11("24 85") S1 -.- S12("— —") S11 <--> S111(("—")) S11 <--> S112(("—")) S12 -.- S121(("—")) S12 -.- S122(("—")) S2 -.- S21("— —") S21 -.- S211(("—")) S21 -.- S212(("—")) S2 -.- S22("— —") S22 -.- S221(("—")) S22 -.- S222(("—")) classDef pointillet stroke-dasharray: 5 5; class S2,S12,S21,S22,S121,S122,S211,S212,S221,S222 pointillet; classDef gras stroke-width:3px; class S11 gras;
flowchart TD S("— — — — 17 31 96 50") --> S1("24 85 63 45") S -.- S2("— — — —") S1 <--> S11("— —") S1 -.- S12("— —") S11 <--> S111(("—")) S11 <--> S112(("—")) S12 -.- S121(("—")) S12 -.- S122(("—")) S2 -.- S21("— —") S21 -.- S211(("—")) S21 -.- S212(("—")) S2 -.- S22("— —") S22 -.- S221(("—")) S22 -.- S222(("—")) classDef pointillet stroke-dasharray: 5 5; class S2,S12,S21,S22,S121,S122,S211,S212,S221,S222 pointillet; classDef gras stroke-width:3px; class S1 gras;
flowchart TD S("— — — — 17 31 96 50") --> S1("24 85 — —") S -.- S2("— — — —") S1 <--> S11("— —") S1 --> S12("63 45") S11 <--> S111(("—")) S11 <--> S112(("—")) S12 -.- S121(("—")) S12 -.- S122(("—")) S2 -.- S21("— —") S21 -.- S211(("—")) S21 -.- S212(("—")) S2 -.- S22("— —") S22 -.- S221(("—")) S22 -.- S222(("—")) classDef pointillet stroke-dasharray: 5 5; class S2,S21,S22,S121,S122,S211,S212,S221,S222 pointillet; classDef gras stroke-width:3px; class S12 gras;
flowchart TD S("— — — — 17 31 96 50") --> S1("24 85 — —") S -.- S2("— — — —") S1 <--> S11("— —") S1 --> S12("— 45") S11 <--> S111(("—")) S11 <--> S112(("—")) S12 --> S121(("63")) S12 -.- S122(("—")) S2 -.- S21("— —") S21 -.- S211(("—")) S21 -.- S212(("—")) S2 -.- S22("— —") S22 -.- S221(("—")) S22 -.- S222(("—")) classDef pointillet stroke-dasharray: 5 5; class S2,S21,S22,S122,S211,S212,S221,S222 pointillet; classDef gras stroke-width:3px; class S121 gras;
flowchart TD S("— — — — 17 31 96 50") --> S1("24 85 — —") S -.- S2("— — — —") S1 <--> S11("— —") S1 --> S12("63 —") S11 <--> S111(("—")) S11 <--> S112(("—")) S12 <--> S121(("—")) S12 --> S122(("45")) S2 -.- S21("— —") S21 -.- S211(("—")) S21 -.- S212(("—")) S2 -.- S22("— —") S22 -.- S221(("—")) S22 -.- S222(("—")) classDef pointillet stroke-dasharray: 5 5; class S2,S21,S22,S211,S212,S221,S222 pointillet; classDef gras stroke-width:3px; class S122 gras;
flowchart TD S("— — — — 17 31 96 50") --> S1("24 85 — —") S -.- S2("— — — —") S1 <--> S11("— —") S1 --> S12("45 63") S11 <--> S111(("—")) S11 <--> S112(("—")) S12 <--> S121(("—")) S12 <--> S122(("—")) S2 -.- S21("— —") S21 -.- S211(("—")) S21 -.- S212(("—")) S2 -.- S22("— —") S22 -.- S221(("—")) S22 -.- S222(("—")) classDef pointillet stroke-dasharray: 5 5; class S2,S21,S22,S211,S212,S221,S222 pointillet; classDef gras stroke-width:3px; class S12 gras;
flowchart TD S("— — — — 17 31 96 50") --> S1("24 45 63 85") S -.- S2("— — — —") S1 <--> S11("— —") S1 <--> S12("— —") S11 <--> S111(("—")) S11 <--> S112(("—")) S12 <--> S121(("—")) S12 <--> S122(("—")) S2 -.- S21("— —") S21 -.- S211(("—")) S21 -.- S212(("—")) S2 -.- S22("— —") S22 -.- S221(("—")) S22 -.- S222(("—")) classDef pointillet stroke-dasharray: 5 5; class S2,S21,S22,S211,S212,S221,S222 pointillet; classDef gras stroke-width:3px; class S1 gras;
flowchart TD S("24 45 63 85 — — — —") <--> S1("— — — —") S --> S2("17 31 96 50") S1 <--> S11("— —") S1 <--> S12("— —") S11 <--> S111(("—")) S11 <--> S112(("—")) S12 <--> S121(("—")) S12 <--> S122(("—")) S2 -.- S21("— —") S21 -.- S211(("—")) S21 -.- S212(("—")) S2 -.- S22("— —") S22 -.- S221(("—")) S22 -.- S222(("—")) classDef pointillet stroke-dasharray: 5 5; class S21,S22,S211,S212,S221,S222 pointillet; classDef gras stroke-width:3px; class S2 gras;
flowchart TD S("24 45 63 85 — — — —") <--> S1("— — — —") S --> S2("17 31 50 96") S1 <--> S11("— —") S1 <--> S12("— —") S11 <--> S111(("—")) S11 <--> S112(("—")) S12 <--> S121(("—")) S12 <--> S122(("—")) S2 <--> S21("— —") S21 <--> S211(("—")) S21 <--> S212(("—")) S2 <--> S22("— —") S22 <--> S221(("—")) S22 <--> S222(("—")) classDef gras stroke-width:3px; class S2 gras;
flowchart TD S("17 24 31 45 50 63 85 96") <--> S1("— — — —") S <--> S2("— — — —") S1 <--> S11("— —") S1 <--> S12("— —") S11 <--> S111(("—")) S11 <--> S112(("—")) S12 <--> S121(("—")) S12 <--> S122(("—")) S2 <--> S21("— —") S21 <--> S211(("—")) S21 <--> S212(("—")) S2 <--> S22("— —") S22 <--> S221(("—")) S22 <--> S222(("—")) classDef gras stroke-width:3px; class S gras;
Implémentation du tri fusion pour un tableau
- Étudier le code suivant et remplacer les … pour chaque numéro.
|
|
- Étudier le code suivant et expliquer comment s’effectue la fusion.
|
|
- Étudier le comportement du programme complet à l’aide de pythontutor. Construire la liste à l’aide de l’instruction :
|
|
-
Quelle est la complexité de la fonction
fusion
? -
Essayer d’évaluer la complexité de l’algorithme sans faire de calcul.
Le tri fusion d’une liste chaînée
Dans cette section, on cherche à adapter l’algorithme de tri fusion à une liste chaînée.
-
Écrire le code de la classe
Cellule
permettant d’implémenter une liste chaînée. Cette classe sert juste de structure et définit les champsvaleur
, de typeint
, etsuivant
, de typeCellule
, initialisé àNone
. -
Dans la partie principale du programme, écrire le code qui crée la liste chaînée
[14, 11, 2, 35, 9, 1]
. -
Définir le code de la fonction
tri_fusion
dont la spécification est
|
|
Cette fonction doit utiliser la fonction coupe
(définie un peu plus bas), qui découpe une liste chaînée en deux sous-listes, et la fonction fusion
(définie elle aussi un peu plus bas) qui réalise la fusion de deux listes triées.
La fonction tri_fusion
doit mettre en œuvre le principe « Diviser pour régner ».
- Définir la fonction
coupe
dont la spécification est
|
|
- Définir la fonction
fusion
dont la spécification est
|
|