Nous avons vu que le tri cocktail permet d'améliorer un peu les choses pour les tortues (ie, les petites valeurs près de la fin du tableau), mais on peut faire mieux. Le tri à peigne revient à leur faire prendre un racourci : Au lieu de comparer les valeurs adjacentes, on compare des valeurs séparés par un écart plus grand que 1. Ainsi, les tortues vont se déplacer de ecart cases à chaque parcours. Bien entendu, il faut appliquer l'algorithme avec des écarts de plus en plus petit et terminer avec ecart=1 pour s'assurer que le tableau est entièrement trié à la fin. Choisir comment réduire l'écart entre les parcours est une question difficile (voir wikipédia), mais en pratique, le diviser par 1.3 à chaque fois amène de bons résultats. Voici le pseudo-code correspondant :
ecart = lgr; faire si ecart>1 alors ecart = ecart / 1.3 i = O tant que i+ecart < lgr faire: si i et i+ecart doivent être inversés, le faire incrémenter i de 1 tant que l'écart est plus grand que 1 ou que le dernier parcours a inversé au moins un élément[!scala]
L'un des problèmes à résoudre est que la variable ecart
est
entière (de type Int
), et que nous voulons la diviser par 1.3,
qui est un nombre à virgule (de type Double
). Le système de
types de scala ne vous laissera pas faire une chose pareil sans
broncher. C'est que ce genre de disparité est souvent le signe de problèmes
que le programmeur n'a pas vu. Comme ce n'est pas une erreur dans notre cas,
nous allons devoir convertir ecart
en double pour le temps de
l'opération, puis convertir le résultat de retour en entier pour le stocker
dans ecart
. Cela s'écrit de la manière suivante:
ecart = (ecart.asInstanceOf[Double] / 1.3).asInstanceOf[Int]
C'est un peu bavard, mais finalement, cette écriture n'est pas très complexe. Et n'oubliez pas que le système de types est votre ami. Il est un peu tatillon et parfois un peu pénible (comme aujourd'hui), mais au fond, il trouve souvent des bugs bizarres qui auraient été très pénibles à débugger s'il ne les avait pas attrapé à la source. Et comme de plus les auteurs de Scala sont pragmatiques, cela peut aussi de manière simplifiée :
ecart = (ecart.toDouble / 1.3).toInt
toDouble
et toInt
sont simplement des raccourcis
pour les expressions équivalentes asInstanceOf[Double]
et
asInstanceOf[Int]
. Ce n'est pas très générique, mais c'est
extrêmement pratique.
Cet algorithme a été inventé par Wlodek Dobosiewicz en 1980 et redécouvert et popularisé par Stephen Lacey et Richard Box, qui l'ont décrit dans le magazine Byte d'avril 1991.