Terminale · Algorithmique

Le tri fusion

Deux listes déjà triées peuvent être réunies sans recommencer un tri complet. Il suffit de comparer leurs premiers éléments encore disponibles. Le tri fusion exploite cette opération après avoir décomposé le problème jusqu’à des listes si petites qu’elles sont déjà triées.

SofienAvec SofienIngénieur et enseignant en informatique
Dans ce chapitre

Un cap pour ce chapitre

Ce que vous saurez faire

  • Réaliser une fusion sans perdre de valeur.
  • Tracer les divisions et les remontées.
  • Expliquer le coût en n log n et la mémoire utilisée.
Les bases utiles pour commencer

Fusionner deux entrées déjà triées

Prenons [2,7] et [1,5,8]. On compare deux et un : un est ajouté au résultat. Puis deux et cinq : deux est ajouté. Puis sept et cinq : cinq est ajouté. Puis sept et huit : sept est ajouté. La première liste est épuisée ; on ajoute le reste, huit. Le résultat est [1,2,5,7,8].

À chaque choix, la plus petite valeur encore disponible se trouve en tête de l’une des deux listes, puisqu’elles sont triées. Le prérequis est essentiel. La fusion ne peut pas compenser une entrée non triée en choisissant seulement parmi les deux positions courantes.

def fusion(gauche, droite):
    i, j = 0, 0
    resultat = []
    while i < len(gauche) and j < len(droite):
        if gauche[i] <= droite[j]:
            resultat.append(gauche[i])
            i += 1
        else:
            resultat.append(droite[j])
            j += 1
    resultat.extend(gauche[i:])
    resultat.extend(droite[j:])
    return resultat

Diviser jusqu’aux bases

Une liste vide ou singleton est déjà triée. Sinon, on la coupe en deux parties aussi proches que possible en taille, puis on trie récursivement chaque partie. Une fois ces résultats obtenus, on les fusionne. L’appel parent attend donc les deux réponses avant sa combinaison.

def tri_fusion(valeurs):
    if len(valeurs) <= 1:
        return valeurs.copy()
    milieu = len(valeurs) // 2
    gauche = tri_fusion(valeurs[:milieu])
    droite = tri_fusion(valeurs[milieu:])
    return fusion(gauche, droite)

La fonction fusion est le composant décrit dans cette page. Cette version crée de nouvelles listes et conserve la liste d’entrée. Une implémentation différente pourrait choisir d’autres interfaces, à condition de les annoncer.

Justifier la correction et les doublons

Pendant une fusion, le résultat contient dans l’ordre les plus petites valeurs déjà consommées. Les indices indiquent exactement ce qu’il reste dans chaque entrée. Choisir la plus petite tête conserve cette propriété. Lorsqu’une entrée est vide, le reste de l’autre peut être ajouté puisqu’il est trié et supérieur ou égal au dernier élément choisi.

Les doublons doivent être conservés. Pour une fusion stable, on choisit l’élément de gauche en cas d’égalité : l’ordre relatif d’éléments égaux venant de l’entrée initiale est alors préservé. La stabilité est une propriété supplémentaire utile, distincte du simple ordre croissant des valeurs.

Une liste triée ne suffit pas à certifier un tri correct : elle doit aussi contenir exactement les mêmes occurrences que l’entrée. Pour [4,4,1], [1,4] respecte l’ordre mais perd une donnée. Comparez les longueurs et les multiplicités, puis seulement l’ordre et, si nécessaire, la stabilité.

Compter le travail par niveaux

Fusionner deux listes de longueur totale n demande un travail linéaire : chaque élément est ajouté une fois. Le découpage équilibré produit environ log₂ n niveaux. À un même niveau, les différentes fusions manipulent au total une quantité proportionnelle à n. Le coût global est donc de l’ordre de n log n, y compris dans le pire cas de cette organisation.

La version présentée utilise des listes supplémentaires. Une implémentation standard de tri fusion peut travailler avec une mémoire auxiliaire linéaire, à laquelle s’ajoute une pile logarithmique. Les détails des copies influencent les constantes ; annoncer un tri en place pour ce code serait incorrect.

Exemple suivi : trier une longueur impaire

Pour [7,2,5,1,4], la coupure au milieu entier donne [7,2] et [5,1,4]. Le premier côté devient [2,7]. Le second se coupe en [5] et [1,4], puis devient [1,4,5]. La fusion finale compare 2 et 1, 2 et 4, 7 et 4, 7 et 5 ; elle produit [1,2,4,5] puis ajoute le reste [7]. Le résultat contient cinq valeurs, comme l’entrée.

Une taille impaire ne demande pas une règle spéciale de fusion : les moitiés peuvent différer d’une unité. Ce sont les bornes de division et les cas de base qui doivent rester corrects. Le code emploie des tranches Python pour écrire les parties ; lire valeurs[:milieu] comme la partie avant milieu et valeurs[milieu:] comme celle qui commence à milieu suffit ici. Ces copies ont un coût et font partie de cette implémentation particulière.

Exemple suivi : voir la stabilité avec des étiquettes

Imaginons les données (4,A), (2,B), (4,C), (2,D), à trier seulement selon leur nombre. Une sortie stable conserve B avant D parmi les deux valeurs 2, et A avant C parmi les deux valeurs 4. En fusionnant deux parties, choisir l’élément gauche lorsque les clés sont égales préserve leur ordre initial, puisque la partie gauche venait avant la droite dans l’entrée.

Avec des nombres seuls, les deux occurrences de 4 sont visuellement indiscernables ; leurs étiquettes rendent la propriété testable. La stabilité n’est pas indispensable à chaque usage, mais elle importe lorsqu’un premier classement doit être conservé entre des éléments ex æquo. Les comparaisons comptées dans l’atelier portent sur les valeurs pendant les fusions. Les copies des restes représentent aussi du travail, même lorsqu’elles ne demandent plus de comparaison avec une autre tête.

À vous de faire varier les choses

Suivez la remontée des fusions

Entrez au plus douze nombres et révélez les fusions terminées. Le nombre de comparaisons ne compte que les fusions déjà révélées. Prédisez la prochaine fusion et le reste à recopier avant de progresser.

Lire le résultat de l’expérience initiale

3 fusion(s) terminée(s) observée(s). Prévoyez la suivante.

Chaque ligne correspond à une fusion réellement terminée après le traitement récursif de ses enfants.

Gauche triéeDroite triéeFusion obtenue
353, 5
83, 53, 5, 8
922, 9

Le résultat remonte depuis les petites listes ; chaque fusion repose sur deux résultats déjà ordonnés.

De la compréhension à l’autonomie

À vous de résoudre

Cherchez d’abord par vous-même. Vérifiez les résultats demandés, utilisez les indices si nécessaire, puis comparez votre méthode à la correction.

Exercice 1 · Appliquer#

Réaliser une fusion

Fusionnez [1,4,9] et [2,4,6]. Quelle séquence obtenez-vous ?

Indice 1

Comparez seulement les premières valeurs encore disponibles.

Indice 2

Conservez les deux occurrences de quatre.

Comprendre la correction

Le résultat est [1,2,4,4,6,9]. Avec un choix gauche en cas d’égalité, le quatre de la première liste précède celui de la seconde. Supprimer l’un des deux changerait les données au lieu de seulement les trier.

Exercice 2 · Comprendre#

Comprendre un reste

Lors d’une fusion, la gauche est épuisée et la droite contient encore [7,8,10]. Faut-il comparer ces valeurs deux à deux avant de les ajouter ?

Indice 1

Le contrat garantit déjà l’ordre de chaque entrée.

Indice 2

Toutes les valeurs plus petites ont été choisies.

Comprendre la correction

Non. Le reste est déjà trié et peut être ajouté directement. Le travail consiste à recopier ces valeurs, pas à rétablir leur ordre. Cette étape est indispensable pour ne pas perdre des éléments après l’épuisement d’une entrée.

Exercice 3 · Corriger#

Détecter une mauvaise base

La base teste seulement len(valeurs)==1. Que peut-il arriver si l’on appelle le tri avec une liste vide ?

Indice 1

Le découpage d’une liste vide reste vide.

Indice 2

La taille diminue-t-elle entre les appels ?

Comprendre la correction

La fonction peut rappeler indéfiniment le tri sur des listes vides jusqu’à une limite de récursion. Il faut inclure le cas zéro, par exemple len(valeurs)<=1. Une base correcte doit couvrir toutes les petites entrées autorisées.

Exercice 4 · Justifier#

Comparer les ordres de grandeur

Pour n=1024, comparez les expressions n² et n log₂ n. S’agit-il de temps en secondes ?

Indice 1

1024 vaut deux puissance dix.

Indice 2

Calculez les expressions sans leur attribuer une unité absente.

Comprendre la correction

n² vaut 1 048 576 et n log₂ n vaut 10 240. Ce sont ici des modèles de croissance ou de comptage, pas des durées mesurées en secondes. Ils montrent l’intérêt d’un meilleur ordre de coût lorsque n augmente.

Exercice 5 · Problème de synthèse#

Problème : suivre une fusion complète

Fusionnez [2,6,8] et [1,3,7,9]. Écrivez les paires comparées, le résultat et le reste ajouté sans comparaison. Combien de comparaisons de valeurs sont effectuées ? Que changerait une entrée droite vide ?

Indice 1

Arrêtez les comparaisons dès qu’un côté est épuisé.

Indice 2

L’ajout d’un reste n’est pas une comparaison de deux têtes.

Comprendre la correction

Les paires sont (2,1),(2,3),(6,3),(6,7),(8,7),(8,9), soit six comparaisons. Le résultat est [1,2,3,6,7,8,9] ; [9] est ajouté après épuisement de la gauche. Avec une droite vide, aucune comparaison entre valeurs des deux entrées n’est nécessaire et toute la gauche est copiée. Le travail de copie subsiste.

Exercice 6 · Problème de synthèse#

Problème : tester ordre, conservation et stabilité

On trie par nombre les éléments (4,A),(2,B),(4,C),(2,D). Donnez la sortie stable. Une version renvoie (2,D),(2,B),(4,A),(4,C) : quelles propriétés respecte-t-elle et laquelle viole-t-elle ? Une autre renvoie (2,B),(4,A) : quel défaut supplémentaire apparaît ?

Indice 1

Les étiquettes distinguent les occurrences égales.

Indice 2

L’ordre croissant ne suffit pas à garantir la conservation.

Comprendre la correction

La sortie stable est (2,B),(2,D),(4,A),(4,C). La première version conserve les éléments et trie les nombres, mais inverse B et D : elle n’est pas stable. La seconde perd deux occurrences ; ce n’est plus un tri correct du contenu initial. Pour tester les garanties, on vérifie séparément ordre, conservation et maintien des ex æquo.

Exercice 7 · Problème de synthèse#

Problème : analyser une division équilibrée

On trie huit valeurs distinctes en divisant toujours en deux moitiés. Combien de niveaux de fusion existe-t-il ? Combien de fusions élémentaires, intermédiaires puis finales ? Si chaque fusion utilise son maximum de comparaisons, quel total obtient-on ? Justifiez les maxima 1,3 et 7.

Indice 1

Une fusion de p+q valeurs compare au plus p+q-1 paires.

Indice 2

Les niveaux fusionnent des résultats de tailles 1, puis 2, puis 4.

Comprendre la correction

Il y a trois niveaux : quatre fusions 1+1, deux fusions 2+2, une fusion 4+4. Les maxima valent 1,3,7 parce qu’après au plus p+q-1 choix un côté est épuisé. Le total maximal est 4×1+2×3+7=17. Le travail de copie reste proportionnel aux huit valeurs à chaque niveau, ce qui explique la croissance en n log n.

Les erreurs qui méritent un détour

Oublier le reste d’une liste après épuisement de l’autre.
Tous les éléments doivent apparaître dans le résultat.
Confondre concaténation et fusion.
La concaténation ne réordonne pas la frontière des deux listes.

La fiche à garder

L’essentiel à retenir

  • La fusion suppose ses deux entrées triées.
  • La récursion prépare ces entrées puis remonte les fusions.
  • Le découpage équilibré conduit à un coût en n log n.

Cette notion au bac

Retrouvez ces idées dans un sujet complet, avec des indices, une correction expliquée et des ateliers.

Le prochain pas

Retrouver le catalogue de Terminale

Ce chapitre s’appuie sur le programme officiel de Terminale (PDF, nouvel onglet). Les explications et exercices sont proposés pour l’apprentissage.