Ao contrário de outros problemas de ordenação, a operação cara não é a comparação de valores, mas virar as panquecas. Neste exercício, vamos explorar outro algoritmo que tenta reduzir a quantidade de viradas da pilha. O engraçado é que este algoritmo mostrado primeiro por Bill Gates, antes de inventar o Windows.
A ideia básica é aumentar as sequências de panquecas ordenadas, não
necessariamente começando do fundo. Dizemos que uma sequência de panquecas
ordenadas constitui um bloco enquanto uma panqueca que não é parte de
um bloco é dita livre. O algoritmo então considera o panqueca mais de
cima (de raio t
) e busca pelas panquecas t+1
ou
t-1
(a vizinhança considerada é t+o
). Oito casos
podem acontecer:
t
quanto t+o
são livres. elas
são então juntadas em uma virada.t
é livre, e t+o
é o primeiro de um
bloco. Eles são juntados em uma virada.t
é livre mas tanto t-1
quanto
t+1
são últimos elementos de blocos. Os blocos e t
são mesclados juntos em 4 viradas. Cuidado, se t-1
ou
t+1
não existir (pois t
é 0 ou max), apenas duas
viradas são obrigatórias.
t
está num bloco mas t+o
é
livre. Eles são mesclados em uma virada.t
está num bloco e t+o
é o primeiro
elemento de um bloco. Eles são mesclados em uma virada.t
está em um bloco e t+o
é o último
elemento de outro bloco. Eles são mesclados em 3 viradas como segue.t
está em um bloco de comprimento k+1 (o último
elemento é t+ko
), t+(k+1)o
é tanto livre ou o
último elemento é outro bloco. Ambos os blocos são mesclados em 2 viradas:t
está num bloco de comprimento k+1 (o último
elemento é t+ko
), t+(k+1)o
é o primeiro elemento
de outro bloco (a diferença com o caso g é que t+(k+1)o
é agora
o primeiro elemento de seu bloco). Ambos os blocos são mesclados em 2
viradas:t
está num bloco de comprimento n
(este bloco contém todas as panquecas). Se t
não for 1, a pilha
toda destá virada. O algoritmo então pára.Cada iteração aumenta o tamanho dos blocos, então o algoritmo eventualmente
pára em todos os casos. Uma análise mais aprofundada mostrará que leva no
máximo (5n+5)/3
passos para ordenar a pilha. O que é melhor que
o algoritmo simplório, que precisa de 2n-3 passos.
Você agora tem quase toda a informação necessária para implementar este
algoritmo por si só. Temos apenas que remover as últimas ambiquidades para
garantir que você implemente exatamente o mesmo algoritmo que a correção. Se
vários casos se aplicam a sua situação, então você deve usar o primeiro que
foi dado. Por exemplo, se tanto o caso a quanto o caso b se se aplicam
(e.g., com t-1
no a e t+1
no caso
b), então você deve aplicar as viradas do caso a. Se um dado
caso se aplica tanto para t+1
quanto para t-1
,
então você deve aplicá-lo a t+1
.
Observe que este é de certa forma mais difícil que os outros exercícios que fizemos até agora, logo não se surpreenda se você precisar de mais tempo para terminar. Mas não desista, você pode conseguir!
isFirst()
ou isFree()
. Isto vai simplificar seu algoritmo principal, que
vai poder ser escrito de forma muito similar à explicação acima com um
conjunto de condições if. Fatorizar o código desta forma às vezes ajuda a
tornar seu código mais legível.
selecionado()
retorna verdadeiro. Isto acontecerá
apenas para a entidade que estiver selecionada na interface gráfica, que é
provavelmente o mundo que você está depurando no momento. Isto vai ajudar
dividindo a dificuldade em partes e depurando a situção uma após a outra.