Le processus de classement est une opération fondamentale en programmation, et l’efficacité de cette opération dépend grandement de l’algorithme utilisé. Un choix inadéquat peut entraîner des temps d’exécution excessivement longs.
Cet article explore divers algorithmes de tri, en détaillant leurs principes de fonctionnement.
Nous allons examiner pas à pas différents algorithmes de tri. Bien que l’implémentation soit présentée en Python, la logique sous-jacente peut être facilement adaptée à d’autres langages. L’adaptation se résume à une question de syntaxe spécifique au langage.
Nous aborderons les algorithmes en commençant par les moins performants pour finir avec les plus efficaces. Ne vous inquiétez pas, suivez attentivement l’article et essayez de les mettre en œuvre par vous-même.
Entrons maintenant dans le vif du sujet et explorons ces algorithmes de tri.
Tri par insertion
Le tri par insertion se distingue par sa simplicité et sa facilité de mise en œuvre. Cependant, son efficacité diminue pour les tableaux de grande taille, ce qui limite son utilisation dans ces cas.
Cet algorithme maintient deux parties distinctes au sein du tableau : une partie triée et une partie non triée.
Au début du processus, la partie triée ne contient que le premier élément du tableau. L’algorithme consiste à sélectionner un élément de la partie non triée et à l’insérer à sa place appropriée dans la partie triée.
Pour une meilleure compréhension, examinons les étapes de cet algorithme à l’aide d’un exemple visuel.
Voici les étapes détaillées pour implémenter le tri par insertion :
- Initialisez un tableau avec des valeurs numériques arbitraires.
- Parcourez le tableau à partir du deuxième élément.
- Stockez la position et la valeur de l’élément actuel dans des variables.
- Exécutez une boucle qui continue tant que la position est valide et que l’élément actuel est inférieur à l’élément précédent.
- Déplacez l’élément précédent à la position de l’élément actuel.
- Décrémentez la position actuelle.
- Une fois la boucle terminée (soit au début du tableau, soit en trouvant un élément plus petit), insérez l’élément actuel à la position correcte.
La complexité temporelle du tri par insertion est de O(n^2), tandis que sa complexité spatiale est de O(1).
Voilà, le tableau est maintenant trié. Le code suivant illustre l’implémentation en Python. Assurez-vous d’avoir Python installé ou utilisez un compilateur en ligne.
def insertion_sort(arr, n): for i in range(1, n): # Position et élément courants current_position = i current_element = arr[i] # Itération tant que # la position est valide et que l'élément actuel est plus petit que le précédent while current_position > 0 and current_element < arr[current_position - 1]: # Déplacement de l'élément précédent à la position actuelle arr[current_position] = arr[current_position - 1] # Déplacement à la position précédente current_position -= 1 # Insertion de l'élément à la position correcte arr[current_position] = current_element if __name__ == '__main__': # Initialisation du tableau arr = [3, 4, 7, 8, 1, 9, 5, 2, 6] insertion_sort(arr, 9) # Affichage du tableau trié print(str(arr))
Tri par sélection
Le tri par sélection présente des similitudes avec le tri par insertion. L’algorithme divise le tableau en deux parties, une triée et une non triée. À chaque itération, il recherche l’élément minimum dans la partie non triée et le place à la fin de la partie triée.
Examinons visuellement les étapes du tri par sélection pour une meilleure compréhension.
Voici les étapes pour implémenter le tri par sélection :
- Initialisez un tableau avec des valeurs numériques.
- Parcourez le tableau.
- Mémorisez l’indice de l’élément minimum.
- Parcourez le tableau, en partant de l’élément actuel jusqu’à la fin.
- Vérifiez si l’élément actuel est inférieur à l’élément minimum.
- Si c’est le cas, mettez à jour l’indice de l’élément minimum.
- Échangez l’élément actuel avec l’élément minimum trouvé.
La complexité temporelle du tri par sélection est O(n^2), et sa complexité spatiale est O(1).
Tentez d’implémenter l’algorithme. Il est similaire au tri par insertion. Vous pouvez consulter le code ci-dessous.
def selection_sort(arr, n): for i in range(n): # Mémorisation de l'indice de l'élément minimum min_element_index = i for j in range(i + 1, n): # Recherche de l'indice de l'élément minimum if arr[j] < arr[min_element_index]: min_element_index = j # Échange de l'élément actuel avec l'élément minimum arr[i], arr[min_element_index] = arr[min_element_index], arr[i] if __name__ == '__main__': # Initialisation du tableau arr = [3, 4, 7, 8, 1, 9, 5, 2, 6] selection_sort(arr, 9) # Affichage du tableau trié print(str(arr))
Tri à bulles
Le tri à bulles est un algorithme simple qui consiste à comparer et à permuter les éléments adjacents à plusieurs reprises jusqu’à ce que le tableau soit entièrement trié.
L’algorithme parcourt le tableau et déplace l’élément courant vers sa position suivante tant qu’il est supérieur à l’élément qui le suit.
Visualisons le tri à bulles pour faciliter la compréhension.
Voici les étapes pour implémenter le tri à bulles :
- Initialisez le tableau avec des données factices.
- Parcourez le tableau.
- Parcourez le tableau de 0 à n-i-1 (car les i derniers éléments sont déjà triés).
- Comparez l’élément actuel avec l’élément suivant.
- Si l’élément actuel est supérieur à l’élément suivant, échangez-les.
La complexité temporelle du tri à bulles est O(n^2), avec une complexité spatiale de O(1).
Vous pouvez maintenant implémenter facilement le tri à bulles. Voici le code :
def bubble_sort(arr, n): for i in range(n): # Parcours du tableau jusqu'à n-i-1 for j in range(n - i - 1): # Comparaison avec l'élément suivant if arr[j] > arr[j + 1]: # Échange des éléments adjacents arr[j], arr[j + 1] = arr[j + 1], arr[j] if __name__ == '__main__': # Initialisation du tableau arr = [3, 4, 7, 8, 1, 9, 5, 2, 6] bubble_sort(arr, 9) # Affichage du tableau trié print(str(arr))
Tri par fusion
Le tri par fusion est un algorithme récursif qui utilise une approche diviser pour mieux régner. Il est plus performant que les algorithmes précédents en termes de complexité temporelle.
L’algorithme consiste à diviser le tableau en deux moitiés, à les trier séparément, puis à les fusionner en un seul tableau trié.
Étant donné qu’il s’agit d’un algorithme récursif, le processus de division se poursuit jusqu’à ce que le tableau soit réduit à des sous-tableaux unitaires, qui sont trivialement triés.
Passons à une représentation visuelle de ce processus.
Voici les étapes pour mettre en œuvre le tri par fusion :
- Initialisez un tableau avec des données factices (des entiers).
- Définissez une fonction `merge` pour fusionner deux sous-tableaux en un tableau trié. Elle prend en arguments : le tableau, l’indice de début, l’indice du milieu et l’indice de fin.
- Calculez les longueurs des deux sous-tableaux en utilisant les indices fournis.
- Copiez les éléments du tableau dans les tableaux gauche et droit respectivement.
- Parcourez les deux sous-tableaux.
- Comparez les éléments des deux sous-tableaux.
- Incorporez l’élément le plus petit des deux sous-tableaux au tableau fusionné.
- Vérifiez s’il reste des éléments dans les deux sous-tableaux et ajoutez-les.
- Définissez une fonction `merge_sort` avec le tableau, les indices gauche et droit comme paramètres.
- Si l’indice de gauche est supérieur ou égal à l’indice de droite, arrêtez la récursion.
- Trouvez l’indice du milieu pour diviser le tableau en deux moitiés.
- Appelez récursivement `merge_sort` sur les deux moitiés du tableau.
- Après les appels récursifs, fusionnez les deux moitiés en utilisant la fonction `merge`.
La complexité temporelle du tri par fusion est O(n log n), et sa complexité spatiale est O(n).
C’est tout pour l’implémentation de l’algorithme de tri par fusion. Voici le code :
def merge(arr, left_index, mid_index, right_index): # Création des sous-tableaux gauche et droit left_array = arr[left_index:mid_index+1] right_array = arr[mid_index+1:right_index+1] # Calcul des longueurs des sous-tableaux left_array_length = mid_index - left_index + 1 right_array_length = right_index - mid_index # Indices pour fusionner les deux tableaux i = j = 0 # Indice pour le remplacement des éléments dans le tableau k = left_index # Parcours des deux sous-tableaux while i < left_array_length and j < right_array_length: # Comparaison des éléments if left_array[i] < right_array[j]: arr[k] = left_array[i] i += 1 else: arr[k] = right_array[j] j += 1 k += 1 # Ajout des éléments restants while i < left_array_length: arr[k] = left_array[i] i += 1 k += 1 while j < right_array_length: j += 1 k += 1 def merge_sort(arr, left_index, right_index): # Condition de base pour la récursion if left_index >= right_index: return # Calcul de l'indice du milieu mid_index = (left_index + right_index) // 2 # Appels récursifs merge_sort(arr, left_index, mid_index) merge_sort(arr, mid_index + 1, right_index) # Fusion des deux sous-tableaux merge(arr, left_index, mid_index, right_index) if __name__ == '__main__': # Initialisation du tableau arr = [3, 4, 7, 8, 1, 9, 5, 2, 6] merge_sort(arr, 0, 8) # Affichage du tableau trié print(str(arr))
Conclusion
Il existe une multitude d’autres algorithmes de tri, mais ceux présentés ici sont parmi les plus couramment utilisés. J’espère que vous avez apprécié cette exploration du tri.
Pour la suite, nous aborderons les algorithmes de recherche.
Bon codage 🙂 👨💻