Menu
Coddy logo textTech

Counting Sort

Última atualização

Counting sort é uma ordenação sem comparações para inteiros em um intervalo conhecido e limitado. Ele conta quantas vezes cada valor aparece e depois usa essas contagens para escrever cada valor diretamente em sua posição ordenada, sem comparações. Pressione reproduzir acima para ver os valores sendo contados e depois posicionados em ordem.

Counting sort roda em tempo O(n + k), onde k é o intervalo dos valores de entrada. Quando k não é muito maior que n, ele é extremamente rápido e pode superar ordenações por comparação de O(n log n), mas se o intervalo de valores for enorme, o vetor de contagem de O(k) o torna impraticável.

Complexidade de tempo e espaço

CasoComplexidadeNotas
TempoO(n + k)n elementos, k = intervalo de valores
EspaçoO(n + k)Vetor de contagem + vetor de saída
EstávelSimAo posicionar da direita para a esquerda usando somas de prefixo
Comparação?NãoOrdena por contagem, não por comparação
Melhor paraIntervalo inteiro pequenok próximo de n

Passo a passo

PassoO que acontece
1Encontrar o valor máximo para dimensionar o vetor de contagem.
2Contar quantas vezes cada valor ocorre.
3(Opcional) Converter as contagens em somas de prefixo para obter estabilidade.
4Escrever cada valor na saída o número de vezes que ele aparece.
5O vetor de saída já está completamente ordenado.

Exemplo resolvido

Ordenando [1, 4, 1, 2, 4] (os valores vão de 0 a 4, então o vetor de contagem tem 5 posições):

PassagemEstadoAção
Percorrer entradacount = [0, 2, 1, 0, 2]Contar ocorrências: o 1 aparece duas vezes, o 2 uma vez, o 4 duas vezes.
Somas de prefixocount = [0, 2, 3, 3, 5]Cada posição agora guarda quantos valores são <= ao seu índice, dando as posições finais.
Posicionar 4output = [_, _, _, _, 4]Ler da direita para a esquerda: count[4] = 5, então o 4 vai para o índice 4; decrementar para 4.
Posicionar 2output = [_, _, 2, _, 4]count[2] = 3, então o 2 vai para o índice 2; decrementar para 2.
Posicionar 1output = [_, 1, 2, _, 4]count[1] = 2, então o 1 vai para o índice 1; decrementar para 1.
Posicionar 4output = [_, 1, 2, 4, 4]count[4] = 4, então este 4 vai para o índice 3; decrementar para 3.
Posicionar 1output = [1, 1, 2, 4, 4]count[1] = 1, então este 1 vai para o índice 0. O vetor está ordenado.

Quando usar o counting sort

Use quandoEvite quando
Você ordena inteiros (ou chaves mapeáveis para inteiros) em um intervalo pequeno e conhecido.O intervalo de valores k é muito maior que a quantidade de elementos n.
Você precisa de tempo linear O(n + k) e pode arcar com os vetores extras.A memória é escassa: o vetor de contagem custa O(k) independentemente de n.
Você precisa de uma ordenação estável como sub-rotina (por exemplo, dentro do radix sort).As chaves são floats, strings ou objetos arbitrários sem mapeamento para inteiros.
O valor máximo é limitado e barato de calcular antecipadamente.O intervalo é desconhecido ou ilimitado, então você não consegue dimensionar o vetor de contagem.

Código de Counting Sort

Uma implementação limpa e executável de Counting Sort em Python, JavaScript, Java, C++, C. Escolha uma linguagem, copie o código ou abra-o já carregado no Playground da Coddy.

Código de Counting Sort em Python

Python
1def counting_sort(a):2    # Works for non-negative integers with a small max value3    counts = [0] * (max(a) + 1)4    for value in a:5        counts[value] += 16    # Prefix sums turn counts into final positions7    for i in range(1, len(counts)):8        counts[i] += counts[i - 1]9    out = [0] * len(a)10    for value in reversed(a):  # reversed keeps equal values stable11        counts[value] -= 112        out[counts[value]] = value13    return out14
15
16nums = [4, 2, 2, 8, 3, 3, 1]17print("Before:", nums)18print("After: ", counting_sort(nums))
Execute este código no Playground de Python

Perguntas frequentes sobre Counting Sort

Qual é a complexidade de tempo do counting sort?
Counting sort é O(n + k), onde n é o número de elementos e k é o intervalo de valores possíveis. Quando k = O(n) isso é tempo linear. Ele usa O(n + k) de espaço adicional.
O counting sort é estável?
Pode ser. A versão estável constrói somas de prefixo das contagens e posiciona os elementos da direita para a esquerda, o que preserva a ordem relativa das chaves iguais. A versão simples de "reescrever por valor" mostrada aqui produz uma ordenação correta, mas é usada principalmente para inteiros simples.
Quando devo usar o counting sort?
Use ao ordenar inteiros (ou chaves mapeáveis para inteiros) dentro de um intervalo pequeno e conhecido. Se o intervalo de valores k for muito maior que o número de elementos, o vetor de contagem desperdiça memória e uma ordenação por comparação é melhor.
Qual é a diferença entre counting sort e radix sort?
Counting sort ordena pelo valor inteiro em uma única passagem e precisa de um vetor de contagem tão grande quanto o intervalo de valores. Radix sort ordena dígito por dígito e normalmente chama um counting sort estável em cada dígito, o que mantém pequeno o intervalo por passagem (por exemplo, 10 para dígitos decimais). Radix sort lida com intervalos de valores grandes que tornariam um único counting sort impraticável.
Por que o counting sort nem sempre é mais rápido que o quicksort?
Counting sort é O(n + k), então ele só vence quando o intervalo de valores k é comparável a n. Se k for enorme -por exemplo, ordenar 100 valores no intervalo de 0 a 1,000,000,000- o vetor de contagem de O(k) domina e desperdiça memória, enquanto uma ordenação por comparação de O(n log n) como o quicksort permanece rápida e eficiente em espaço.
O counting sort consegue lidar com números negativos?
Sim, com um pequeno deslocamento. Em vez de indexar o vetor de contagem diretamente pelo valor, indexe-o por value - min, de modo que o menor valor seja mapeado para o índice 0. O tamanho do vetor de contagem passa a ser max - min + 1. Esquecer esse deslocamento é um erro comum que falha com entradas negativas.
Coddy programming languages illustration

Domine algoritmos com a Coddy

COMEÇAR