Tri à peigne

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 raccourci : 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 Wikipedia), 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 s'écrire 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.