Визуализация
Данные: Случайные
Легенда цветов
Как работает сортировка подсчетом
Хитрость вместо сравнений. Все привычные сортировки сравнивают элементы друг с другом. Сортировка подсчетом идет другим путем: она заводит массив счетчиков - по одному на каждое возможное значение - и просто считает, сколько раз встретилось каждое значение.
Фаза 1 - подсчет. Проходим по входному массиву и для каждого элемента увеличиваем счетчик с номером, равным его значению. Встретили тройку - прибавили единицу к счетчику номер 3.
Фаза 2 - сборка. Идем по счетчикам слева направо: счетчик номер 0 говорит, сколько нулей записать в результат, счетчик номер 1 - сколько единиц, и так далее. Результат получается отсортированным сам собой.
В чем подвох? Значения должны быть целыми и из небольшого диапазона (у нас 0..9). Если сортировать числа до миллиарда, понадобится миллиард счетчиков - память закончится раньше, чем сортировка начнется. Зато когда диапазон мал, сортировка подсчетом обгоняет даже самые быстрые сортировки сравнением.
Синонимы названия: Сортировка подсчетом, Counting Sort.
Сложность алгоритма
Сложность - это оценка того, как быстро растет потребление ресурса при росте длины массива n. Ресурса у алгоритма два, поэтому и оценки две: по времени и по памяти. Обе записывают через O-нотацию - у нас есть отдельная анимация о том, как читать такие записи.
По времени
Показывает, как растет число операций (здесь это чтения и записи, сравнений нет вовсе) при росте n. Лейбл "Сложность" под визуализацией - время, которое получилось фактически на ваших данных.
| Характеристика | Оценка | Комментарий |
|---|---|---|
| Время (все случаи) | O(n + k) | n - длина массива, k - размер диапазона значений. Растет линейно: порядок данных не важен |
По памяти
Показывает, сколько дополнительной памяти нужно алгоритму. Сам входной массив в эту оценку не входит: дополнительной считается память сверх него.
| Характеристика | Оценка | Комментарий |
|---|---|---|
| Дополнительная память | O(k) | k счетчиков. Часто еще аллоцируют массив результата на n элементов, тогда O(n + k). Плата за скорость: пузырек обходится O(1) памяти, но тратит квадратичное время, а подсчет наоборот - покупает линейное время дополнительной памятью. |
Устойчивость алгоритма
Устойчивой называется сортировка, которая не меняет взаимный порядок равных элементов. Пример: сортируем учеников по оценке, а внутри одной оценки они уже стояли по алфавиту. Устойчивая сортировка сохранит алфавитный порядок внутри каждой оценки, неустойчивая - может перемешать.
| Характеристика | Оценка | Комментарий |
|---|---|---|
| Устойчивость | Да | В классической версии с префиксными суммами: равные элементы переносятся в исходном порядке, поэтому подсчет лежит в основе поразрядной сортировки (Radix sort). Наша упрощенная версия раскладывает голые числа по счетчикам - для чисел без "нагрузки" разницы нет. |
Примеры реализации сортировки подсчетом (Counting Sort)
Код на C
void countingSort(int arr[], int n, int max_val) {
// 1. Создаем массив счетчиков (k = max_val + 1)
int k = max_val + 1;
int* counts = (int*)calloc(k, sizeof(int));
// 2. Фаза подсчета
for (int i = 0; i < n; i++) {
counts[arr[i]]++;
}
// 3. Фаза сборки результата
int index = 0;
for (int i = 0; i < k; i++) {
while (counts[i] > 0) {
arr[index] = i;
index++;
counts[i]--;
}
}
free(counts);
}
Код на Python
def counting_sort(arr, max_val):
# 1. Создаем массив счетчиков
counts = [0] * (max_val + 1)
# 2. Фаза подсчета
for num in arr:
counts[num] += 1
# 3. Фаза сборки результата
index = 0
for i in range(len(counts)):
while counts[i] > 0:
arr[index] = i
index += 1
counts[i] -= 1
Код на JavaScript
function countingSort(arr, maxVal) {
// 1. Создаем массив счетчиков
const counts = new Array(maxVal + 1).fill(0);
// 2. Фаза подсчета
for (let i = 0; i < arr.length; i++) {
counts[arr[i]]++;
}
// 3. Фаза сборки результата
let index = 0;
for (let i = 0; i < counts.length; i++) {
while (counts[i] > 0) {
arr[index] = i;
index++;
counts[i]--;
}
}
return arr;
}
Хотите разобрать тему глубже? В нашем бесплатном курсе есть урок про сортировку подсчетом - с подробной теорией, задачами и проверочными вопросами.