Contrairement aux problèmes classiques de tri, l'opération coûteuse à économiser n'est pas la comparaison des valeurs, mais le retournement des crêpes. Dans cet exercice, nous allons explorer un autre algorithme permettant de réduire le nombre de retournements nécessaires pour trier la pile. Fait amusant, cet algorithme a été proposé pour la première fois par Bill Gates, avant qu'il n'invente Windows.
L'idée de base est de faire grandir des séquences de crêpes triées, pas
forcément en commençant du bas de la pile. On dira qu'un ensemble de crêpes
dans l'ordre constitue un block tandis qu'une crêpe qui n'est pas
dans un bloc est dite libre. L'algorithme considère la crêpe tout en
haut de la pile, dont la taille est notée t
, et cherche les
deux crêpes de taille t-1
et t+1
(le voisin ainsi
considéré est noté t+o
). Huit cas sont possibles alors :
t
et t+o
sont tous les deux
libres. Ils sont alors fusionnés en un retournement.t
est libre, et t+o
est le premier
élément d'un bloc. Ils sont fusionnés en un bloc.t
est libre, mais t-1
et
t+1
sont tous les deux les derniers éléments de blocs. Ces deux
blocs ainsi que t
sont tous fusionnés en 4
retournements. Prenez garde, si t-1
ou t+1
n'existe pas (parce que t
est 0 ou max), seulement deux de ces
retournements sont nécessaires.
t
est dans un bloc, mais t+o
est
libre. Ils sont fusionnés en un retournement.t
est dans un bloc, et t+o
est le
premier élément d'un bloc. Ils sont fusionnés en un retournement.t
est dans un bloc, et t+o
est le
dernier élément d'un autre bloc. Ils sont fusionnés en trois retournements
comme suit.t
est dans un bloc de taille k+1 (le dernier
élément est t+ko
), t+(k+1)o
est soit libre soit le
dernier élément d'un autre bloc. Les deux blocs sont fusionnés en deux
retournements:t
est dans un bloc de taille k+1 (le dernier
élément est t+ko
), t+(k+1)o
est le premier élément
d'un autre bloc (la différence avec le cas g est que t+(k+1)o
est maintenant le premier élément de son bloc). Les deux blocs sont
fusionnés en deux retournements:t
est dans un bloc de taille n
, qui
contient donc toutes les crêpes. Si t
n'est pas 1, toute la
pile est retournée. Ensuite, l'algorithme s'arrête.Chaque itération augmente la taille des blocs, donc la terminaison de
l'algorithme est certaine. Une analyse plus fine montre qu'il prend au plus
(5n+5)/3
étapes pour trier la pile. C'est mieux que
l'algorithme naïf, qui nécessite 2n-3
étapes pour cela.
Vous avez maintenant quasi assez d'informations pour implémenter cet
algorithme par vous-même. Il faut juste lever les dernières ambiguïtés pour
que vous implémentiez exactement le même algorithme que la correction. Si
plusieurs cas s'appliquent à la situation courante, appliquez le
premier. Par exemple, si les cas a et b s'appliquent (avec t-1
pour le cas a et t+1
pour le cas b), vous devez appliquer les
instructions du cas a. Si un cas donné s'applique à la fois pour
t+1
et t-1
, appliquez le pour t+1
.
Cet exercice est plus difficile que ceux que nous avons fait jusque là, et il ne serait pas choquant que vous ayez besoin d'un peu plus de temps que les autres pour le résoudre. Mais n'abandonnez pas, vous pouvez le faire !
estLibre()
ou
estPremier()
. Cela simplifiera l'écriture de votre algorithme,
qui peut être écrit sous une forme très similaire à l'énoncé si vous faites
les bonnes fonctions d'aide. Factoriser ainsi votre code aide très souvent à
améliorer la lisibilité du code.
isSelected()
qui ne renvoi vrai que si le
monde courant est celui sélectionné dans l'interface. Cela aidera à réduire
la complexité en résolvant les problèmes les uns après les autres.