Merge-Sort é um algoritmo para ordenação de dados simples e compacto, normalmente implementado utilizando recursão. A idéia do Merge-Sort é embasada na divisão de um vetor, dividi-lo em vários vetores menores até que não se possa dividir mais. Depois compara-se os elementos dos vetores menores para uni-los na ordem desejada.
O Merge-Sort é baseado em um padrão de projeto chamado divisão e conquista (divide-and-conquer), que pode ser dividido em 3 partes:
Divisão: Se a quantidade de elementos que serão ordenados for um ou dois então resolva o problema diretamente, se tiver mais elementos então divida a quantidade de elementos em dois ou mais conjuntos.
Recursão: Utilize a recursão para resolver cada um dos subconjuntos de elementos.
Conquista: Depois da resolução de cada subconjuntos, reagrupe-as em uma única solução.
Fluxo de execução do Merge Sort
Dado um vetor de elementos inteiros [3, 5, 4, 1, 9, 6, 7, 2], ordená-lo utilizando Merge Sort. Divide o vetor até ter um par de elementos, ordena esses elementos e altera a ordem deles no vetor original se necessário:
Ordena outro par de elementos e altera a ordem deles no vetor original se necessário:
Depois que tem 2 pares ordenados, ordena este 2 pares e altera a ordem deles no vetor original se necessário:
Continua ordenando a outra metade do vetor, faz o mesmo processo de dividir os elementos até chegar em um par de valores e ordena esses valores e altera a ordem deles no vetor original se necessário:
Ordena outro par de elementos e altera a ordem deles no vetor original se necessário.
Depois que tem 2 pares ordenados, ordena estes 2 pares e altera a ordem deles no vetor original se necessário:
Depois que as duas metades do vetor está ordenado, ordena novamente as duas metades e altera a ordem dos elementos no vetor original se necessário:
O vetor foi ordenado por completo:
Implementação do Merge Sort iterativo
Na linha 24 tem a assinatura do método mergeSort no formato iterativo, que recebe o tamanho do vetor e o vetor que será ordenado.
Na linha 27 é criado uma variável para percorrer os elementos do vetor, está variável é inicializada com 1 porque o vetor precisa ter pelo menos um elemento dentro dele.
Na linha 29 é criado três variáveis para controlar a posição inicial, meio e fim do vetor que será trabalhando.
Na linha 32 é criado um while para percorrer todos os elementos do vetor, neste while o vetor será percorrido de 1 em 1, depois de 2 em 2, depois de 4 em 4, etc, porque estamos simulando o tamanho do vetor original, para dividi-lo em partes pequenas que podem ser ordenadas e depois intercalada.
Na linha 38 é criado outro while para percorrer os elementos do vetor, utilizando a quantidade de elementos de 1 em 1, de 2 em 2, ou seja, vai ordenar dois elementos ou quatro elementos ou oito elementos.
Na linha 40 define qual a posição do meio do vetor.
Na linha 42 define qual a posição final do vetor.
Na linha 51 chama o método que intercala os valores do vetor, de acordo com as posições inicio, meio e fim passadas.
Na linha 54 faz a posição inicial do vetor ser igual a posição fim, porque será ordenado outra parte do vetor.
Na linha 58 duplica o tamanho dos elementos que deve ser ordenados e intercalados.
Na linha 70 declara a assinatura do método intercala que recebe o vetor e as posições inicio, meio e fim que serão ordenadas dentro do vetor.
Na linha 84 tem um while que serve para ordenar os elementos do inicio ao meio do vetor, ou do meio ao fim do vetor.
Na linha 101 tem um while que é para os elementos que estão no inicio do vetor, mas ainda não foram ordenados.
Na linha 109 tem um while que é para os elementos que estão no meio do vetor, mas ainda não foram ordenados.
Na linha 116 tem um for para passar os valores ordenados no vetor original.
Merge Sort usando recursão
Na linha 25 tem a assinatura do método recursivo de merge sort, que agora recebe a posição inicial e final do vetor que será ordenado.
Na linha 27 verifica se o inicio é menor que o fim – 1, para saber se o vetor não está vazio.
Na linha 29 calcula a posição que seria o meio do vetor que será ordenado, está posição é utilizada para dividir o vetor e depois intercalar seus valores.
Na linha 31 chama o método recursivamente, só que agora a posição final do vetor vai ser a posição do meio do vetor, que foi calculado anteriormente, assim faremos as chamadas recursivas caminhando para a esquerda do vetor.
Na linha 35 chama o método recursivamente, só que agora a posição inicial vai ser a posição do meio do vetor, que foi calculado anteriormente, assim faremos as chamadas recursivas caminhando para a direita do vetor.
Na linha 38 chama o método que vai intercalar (ordenar) os valores do vetor.
A imagem abaixo mostra a arvore de chamadas recursivas, caso este método receba um vetor de 5 elementos.
Em vermelho está a ordem em que os métodos serão chamados recursivamente.
Exemplo de Merge Sort com vetor de objetos
Neste exemplo temos uma classe Animal e cada animal tem uma especie e um nome.
A partir da classe animal, criamos um vetor de animais e queremos ordenar os animais pelo nome.
Segue abaixo a implementação do programa que ordena o vetor de animais pelo nome utilizando o algoritmo de Merge Sort:
O método do merge sort é muito parecido com o anterior, à única diferença é que na assinatura do método ele recebe um vetor de objetos Animal.
O método intercala é muito parecido com o anterior, na assinatura do método linha 53, alterou o tipo do vetor que ele recebe, para receber um vetor de objetos Animal.
Na linha 55 cria um vetor de objetos Animal, para guardar temporariamente os Animais ordenados pelo nome. Na linha 70 foi alterado, para ordenar os nomes dos Animais em ordem crescente.