Shaker Sort
11-12-2021
Animation de l'algorithme de tri 'Shaker Sort'
Le tri “Shaker”, également appelé tri “Cocktail”, tri “Shuttle”, tri “boustrophédon” ou “tri à bulles bidirectionnel” est une variante du tri à bulles.
Avec le tri à bulle classique on a des “lièvres” et des “tortues”. Les “lièvres”, sont les éléments de fin de liste qui migrent rapidement à leur place définitive et les “tortues” ceux de début de liste qui se déplacent lentement.
L’idée du tri shaker est d’accélérer les tortues en changeant de direction à chaque itération. Donc, à chaque changement de direction, les “lièvres” deviennent “tortues” et inversement. Il permet non seulement aux plus grands éléments de migrer rapidement vers la fin de la série mais également aux plus petits éléments de migrer plus vite vers le début.
L’animation ci-dessous détaille le fonctionnement du tri shaker :
Vous trouverez ici une petite vidéo qui montre cet algorithme.
Travaux pratiques
Le mini-jeu ci-dessous vous permet d’essayer de trier, par ordre de poids croissant, une suite de 5 tonneaux, avec juste une balance pour les comparer. Vous pouvez essayer de le résoudre avec cette méthode de tri.
Variantes
La version de cet algorithme que l’on rencontre le plus souvent est composée de deux boucles imbriquées.
void swap(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void shakersort(int vect[], int size) {
int step, current;
for (step = 1; step <= size / 2; step++)
{
for (current = step - 1; current < size - step; current++)
if (vect[current] > vect[current+1])
swap(&vect[current], &vect[current + 1]);
for (current = size - step - 1; current >= step; current--)
if (vect[current] < vect[current-1])
swap(&vect[current], &vect[current - 1]);
}
}
Comme pour le tri bulle, on peut s’arrêter après un parcours sans permutation, quelque soit le sens.
Complexité
Le tri shaker n’apporte pas grand chose au tri bulle.
Dans le pire des cas, avec des données triées à l’envers, les parcours successifs du tableau imposent d’effectuer (n2 - n) comparaisons et (n2 - n) / 2 échanges. Par exemple, pour une liste de 10 éléments, il faudra, dans le pire des cas, faire 45 comparaisons et 45 échanges [ (102 - 10) / 2 ]. La complexité en temps est donc quadratique, de l’ordre de O(n2).
En moyenne, lorsque l’ordre initial des éléments à trier est aléatoire, on considère qu’il faudra faire (n2 - 2*n) / 4 échanges. C’est un peu mieux que le tri bulle classique mais la complexité reste de l’ordre de O(n2).
Dans le meilleur des cas, quand la liste est déjà triée, il faudra (n - 1) comparaisons et aucune permutation. La complexité en temps est linéaire, en O(n).
En espace utilisé (coût en mémoire de l’algorithme), la complexité du tri bulle est linéaire. Elle croit à la même vitesse que le nombre de données en entrée. Elle est donc de O(n).
L’animation ci-dessous permet de vérifier, de manière empirique, cette évolution du nombre d’opérations en fonction du nombre d’éléments à trier.
Taille données | Comparaisons | Echanges | Total |
---|
Pour vous faire une idée plus concrète des performances de cet algorithme, supposez que vous deviez trier par ordre alphabétique le répertoire des habitants de plusieurs grandes villes. Et que la machine dont vous disposez peut effectuer disons dix millions d’instructions par seconde. Voici le temps qui serait nécessaire avec cette méthode :
Ville | Nombre d'habitants | Durée du tri |
---|---|---|
Paimpol | 7 172 | |
Helsinki | 631 695 | |
Denver | 705 576 | |
Stockholm | 975 551 | |
Berlin | 3 520 031 | |
Nairobi | 4 734 881 | |
Barcelone | 5 407 264 | |
Rio | 6 718 000 | |
Moscou | 12 655 050 | |
Lagos | 22 829 561 | |
Shanghai | 24 870 895 | |
Séoul | 26 000 782 | |
Manille | 28 644 207 | |
Tokyo | 42 796 714 |
Vous pouvez changer le nombre d’instructions par seconde, pour tester.