En tant qu'autodidacte, je reprends les algorithmes depuis le début, et je documente cela, pour moi mais aussi pour ceux qui seraient intéressés. Aujourd'hui, plongeons dans le tri à bulles (Bubble Sort) !
Imaginez que vous soyez l'entraîneur d'une équipe de foot à 7 joueurs et que vous deviez les aligner dans l'ordre de leur numéro de maillot pour une photo d'équipe. Vos joueurs sont éparpillés et vous devez les réorganiser. Le tri à bulles tire son nom de la façon dont les éléments "remontent" dans la liste, comme des bulles dans l'eau !
L'objectif est simple : ranger les joueurs du plus petit au plus grand numéro. Voici comment procéder :
Vous commencez par le premier joueur
Vous le comparez avec son voisin de droite
Si son numéro est plus grand, ils échangent leur place
Vous continuez ainsi jusqu'au bout de la ligne
Vous recommencez depuis le début jusqu'à ce que tout soit ordonné
Voici une première version du code, simple mais fonctionnelle :
export default function bubbleSort(arr) {
const n = arr.length;
for (let i = 0; i < n; i++) {
for (let j = 0; j < n - 1; j++) {
// Si le joueur actuel a un numéro plus grand que son voisin
if (arr[j] > arr[j + 1]) {
// On les échange de place
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return arr;
}
Première amélioration : si pendant un tour complet aucun joueur n'a bougé, c'est que l'équipe est déjà bien alignée !
export default function bubbleSort(arr) {
const n = arr.length;
for (let i = 0; i < n; i++) {
let swapped = false;// Notre indicateur d'échange
// Notez le n - i - 1 : on sait que les i derniers éléments sont déjà triés !
for (let j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
swapped = true;
}
}
// Si aucun échange n'a eu lieu, c'est que tout est trié
if (!swapped) break;
}
return arr;
}
Une autre amélioration : à chaque passage, le plus grand numéro "remonte" à sa position finale. Nous n'avons donc plus besoin de vérifier cette partie déjà triée lors des passages suivants (d'où le n - i - 1
dans la boucle interne).
Pour mieux comprendre, prenons un exemple avec les numéros [5, 1, 4, 2, 8] :
Tour 1 : [5, 1, 4, 2, 8] → [1, 5, 4, 2, 8] → [1, 4, 5, 2, 8] → [1, 4, 2, 5, 8]
Tour 2 : [1, 4, 2, 5, 8] → [1, 2, 4, 5, 8]
Tour 3 : [1, 2, 4, 5, 8] → Terminé !
Simple à comprendre et à implémenter
Stable (préserve l'ordre relatif des éléments égaux)
Efficace pour les petits tableaux
Peu de mémoire supplémentaire requise (tri en place)
Complexité quadratique O(n²) dans le pire et le cas moyen
Inefficace sur de grandes quantités de données
Nombre élevé d'échanges même pour des tableaux presque triés
Le tri à bulles est excellent pour :
Introduire les concepts de base du tri
Comprendre les notions de complexité algorithmique
S'exercer à l'optimisation d'algorithmes
Visualiser concrètement le processus de tri
Pour bien comprendre comment fonctionne notre tri à bulles en pratique, et si vous connaissez un minimum le langage Python
, voici une version plus détaillée avec des tests unitaires et des messages de débogage. Cette version est particulièrement utile pour l'apprentissage, car elle montre chaque échange en temps réel :
import unittest
from random import shuffle
def bubble_sort(arr):
n = len(arr)
# Optimisation : sortie rapide pour les listes vides ou à un élément
if n <= 1:
return arr
for i in range(n):
swapped = False
# On parcourt jusqu'à n-i-1 car les i derniers éléments sont déjà triés
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
# Échange des joueurs
arr[j], arr[j + 1] = arr[j + 1], arr[j]
swapped = True
# Affichage pédagogique des échanges
print(f'{arr[j]} <=> {arr[j+1]}')
print(f'Tour : {i + 1}')
# Optimisation : arrêt si aucun échange n'a été nécessaire
if not swapped:
break
return arr
# Tests unitaires pour vérifier notre implémentation
class TestBubbleSort(unittest.TestCase):
def test_bubble_sort(self):
players = [1, 2, 3, 4, 5, 6, 7]
shuffled_players = players[:]
shuffle(shuffled_players)
sorted_players = bubble_sort(shuffled_players)
self.assertEqual(sorted_players, sorted(players))
if __name__ == '__main__':
# Exemple avec une équipe de 7 joueurs
players = [1, 2, 3, 4, 5, 6, 7]
shuffle(players)
print(f'Équipe non ordonnée : {players}')
# Tri de l'équipe
sorted_team = bubble_sort(players)
print(f'Équipe ordonnée : {sorted_team}')
# Lancement des tests unitaires
unittest.main()
Optimisations intégrées :
Détection des listes déjà triées avec swapped
Sortie rapide pour les listes vides ou à un élément
Réduction de la zone à trier à chaque passage (n - i - 1
)
Débogage visuel :
Affichage de chaque échange de joueurs
Suivi du progrès tour par tour
Visualisation de l'état initial et final
Tests unitaires :
Vérification automatique du bon fonctionnement
Test avec une équipe complète
Comparaison avec la fonction sorted()
de Python
Voici ce que vous pourriez voir lors de l'exécution :
Équipe non ordonnée : [5, 2, 7, 1, 4, 3, 6]
2 <=> 5
1 <=> 7
3 <=> 4
Tour : 1
2 <=> 7
1 <=> 4
3 <=> 6
Tour : 2
2 <=> 4
1 <=> 3
Tour : 3
1 <=> 2
Tour : 4
Équipe ordonnée : [1, 2, 3, 4, 5, 6, 7]
En tant qu'autodidacte, le tri à bulles a été mon premier "tacle" dans le monde des algorithmes, et je suis ravi de partager cette expérience avec vous. Comme un joueur qui apprend d'abord les bases avant de tenter des gestes techniques plus complexes, j'ai choisi de commencer par cet algorithme simple mais instructif.
La visualisation est clé : transformer un concept abstrait en équipe de foot m'a aidé à mieux comprendre
L'optimisation n'est pas réservée aux experts : même un débutant peut améliorer son code pas à pas
Les tests sont nos amis : ils nous donnent confiance dans notre code
Ce premier algorithme n'est que le début. Dans les prochains articles, nous explorerons ensemble des algorithmes plus avancés, toujours avec cette approche concrète et accessible.
Restez à l'écoute pour découvrir :
Le tri fusion (Merge Sort)
Le tri rapide (Quick Sort)
Et d'autres algorithmes fondamentaux !
Cette plongée dans le tri à bulles marque le coup d'envoi de ma série sur les algorithmes. Comme un joueur qui progresse match après match, je compte bien continuer à explorer et partager mes apprentissages avec vous. Rendez-vous dans le prochain article pour tacler un nouvel algorithme ensemble !