Counting sort: diferenças entre revisões

Origem: Wikipédia, a enciclopédia livre.
Conteúdo apagado Conteúdo adicionado
Linha 300: Linha 300:


for (int i = A.length - 1; i >= 0; i--) {
for (int i = A.length - 1; i >= 0; i--) {
//resp[aux[A[i]] - 1] = A[i];
resp[aux[A[i].getKey()]-1]= A[i];
resp[aux[A[i].getKey()]-1]= A[i];
aux[A[i].getKey()]--;
aux[A[i].getKey()]--;

Revisão das 17h22min de 21 de abril de 2017

Counting sort
classe Algoritmo de ordenação
estrutura de dados Array, Listas ligadas
complexidade pior caso
complexidade caso médio
complexidade melhor caso
Algoritmos

Counting sort é um algoritmo de ordenação estável cuja complexidade é O(n). As chaves podem tomar valores entre 0 e M-1. Se existirem k0 chaves com valor 0, então ocupam as primeiras k0 posições do vetor final: de 0 a k0-1.

A ideia básica do counting sort é determinar, para cada entrada x, o número de elementos menor que x. Essa informação pode ser usada para colocar o elemento x diretamente em sua posição no array de saída. Por exemplo, se há 17 elementos menor que x, então x pertence a posição 18. Esse esquema deve ser ligeiramente modificado quando houver vários elementos com o mesmo valor, uma vez que nós não queremos colocar eles na mesma posição.[1]

Pseudocódigo

//k é o maior valor do vetor A

//Criar vetor auxiliar com k+1 elementos e inicializar com zeros
for i ← 0 to k
    do C[i]←0
    
for j ← 1 to lenght[A]
    do C[A[j]] ← C[A[j]] + 1
//Agora C[i] contem o numero de elementos igual a i.

for i ← 1 to k
    do C[i] ← C[i] + C[i - 1]
//Agora C[i] contem o numero de elementos menor que ou igual a i.

for j ← lenght[A] downto 1
    do B[C[A[j]]] ← A[j]
        C[A[j]] ← C[A[j]] - 1
        
//Pseudocodigo do livro "Introduction to Algorithms" 
//de Thomas H. Cormen...[et al.] - 2nd ed.
//The MIT Press (p. 168)

Implementações

  1. Cria cnt[M+1] e b[max N]
  2. Inicializa todas as posições de cnt a 0.
  3. Percorre o vector a e, para cada posição i de a faz cnt[a[i]-1]++ o que faz com que, no final, cada posição i de cnt contem o nº de vezes que a chave i-1 aparece em a.
  4. Acumula em cada elemento de cnt o elemento somado ao elemento anterior: cnt[i] indica a posição ordenada do primeiro elemento de chave i.
  5. Guarda em b os valores de a ordenados de acordo com b[cnt[a[i]++]=a[i]
  6. Copia b para a.
  7. Counting-Sort trabalha como uma contadora de ocorrências dentro de um programa, especificamente dentro de um vetor. Quando determinado vetor tem números repetidos, números únicos e números que não existem um outro vetor indica a quantidade de ocorrências.

Esta implementação tem a desvantagem de precisar de vectores auxiliares. O Counting Sort ordena exclusivamente números inteiros pelo fato de seus valores servirem como índices no vetor de contagem.

Características

  • Estável
  • Necessita de memória auxiliar. Logo, não é in-place
  • Complexidade linear

Código em C++

template<class T>
std::vector<T> counting_sort( const std::vector<T> &op )
{
   if ( op.empty() )
      return std::vector<T> {};

   auto min = *std::min_element( op.begin(), op.end() );
   auto max = *std::max_element( op.begin(), op.end() );

   std::vector<int> contagem( max - min + 1, 0 );
   for ( auto it = op.begin(); it != op.end(); ++it )
      ++contagem[ *it - min ];

   std::partial_sum( contagem.begin(), contagem.end(), contagem.begin() );

   std::vector<T> ordenado( op.size() );
   for ( auto it2 = op.rbegin(); it2 != op.rend(); ++it2 )
      ordenado[ --contagem[ *it2 - min ] ] = *it2;

   return ordenado;
}

Código em C

# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <ctype.h>
# define MAX 100001

struct data
{
    int number;
    char key[100];
} DataBase[MAX], VectorSort[MAX];

int CounterNum[MAX];
int size = 0;

int main (void)
{
    int i = 0;

    while (scanf("%d%s", &DataBase[size].number, DataBase[size].key) >= 1)
        size++;

    int aux[2] = {0, 0};
    for (i = 0; i <= size; i++)
        aux[DataBase[i].number]++;

    aux[1] += aux[0];

    for (i = size - 1; i >= 0; i--)
        VectorSort[--aux[DataBase[i].number]] = DataBase[i];

    for (i = 0; i < size; i++)
        printf("Number: %d  ---  Key: %s\n", VectorSort[i].number, VectorSort[i].key);

    return 0;
}

Código em Java 1.0

public void CountingSort(Integer[] v) {
		
	int maior = v[0];
	for (int i = 1; i < v.length; i++) {
		    if (v[i] > maior) {
				maior = v[i];
			}
		}
		
// frequencia
	int[] c = new int[maior];
	for (int i = 0; i < v.length; i++) {
			c[v[i] -1] += 1;
		}
		
// cumulativa
	for (int i = 1; i < c.length; i++) {
			c[i] += c[i-1];
		}
		
	Integer[] b = new Integer[v.length];
	for (int i = 0; i < b.length; i++) {
			b[c[v[i] -1] -1] = v[i];
			c[v[i] -1]--;
		}
		
	for (int i = 0; i < b.length; i++) {
			v[i] = b[i];
		}
	}

Código em Java 1.1

public void CountingSort(Integer[] array, int leftIndex, int rightIndex) {
		
		//Encontrar o maior valor 
		int k = 0;
		for(int m = leftIndex; m < rightIndex; m++){
			if(array[m] > k){
				k = array[m];
			}
		}
		
		//Cria vetor com o tamanho do maior elemento
		int[] vetorTemporario = new int[k];
		
		//Inicializar com zero o vetor temporario
		for(int i = 0; i < vetorTemporario.length; i++){
			vetorTemporario[i] = 0;
		}
		
		//Contagem das ocorrencias no vetor desordenado
		for(int j = leftIndex; j < rightIndex; j++){
			vetorTemporario[array[j]] += 1;
		}
		
		//Fazendo o  complemento do numero anterior 
		for(int i = leftIndex; i < rightIndex; i++){
			vetorTemporario[i] = vetorTemporario[i] + vetorTemporario[i - 1];
		}
		
		//Ordenando o array da direita para a esquerda
		int[] vetorAuxiliar = new int[array.length];
		for(int j = rightIndex; j > leftIndex; j--) {
			vetorAuxiliar[vetorTemporario[array[j]]] = array[j];
			vetorTemporario[array[j]] -= 1; 
		}
		
		//Retornando os valores ordenados para o vetor de entrada
		for (int i = leftIndex; i < rightIndex; i++){
			array[i] = vetorAuxiliar[i];
		}
	}

Código em Java 1.8 vetor de inteiros

public static void countingSort(int[] A, int maior) {
/*Por Robert Santos-Ciência da computação-UFMA*/
		int[] aux = new int[maior + 1];
		int[] resp = new int[A.length];
		// preenche aux com zeros (java já faz isso automaticamente)
		for (int i = 0; i < A.length; i++) {
			aux[A[i]]++;
		}

		for (int i = 1; i < aux.length; i++) {
			aux[i] += aux[i - 1];
		}
		

		for (int i = A.length - 1; i >= 0; i--) {
			resp[aux[A[i]] - 1] = A[i];
			aux[A[i]]--;
		}
		for (int i = 0; i < A.length; i++) {
			A[i] = resp[i];
		}
	}

Código em Java 1.8 vetor de objetos

public static void countingSort(Componente[] A, int maior) {
/*Componente possui campo key(inteiro) e campo msg(string)*/
/*Por Robert Santos-Ciência da computação-UFMA*/
		int[] aux = new int[maior + 1];
		// preenche aux com zeros (java já faz isso automaticamente)
		Componente[] resp = new Componente[A.length];
		
		for (int i = 0; i < A.length; i++) {
			aux[A[i].getKey()]++;
		}

		for (int i = 1; i < aux.length; i++) {
			aux[i] += aux[i - 1];
		}

		for (int i = A.length - 1; i >= 0; i--) {
			//resp[aux[A[i]] - 1] = A[i];
			resp[aux[A[i].getKey()]-1]= A[i];
			aux[A[i].getKey()]--;
		}
		for (int i = 0; i < A.length; i++) {
			A[i] = resp[i];
		}
	}

Código em Java 1.8 vetor de inteiros(CountingSort em ordem Decrescente)

public static void countingSort(int[] A, int maior) {
/*Por Robert Santos && Francisco Chaves-ciência da Computação-UFMA*/
		int[] aux = new int[maior + 1];
		int[] resp = new int[A.length];
		// preenche aux com zeros (java já faz isso automaticamente)
		for (int i = 0; i < A.length; i++) {
			aux[A[i]]++;
		}

		for (int i = aux.length -2; i >=0; i--) {
			aux[i] += aux[i + 1];
		}
		

		for (int i = A.length - 1; i >= 0; i--) {
			resp[aux[A[i]] - 1] = A[i];
			aux[A[i]]--;
		}
		for (int i = 0; i < A.length; i++) {
			A[i] = resp[i];
		}
	}

Código em Java 1.8 vetor de Objetos(CountingSort em ordem Decrescente)

public static void countingD(Componente[] A, int maior) {
/*Componente possui campo key(inteiro) e campo msg(string)*/
/*Por Robert Santos && Francisco Chaves-ciência da Computação-UFMA*/
		int[] aux = new int[maior + 1];
		Componente[] resp = new Componente[A.length];
		// preenche aux com zeros (java já faz isso automaticamente)
		for (int i = 0; i < A.length; i++) {
			aux[A[i].getKey()]++;
		}

		for (int i = aux.length -2; i >=0; i--) {
			aux[i] += aux[i + 1];
			
		}
		

		for (int i = A.length - 1; i >= 0; i--) {
			resp[aux[A[i].getKey()]-1]= A[i];
			aux[A[i].getKey()]--;
		}
		for (int i = 0; i < A.length; i++) {
			A[i] = resp[i];
		}
	}
  1. Cormen, Thomas (2001). Introduction to Algorithms. London, England: MIT Press & McGraw-Hill. 168 páginas