Сортировка подсчётом — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
м (Обобщение на произвольный целочисленный диапазон)
(Реализация)
Строка 24: Строка 24:
 
==== Реализация ====
 
==== Реализация ====
  
В этом варианте помимо входного массива <tex>A</tex> потребуется два вспомогательных массива — <tex>C[0..k - 1]</tex> для счётчика и <tex>B[0..n - 1]</tex> для отсортированного массива. Сначала следует заполнить массив <tex>C</tex> нулями, и для каждого <tex>A[i]</tex> увеличить <tex>C[A[i]]</tex> на 1. Далее подсчитывается число элементов меньше или равных текущему. Для этого каждый <tex>C[number]</tex>, начиная с <tex>C[1]</tex>, увеличивают на <tex>C[number - 1]</tex>. На последнем шаге алгоритма читается входной массив с конца и в каждый <tex>B[C[A[i]]]</tex> записывается <tex>A[i]</tex>, а значение <tex>C[A[i]]</tex> уменьшается на 1. Алгоритм устойчив. Устойчивость может потребоваться при [[Сортировка_подсчетом_сложных_объектов|сортировке сложных структур данных]].  
+
В этом варианте помимо входного массива <tex>A</tex> потребуется два вспомогательных массива — <tex>C[0..k - 1]</tex> для счётчика и <tex>B[0..n - 1]</tex> для отсортированного массива. Сначала следует заполнить массив <tex>C</tex> нулями, и, проходя по массиву <tex>A</tex>, записываем сколько у нас есть чисел равных <tex>A[i]</tex> в массив <tex>C</tex> (строки 1 - 4). Далее подсчитывается число элементов меньше или равных текущему (строки 5 - 6). На последнем шаге алгоритма читается входной массив с конца, а в массив <tex>B</tex> записываются элементы на те позиции, где они должны стоять; эта информация хранится в  массиве <tex>C</tex> (строки 7 - 9). Алгоритм устойчив. Устойчивость может потребоваться при [[Сортировка_подсчетом_сложных_объектов|сортировке сложных структур данных]].  
 
<code>
 
<code>
 
  StableCountingSort
 
  StableCountingSort
    for number = 0 to k - 1
+
  for number = 0 to k - 1
        C[number] = 0;
+
      C[number] = 0;
    for i = 0 to length[A] - 1
+
  for i = 0 to length[A] - 1
        C[A[i]] = C[A[i]] + 1;
+
        C[A[i]] = C[A[i]] + 1;
    for number = 1 to k - 1
+
  for number = 1 to k - 1
        C[j] = C[j] + C[j - 1];
+
      C[j] = C[j] + C[j - 1];
    for i = length[A] - 1 to 0
+
  for i = length[A] - 1 to 0
        B[C[A[i]]] = A[i];
+
      B[C[A[i]]] = A[i];
        C[A[i]] = C[A[i]] - 1;
+
      C[A[i]] = C[A[i]] - 1;
 
</code>
 
</code>
  

Версия 10:15, 12 июня 2012

Сортировка подсчётом — алгоритм сортировки целых чисел в диапазоне от [math]0[/math] до некоторой константы [math]k[/math], работающий за линейное время.

Простой алгоритм

Это простейший вариант алгоритма. Создать вспомогательный массив [math]C[0..k - 1][/math], состоящий из нулей, затем последовательно прочитать элементы входного массива [math]A[/math] и для каждого [math]A[i][/math] увеличить [math]C[A[i]][/math] на единицу. Теперь достаточно пройти по массиву [math]C[/math] и для каждого [math]number \in \{0, ..., k - 1\}[/math] в массив [math]A[/math] последовательно записать число [math]number\[/math] [math] C[number][/math] раз.

SimpleCountingSort
    for number = 0 to k - 1
        C[number] = 0;
    for i = 0 to length[A] - 1
        C[A[i]] = C[A[i]] + 1;
    pos = 0;
    for number = 0 to k - 1
        for i = 0 to C[j] - 1
            A[pos] = number;
            pos = pos + 1;

Устойчивый алгоритм

Идея

Основная идея состоит в том, чтобы для каждого элемента входного массива подсчитать количество элементов, меньших данного. Эта информация будет указывать на позиции элементов в отсортированном массиве. Например, если для элемента [math]x[/math] количество таких элементов будет [math]42[/math], то [math]x[/math] будет занимать [math]43[/math]-ю позицию в отсортированном массиве. Если элементы могут иметь одинаковые значения, то необходимо модифицировать алгоритм, так как нельзя разместить все такие элементы в одну позицию.

Реализация

В этом варианте помимо входного массива [math]A[/math] потребуется два вспомогательных массива — [math]C[0..k - 1][/math] для счётчика и [math]B[0..n - 1][/math] для отсортированного массива. Сначала следует заполнить массив [math]C[/math] нулями, и, проходя по массиву [math]A[/math], записываем сколько у нас есть чисел равных [math]A[i][/math] в массив [math]C[/math] (строки 1 - 4). Далее подсчитывается число элементов меньше или равных текущему (строки 5 - 6). На последнем шаге алгоритма читается входной массив с конца, а в массив [math]B[/math] записываются элементы на те позиции, где они должны стоять; эта информация хранится в массиве [math]C[/math] (строки 7 - 9). Алгоритм устойчив. Устойчивость может потребоваться при сортировке сложных структур данных.

StableCountingSort
  for number = 0 to k - 1
      C[number] = 0;
  for i = 0 to length[A] - 1
       C[A[i]] = C[A[i]] + 1;
  for number = 1 to k - 1
      C[j] = C[j] + C[j - 1];
  for i = length[A] - 1 to 0
      B[C[A[i]]] = A[i];
      C[A[i]] = C[A[i]] - 1;

Обобщение на произвольный целочисленный диапазон

Если диапазон значений (минимимум и максимум) заранее не известен, можно найти их с помощью линейного поиска, что не повлияет на асимптотику алгоритма. При работе с массивом [math]C[/math] из [math]A[i][/math] необходимо вычитать минимум, а при обратной записи прибавлять.

Анализ

В первом алгоритме первые два цикла работают за [math]\Theta(k)[/math] и [math]\Theta(n)[/math], соответственно; двойной цикл за [math]\Theta(n + k)[/math]. Во втором алгоритме циклы занимают [math]\Theta(k)[/math], [math]\Theta(n)[/math], [math]\Theta(k)[/math] и [math]\Theta(n)[/math], соответственно. Итого оба алгоритма имеют линейную временную трудоёмкость [math]\Theta(n + k)[/math]. Используемая память в первом алгоритме равна [math]\Theta(k)[/math], а во втором [math]\Theta(n + k)[/math].

Использование сортировки подсчётом целесообразно, когда диапазон возможных значений входных данных достаточно мал по сравнению с количеством элементов в сортируемом множестве, например, если [math]n = 1000000[/math] и все элементы натуральные числа меньшие [math]1000[/math], то время работы алгоритма равно [math]\Theta(n)[/math]. Эффективность алгоритма падает, когда необходимо сортировать различные элементы, попавшие в одну ячейку.

Источники

  • Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн. «Алгоритмы. Построение и анализ» — «Вильямс», 2011 г. — 1296 стр. — ISBN 978-5-8459-0857-5, 5-8459-0857-4, 0-07-013151-1
  • Сортировка подсчетом — Википедия