title: Counting sort
text: # Counting sort
  
  Il Counting sort è un algoritmo di ordinamento per valori numerici interi con complessità lineare. L'algoritmo si basa sulla conoscenza a priori dell'intervallo in cui sono compresi i valori da ordinare.
  
  ## Descrizione intuitiva
  
  L'algoritmo conta il numero di occorrenze di ciascun valore presente nell'array da ordinare, memorizzando questa informazione in un array temporaneo di dimensione pari all'intervallo di valori. Il numero di ripetizioni dei valori inferiori indica la posizione del valore immediatamente successivo.
  
  Si calcolano i valori massimo, $max(A)$, e minimo, $min(A)$, dell'array e si prepara un array ausiliario $C$ di lunghezza $max(A)-min(A)+1$, che inizialmente contiene solo zeri. $C$ conterrà le frequenze di ciascun elemento in $A$ (ad esempio $C[0]=1$ se $min(A)$ appare una sola volta all'interno di $A$).
  
  Una volta costruito $C$, si visita l'array $A$ per popolarlo. Ogni volta che si incontra il valore $i$ in $A$, si andrà ad aumentare di uno il valore di $C[i]$. Al termine di questo processo, $C[i]$ sarà pari al numero di occorrenze dell'elemento $i+min(A)$ nell'array di partenza $A$.
  
  Infine, per ordinare $A$, si scorre $C$ dalla prima cella all'ultima, scrivendo in $A$ il valore $i+min(A)$ per $C[i]$ volte. Va notato che se un elemento $k$ non è presente in $A$, allora $C[k]$ sarà pari a 0, e dunque quell'elemento non sarà inserito.
  
  $A$ sarà ordinato alla fine di questo processo perché si è sfruttata la possibilità di accedere prima casualmente e poi sequenzialmente agli indici di $C$: scansionare un array significa accedere ai suoi indici in ordine, perciò l'ordinamento è garantito da questa proprietà.
  
  ## Esempio
  
  ### Prima scansione
  
  Con una scansione di $A$ individuo il valore minimo (2) e il valore massimo (8).
  
  ### Seconda scansione
  
  Popolo l'array $C$, che tiene il conto delle frequenze di ciascun elemento nell'intervallo $[2,8]$.
  
  Il significato dell'array C è il seguente: l'intero 0 $+min(A)$ = 2 è presente 3 volte nell'array A, l'intero 1+min(A)=3 è presente 1 volta, l'intero 2+min(A)=4 è presente 0 volte, e così via.
  
  ### Terza scansione
  
  Inserisco in A tre volte l'intero 2, 1 volta l'intero 3, 0 volte l'intero 4, 1 volta l'intero 5 e così via.
  
  L'array A è ora ordinato.
  
  ## Complessità
  
  L'algoritmo esegue tre iterazioni, due di lunghezza $n$ (pari alla lunghezza dell'array da ordinare) per l'individuazione di $max(A)$ e $min(A)$ e per il calcolo delle occorrenze dei valori, e una di lunghezza $k$ (pari a $max(A)-min(A)+1$) per l'impostazione delle posizioni finali dei valori: la complessità totale è quindi $O(n+k)$.
  
  Non è basato su confronti e scambi e conviene utilizzarlo quando il valore di $k$ è $O(n)$, nel qual caso l'algoritmo è $O(n)$, altrimenti risulterebbero più veloci altri algoritmi.
  
  