Visualização do Bubble Sort
Os algoritmos de ordenação colocam os elementos de um array numa determinada ordem.
Vamos usar o bubble sort para ordenar números do mais baixo para o mais alto, basicamente alterando algo como isto:
[9, 1, 0, 4]
para isto:
[0, 1, 4, 9].
O algoritmo bubble sort é curto e simples, mas isso tem o custo de uma baixa eficiência - um tema ideal para um programador iniciante!
Os valores mais baixos 'flutuam' (bubble up) para o topo se o array for apresentado verticalmente - daí o nome. No nosso caso, o array é horizontal, por isso 'flutuam para a esquerda'.
Para tornar as coisas um pouco mais interessantes, vamos atribuir uma cor diferente a cada número e exibir o array após cada passagem.
Versão de array unidimensional:
Parece estranho porque existem algumas linhas vazias - vamos adicioná-las mais tarde quando mudarmos para a versão 2D.
| <html> |
| <body> |
| <canvas id="myCanvas" width="720" height="200"></canvas> |
| <script> |
| const canvas = document.getElementById("myCanvas"); |
| const context = canvas.getContext("2d"); |
| |
| const shuffleLength = 1000; |
| const rowLength = 360; |
| |
| |
| const array=[] |
| for (let n = 0; n < rowLength; n++) |
| array[n] = n; |
| |
| |
| |
| |
| |
| for (let n = 0; n < shuffleLength; n++) { |
| let cell1 = Math.floor(Math.random() * rowLength); |
| let cell2 = Math.floor(Math.random() * rowLength); |
| let temp = array[cell1]; |
| array[cell1] = array[cell2]; |
| array[cell2] = temp; |
| } |
| |
| |
| function animate() { |
| let swapped = false; |
| |
| |
| for (let i = 1; i <= rowLength - 1; i++) { |
| if (array[i - 1] > array[i]) { |
| let temp = array[i - 1]; |
| array[i - 1] = array[i]; |
| array[i] = temp; |
| swapped = true; |
| } |
| } |
| for (let n = 0; n < rowLength; n++) { |
| context.fillStyle = `hsl(${array[n]},100%,50%)`; |
| context.fillRect(n * 2, 0, 2, 50); |
| } |
| |
| if (swapped) |
| window.requestAnimationFrame(animate); |
| } |
| |
| animate(); |
| </script> |
| </body> |
| </html> |
As linhas [1-6] configuram o Canvas HTML5, que usaremos para exibir o array.
[8] quantas vezes baralhar os elementos antes da ordenação - selecionado arbitrariamente
[9] o número de elementos
[12] o array a ser ordenado - vazio por enquanto
[13-14] preencher o array com números: [0, 1, 2, 3...]
[20-26] Baralhar o array. Devido à forma como preenchemos o array em [13-14], este já se encontra ordenado. Para ver o bubble sort em ação, temos de destruir esta ordem. Para tal, selecionamos (pseudo)aleatoriamente dois elementos e trocamos os seus valores. Repetimos este processo shuffleLength vezes.
[29-48] Ordenação e visualização propriamente ditas:
[30] Assumimos que nenhum elemento terá de ser trocado, o que significa que todos os elementos já estão ordenados. Se o algoritmo nos provar o contrário, sabemos que é necessária outra iteração.
[33-40] O Algoritmo Bubble Sort
Agora sabe a terrível verdade! Este algoritmo consiste realmente em apenas 6 instruções! Todo aquele entusiasmo sobre este pequeno ciclo! Provavelmente arrepende-se de ter navegado até esta página, mas já que aqui está, mais vale acabar de ler:
[33] Para os elementos 1-360:
[34] Se este elemento tiver um valor superior ao anterior:
[35-38] trocar os elementos:
[35] copiar o primeiro elemento para a variável temp
[36] copiar o segundo elemento para o primeiro
[37] copiar o valor temporário para o segundo elemento
[38] Porque tivemos de trocar elementos, a nossa suposição de [30] deixa de ser verdadeira.
[41-44] Visualização:
[41] Para cada elemento:
[42] Definir a cor para o valor de
HSL (Matiz-Saturação-Luminosidade) é um método de representação de cores. Estamos a usá-lo porque, para uma sequência de números de 0 a 359, cria um arco-íris. Portanto, é apenas um método para obter uma imagem (um arco-íris) sem muito código.
[43] Desenhar um retângulo de 2x50 píxeis.
[46-47] Se trocámos elementos, a ordenação pode estar incompleta - vamos verificar executando outra passagem.
Eis o aspeto:
Clique na imagem para reiniciar.
Com apenas algumas linhas adicionais, podemos ordenar um array bidimensional, de modo a termos várias linhas independentes (o que viu no topo desta página):
| <html> |
| <body> |
| <canvas id="myCanvas" width="720" height="200"></canvas> |
| <script> |
| const canvas = document.getElementById("myCanvas"); |
| const context = canvas.getContext("2d"); |
| const mainArray = []; |
| const shuffleLength = 1000; |
| const rowLength = 360; |
| |
| for (let row = 0; row < 90; row++) { |
| const array=[] |
| for (let n = 0; n < rowLength; n++) |
| array[n] = n; |
| mainArray[row] = array; |
| } |
| |
| for (let row = 0; row < 90; row++) { |
| let array = mainArray[row]; |
| for (let n = 0; n < shuffleLength; n++) { |
| let cell1 = Math.floor(Math.random() * rowLength); |
| let cell2 = Math.floor(Math.random() * rowLength); |
| let temp = array[cell1]; |
| array[cell1] = array[cell2]; |
| array[cell2] = temp; |
| } |
| } |
| |
| function animate() { |
| let swapped = false; |
| for (let row = 0; row < 90; row++) { |
| let array = mainArray[row]; |
| for (let i = 1; i <= rowLength - 1; i++) { |
| if (array[i - 1] > array[i]) { |
| let temp = array[i - 1]; |
| array[i - 1] = array[i]; |
| array[i] = temp; |
| swapped = true; |
| } |
| } |
| for (let n = 0; n < rowLength; n++) { |
| context.fillStyle = `hsl(${array[n]},100%,50%)`; |
| context.fillRect(n * 2, row * 2, 2, 2); |
| } |
| } |
| if (swapped) |
| window.requestAnimationFrame(animate); |
| } |
| |
| animate(); |
| </script> |
| </body> |
| </html> |
Adicionámos um mainArray bidimensional [7]. O que era o array na versão anterior é agora um elemento no mainArray: [15, 19, 32].
Agora temos de repetir todas as ações para cada linha: [11, 18, 31].
Desenhamos agora quadrados de 2x2 píxeis em [42].
Desfrute das bolhas!