Counting sort (ultra sort, math sort) je výkonný stabilní řadící algoritmus se složitostí , který vymyslel v roce 1954 Harold Seward. Counting sort nepracuje narozdíl od
bubble sortu nebo quicksortu na principu porovnávání jednotlivých hodnot, ale na bázi výčtu jejich výskytů.
Princip
Counting sort využívá znalosti maximální a minimální řazené hodnoty . Díky může vytvořit pole četností hodnot (kolikrát je daná hodnota zastoupena v řazeném poli) a toto pole posléze přepočítat na pole posledních indexů (index i značí pozici posledního výskytu daného prvku v seřazeném poli).
Řazení probíhá jedním průchodem řazeného pole (zprava doleva) a ukládáním hodnot na správné místo v seřazeném poli (které známe díky poli indexů).
Výhody a nevýhody counting sortu
Výhodou counting sortu je jeho složitost , kde
je velikost řazeného pole a
je velikost pole indexů (rozsah různých hodnot).
První nevýhodou tohoto řadicího algoritmu je, že v případě řazení struktur potřebuje ke své práci nejen pomocné pole indexů, ale také dodatečné pole, do kterého budeme řadit. Druhým a významnějším nedostatkem pak je, že se counting sortem dají řadit pouze diskrétní hodnoty (tj. nelze s ním řadit například reálná čísla).
Příklady
Vstupní pole: 9 6 6 3 2 0 4 2 9 3 Pole četností: 1 0 2 2 1 0 2 0 0 2 Pole výskytů: 0 0 2 4 5 5 7 7 7 9 Seřazené pole: 0 2 2 3 3 4 6 6 9 9
Vstupní pole: 2 8 9 8 0 8 8 9 4 6 Pole četností: 1 0 1 0 1 0 1 0 4 2 Pole výskytů: 0 0 1 1 2 2 3 3 7 9 Seřazené pole: 0 2 4 6 8 8 8 8 9 9
Vstupní pole: 9 2 1 9 4 1 5 7 5 3 Pole četností: 2 1 1 1 2 0 1 0 2 Pole výskytů: 1 2 3 4 6 6 7 7 9 Seřazené pole: 1 1 2 3 4 5 5 7 9 9
Kód
01.
/**
02.
* Counting sort
03.
* @param array
04.
* @return pole serazene od nejnizsi honoty po nejvyssi
05.
*/
06.
public
static
int
[] countingSort(
int
[] array) {
07.
// pole do ktereho budeme radit, v pripade primitiv nema smysl
08.
// da se radit i bez nej, ale v pripade objektu by to jinak neslo
09.
int
[] aux =
new
int
[array.length];
10.
11.
// najdeme maximum a minimum
12.
int
min = array[
0
];
13.
int
max = array[
0
];
14.
for
(
int
i =
1
; i < array.length; i++) {
15.
if
(array[i] < min) min = array[i];
16.
else
if
(array[i] > max) max = array[i];
17.
}
18.
19.
// vytvorime pole do ktereho budeme pocitat
20.
int
[] counts =
new
int
[max - min +
1
];
21.
22.
// zinicializujeme pocty vyskytu
23.
for
(
int
i =
0
; i < array.length; i++) {
24.
counts[array[i] - min]++;
25.
}
26.
27.
// prepocitame vyskyty na posledni index dane hodnoty
28.
counts[
0
]--;
29.
for
(
int
i =
1
; i < counts.length; i++) {
30.
counts[i] = counts[i] + counts[i-
1
];
31.
}
32.
33.
// Serad pole zprava doleva
34.
// 1) vyhledej posledni vyskyt dane hodnoty v poli vyskutu
35.
// 2) uloz hodnotu na prislusne misto v serazenem poli
36.
// 3) sniz index posledniho vyskytu dane hodnoty
37.
// 4) pokracuj s predchozi hodnotou vstupniho pole (goto: 1), terminuj, pokud jiz vsechny hodnoty byly zarazeny
38.
for
(
int
i = array.length -
1
; i >=
0
; i--) {
39.
aux[counts[array[i] - min]--] = array[i];
40.
}
41.
42.
return
aux;
43.
}
01.
/**
02.
* Counting sort
03.
* @param array
04.
* @return pole serazene od nejnizsi honoty po nejvyssi
05.
*/
06.
public
static
int
[] CountingSort(
int
[] array)
07.
{
08.
// pole do ktereho budeme radit, v pripade primitiv nema smysl
09.
// da se radit i bez nej, ale v pripade objektu by to jinak neslo
10.
int
[] aux =
new
int
[array.Length];
11.
12.
// najdeme maximum a minimum
13.
int
min = array[0];
14.
int
max = array[0];
15.
for
(
int
i = 1; i < array.Length; i++)
16.
{
17.
if
(array[i] < min) min = array[i];
18.
else
if
(array[i] > max) max = array[i];
19.
}
20.
21.
// vytvorime pole do ktereho budeme pocitat
22.
int
[] counts =
new
int
[max - min + 1];
23.
24.
// zinicializujeme pocty vyskytu
25.
for
(
int
i = 0; i < array.Length; i++)
26.
{
27.
counts[array[i] - min]++;
28.
}
29.
30.
// prepocitame vyskyty na posledni index dane hodnoty
31.
counts[0]--;
32.
for
(
int
i = 1; i < counts.Length; i++)
33.
{
34.
counts[i] = counts[i] + counts[i - 1];
35.
}
36.
37.
// Serad pole zprava doleva
38.
// 1) vyhledej posledni vyskyt dane hodnoty v poli vyskutu
39.
// 2) uloz hodnotu na prislusne misto v serazenem poli
40.
// 3) sniz index posledniho vyskytu dane hodnoty
41.
// 4) pokracuj s predchozi hodnotou vstupniho pole (goto: 1), terminuj, pokud jiz vsechny hodnoty byly zarazeny
42.
for
(
int
i = array.Length - 1; i >= 0; i--)
43.
{
44.
aux[counts[array[i] - min]--] = array[i];
45.
}
46.
47.
return
aux;
48.
}