Записи теоретических кусков
Сортировка подсчётом
Сортировка подсчётом
Как мы выяснили, сортировка пузырьком умеет сортировать массив за $O(n^2)$. Сейчас мы научимся сортировать массивы специально вида гораздо быстрее.
Итак, предположим, что у нас имеется массив целых чисел из некоторого диапазона $[MINVALUE,\,MAXVALUE]$. Пусть также диапазон не слишком велик. Например, пусть $MAXVALUE - MINVALUE \le 10^7$. В этом случае мы можем подсчитать, сколько раз каждое значение из диапазона встречается в массиве. Затем мы можем по этой информации выписать исходный массив в отсортированном порядке.
Приведём код, который сортирует массив. Отметим, что такие параметры алгоритма,
как MINVALUE
и MAXVALUE
, лучше выносить в секцию констант.
В программировании принято имена констант записывать большими буквами.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | const MINVALUE = 0; MAXVALUE = 1000 * 1000; MAXN = 1000 * 1000; var n, i, j, k: longint; a: array [1..MAXN] of longint; count: array [MINVALUE..MAXVALUE] of longint; begin read(n); for i := 1 to n do read(a[i]); // обнуляем массив count for j := MINVALUE to MAXVALUE do count[j] := 0; for i := 1 to n do count[a[i]] := count[a[i]] + 1; i := 1; // позиция ячейки в массиве чисел, // которая будет заполняться следующей for j := MINVALUE to MAXVALUE do for k := 1 to count[j] do begin a[i] := j; i := i + 1; end; for i := 1 to n do write(a[i], ' '); end. |
Оценим время работы этой программы. Обозначим размер диапазона за $m$, т. е. $m := MAXVALUE - MINVALUE + 1$. Цикл в строчках 18-19 выполняется за $O(m)$. Цикл в строчках 21-22 выполняется за $O(n)$. В строках 26-30 суммарно совершается $n + m$ операций. Итого время работы сортировки подсчётом составляет $O(n + m)$, где $n$ — размер массива, а $m$ — размер диапазона чисел. Серьёзное улучшение по сравнению с алгоритмом сортировки пузырьком!