Ordenação por Inserção
A ideia por trás do algoritmo de ordenação por inserção é simples. Para um vetor $A$ de $n$ números, execute os seguintes passos:
-
A cada iteração $i$ do algoritmo, troque de posição o elemento $A[i]$ com cada elemento maior que ele que esteja à sua esquerda.
Seguindo a regra acima, a cada iteração $i$ do algoritmo, todos os elementos à esquerda do índice $i$ estarão ordenados e elementos à direita do elemento no índice $i$ ainda não foram processados (podem ser menores, iguais, ou maiores que o elemento em $A[i]$).
Com as ideias acima em mente, podemos implementar o algoritmo de ordenação por inserção da seguinte forma:
def ordenacao_insercao(A):
n = len(A)
# Percorre o arranjo A.
for j in range(1, n):
chave = A[j]
i = j - 1
# Insere o elemento A[j] na posição correta.
while i >= 0 and A[i] > chave:
A[i + 1] = A[i]
i = i - 1
A[i + 1] = chave
A = random.sample(range(-10, 10), 10)
print("Arranjo não ordenado: ", A)
ordenacao_insercao(A)
print("Arranjo ordenado:", A)
Arranjo não ordenado: [7, -1, 4, -7, 2, 3, -9, 5, 1, 8] Arranjo ordenado: [-9, -7, -1, 1, 2, 3, 4, 5, 7, 8]
No pior caso, o algoritmo de ordenação por inserção possui complexidade quadrática ($O(n^2)$) no número de elementos do vetor de entrada, é um algoritmo in-place e é estável.
Se você quiser acompanhar visualmente a execução do algoritmo de ordenação por inserção, veja o excelente vídeo abaixo, feito pelo pessoal do site Algo-Rythmics:
O algoritmo de ordenação por inserção possui algumas nuances não mostradas acima:
-
O pior caso do algoritmo de ordenação por inserção (complexidade quadrática), ocorre quando o vetor de entrada está ordenado em ordem decrescente.
-
Se o vetor de entrada já estiver ordenado, o algoritmo de ordenação por inserção fará $n$ comparações e zero trocas de elementos.
-
O algoritmo de ordenação por inserção funciona muito bem para arranjos pequenos.
-
É possível reduzir o número de trocas feitas pelo algoritmo de ordenação por inserção. Para isso, podemos usar um algoritmo de busca binária para encontrar a posição em que um elemento deve ficar (isso é feito usando sucessivas trocas no algoritmo original), e após isso inserimos o elemento na posição correta com somente uma troca. Essa otimização reduz o número de trocas feitas pelo algoritmo, o que melhora seu desempenho, mas o número de comparações permanece quadrático.
Playground
# Use este espaço para praticar o que você aprendeu nesta seção.
# Basta digitar o código no espaço abaixo e clicar 'run'.