Classificação de inserção em Java
1. Visão geral
Neste tutorial, vamos discutirthe Insertion Sort algorithm and have a look at its Java implementation.
A Classificação de inserção é um algoritmo eficiente para solicitar um pequeno número de itens. Este método baseia-se na maneira como os jogadores de cartas classificam uma mão de cartas de baralho.
Começamos com a mão esquerda vazia e as cartas colocadas sobre a mesa. Em seguida, removemos um cartão de cada vez da mesa e o inserimos na posição correta na mão esquerda. Para encontrar a posição correta para uma nova carta, comparamos com o conjunto de cartas já classificado na mão, da direita para a esquerda.
Vamos começar entendendo as etapas do algoritmo na forma de pseudocódigo.
2. Pseudo-código
Apresentaremos nosso pseudocódigo para classificação por inserção como um procedimento chamadoINSERTION-SORT, tomando como parâmetro um arrayA[1 .. n] de n itens a serem classificados. The algorithm sorts the input array in-place (reorganizando os itens na matriz A).
Após a conclusão do procedimento, a matriz de entrada A contém uma permutação da sequência de entrada, mas na ordem classificada:
INSERTION-SORT(A)
for i=2 to A.length
key = A[i]
j = i - 1
while j > 0 and A[j] > key
A[j+1] = A[j]
j = j - 1
A[j + 1] = key
Vamos examinar rapidamente o algoritmo acima.
O índicei indica a posição do item atual na matriz a ser processada.
Começamos a partir do segundo item, pois, por definição, uma matriz com um item é considerada classificada. O item no índicei é chamado dekey. Depois de obter okey,, a segunda parte do algoritmo trata de encontrar seu índice correto. If the key is smaller than the value of the item at index j, then the key moves one position to the left. O processo continua até o caso em que alcançamos um elemento menor que a chave.
É importante notar que antes de iniciar a iteração para encontrar a posição correta dekey no índicei, a matrizA[1 .. j – 1] já ésorted.
3. Implementação imperativa
Para o caso imperativo, vamos escrever uma função chamadainsertionSortImperative, tomando como parâmetro uma matriz de inteiros. A função começa a iterar sobre a matriz a partir do segundo item.
Em qualquer momento durante a iteração,we could think of this array as being logically divided into two portions; o lado esquerdo sendo o classificado e o lado direito contendo os itens ainda não classificados.
Uma observação importante aqui é que, depois de encontrar a posição correta na qual inseriremos o novo item,we shift (and not swap) the items to the right para liberar espaço para ele.
public static void insertionSortImperative(int[] input) {
for (int i = 1; i < input.length; i++) {
int key = input[i];
int j = i - 1;
while (j >= 0 && input[j] > key) {
input[j + 1] = input[j];
j = j - 1;
}
input[j + 1] = key;
}
}
A seguir, vamos criar um teste para o método acima:
@Test
public void givenUnsortedArray_whenInsertionSortImperative_thenSortedAsc() {
int[] input = {6, 2, 3, 4, 5, 1};
InsertionSort.insertionSortImperative(input);
int[] expected = {1, 2, 3, 4, 5, 6};
assertArrayEquals("the two arrays are not equal", expected, input);
}
O teste acima prova que o algoritmo classifica corretamente em ordem crescente o array de entrada<6, 2, 3, 4, 5, 1>.
4. Implementação Recursiva
A função para o caso recursivo é chamadainsertionSortRecursive e aceita como entrada um array de inteiros (o mesmo que para o caso imperativo).
A diferença aqui do caso imperativo (apesar do fato de ser recursivo) é quecalls an overloaded function with a second argument that equals the number of items to sort.
Como queremos classificar a matriz completa, passaremos um número de itens igual ao seu comprimento:
public static void insertionSortRecursive(int[] input) {
insertionSortRecursive(input, input.length);
}
O caso recursivo é um pouco mais desafiador. The base case occurs when we attempt to sort an array with one item. Nesse caso, não fazemos nada.
Todas as chamadas recursivas subsequentes classificam uma parte predefinida da matriz de entrada - começando no segundo item até chegarmos ao final da matriz:
private static void insertionSortRecursive(int[] input, int i) {
if (i <= 1) {
return;
}
insertionSortRecursive(input, i - 1);
int key = input[i - 1];
int j = i - 2;
while (j >= 0 && input[j] > key) {
input[j + 1] = input[j];
j = j - 1;
}
input[j + 1] = key;
}
E é assim que a pilha de chamadas se parece com uma matriz de entrada de 6 itens:
insertionSortRecursive(input, 6)
insertionSortRecursive(input, 5) and insert the 6th item into the sorted array
insertionSortRecursive(input, 4) and insert the 5th item into the sorted array
insertionSortRecursive(input, 3) and insert the 4th item into the sorted array
insertionSortRecursive(input, 2) and insert the 3rd item into the sorted array
insertionSortRecursive(input, 1) and insert the 2nd item into the sorted array
Vejamos também o teste para isso:
@Test
public void givenUnsortedArray_whenInsertionSortRecursively_thenSortedAsc() {
int[] input = {6, 4, 5, 2, 3, 1};
InsertionSort.insertionSortRecursive(input);
int[] expected = {1, 2, 3, 4, 5, 6};
assertArrayEquals("the two arrays are not equal", expected, input);
}
O teste acima prova que o algoritmo classifica corretamente em ordem crescente o array de entrada<6, 2, 3, 4, 5, 1>.
5. Complexidade de tempo e espaço
The time taken by the INSERTION-SORT procedure to run is O(n^2). Para cada novo item, iteramos da direita para a esquerda sobre a parte já classificada da matriz para encontrar sua posição correta. Em seguida, o inserimos deslocando os itens uma posição para a direita.
O algoritmo classifica no lugar de modo que seuspace complexity is O(1) for the imperative implementation and O(n) for the recursive implementation.
6. Conclusão
Neste tutorial, vimos como implementar a classificação por inserção.
Esse algoritmo é útil para classificar um pequeno número de itens. It becomes inefficient when sorting input sequences having more than 100 items.
Lembre-se de que, apesar de sua complexidade quadrática, ele classifica no local sem a necessidade de espaço auxiliar, como é o caso demerge sort.
O código inteiro pode ser encontradoover on GitHub.