7
правок
Изменения
Нет описания правки
Такой подход к алгоритму называют '''LSD-сортировкой''' (Least Significant Digit radix sort). Существует модификация алгоритма цифровой сортировки, анализирующая значения разрядов, начиная слева, с наиболее значащих разрядов. Данный алгоритм известен, как '''MSD-сортировка''' (Most Significant Digit radix sort).
=== Корректность алгоритма LSD-сортировки ===
Докажем, что данный алгоритм работает верно, используя метод математической индукции по номеру разряда. Пусть <tex> n </tex> {{---}} количество разрядов в сортируемых объектах.
=== LSD-сортировка ===
В качестве примера рассмотрим сортировку чисел. Как говорилось выше, в такой ситуации в качестве устойчивой сортировки применяют сортировку подсчетом, так как обычно количество различных значений разрядов не превосходит количества сортируемых элементов. Ниже приведен псевдокод цифровой сортировки, которой подается массив <tex> A </tex> <tex> m </tex>-разрядных чисел размера <tex> n </tex>. Сам по себе алгоритм представляет собой цикл по номеру разряда, на каждой итерации которого элементы массива <tex> A </tex> размещаются в нужном порядке во вспомогательном массиве <tex> B </tex>. Для подсчета количества объектов, <tex> i </tex>-й разряд которых одинаковый, а затем и для определения положения объектов в массиве <tex> B </tex> используется вспомогательный массив <tex> C </tex>. Функция <tex> digit(x, i) </tex> возвращает <tex> i </tex>-й разряд числа <tex> x </tex>. Также считаем, что значения разрядов меньше <tex> k </tex>.
'''function''' radixSort(int[] A)
'''for''' i = 1 '''to''' m
'''for''' j = 0 '''to''' k - 1
'''for''' j = 0 '''to''' n - 1
d = digit(A[j], i)
C[d] += 1+
count = 0
'''for''' j = 0 '''to''' k - 1
tmp = C[j]
C[j] = count
count += count + tmp
'''for''' j = 0 '''to''' n - 1
d = digit(A[j], i)
B[C[d]] = A[j]
C[d] += 1+
A = B
=== MSD-сортировка ===
Будем считать, что у всех элементов одинаковое число разрядов. Если это не так, то положим на более старших разрядах элементы с самым маленьким значением — для чисел это 0. Сначала исходный массив делится на <tex>k</tex> частей, где <tex>k</tex> — основание, выбранное для представления сортируемых объектов. Эти части принято называть "корзинами" или "карманами". В первую корзину попадают элементы, у которых старший разряд с номером <tex>d = 0</tex> имеет значение <tex>0</tex>. Во вторую корзину попадают элементы, у которых старший разряд с номером <tex>d = 0</tex> имеет значение <tex>1</tex> и так далее. Затем элементы, попавшие в разные корзины, подвергаются рекурсивному разделению по следующему разряду с номером <tex>d = 1</tex>. Рекурсивный процесс разделения продолжается, пока не будут перебраны все разряды сортируемых объектови пока размер корзины больше единицы. (то есть останавливаемся когда <tex>d > m</tex> или <tex>l \geq r</tex>, где m — максимальное число разрядов в сортируемых объектах, <tex>l</tex>, <tex>r</tex> — левая и правая границы отрезка массива <tex>A</tex>).
В основу распределения элементов по корзинам положен метод распределяющего подсчета элементов с одинаковыми значениями в сортируемом разряде. Для этого выполняется просмотр массива и подсчет количества элементов с различными значениями в сортируемом разряде. Эти счетчики фиксируются во вспомогательном массиве счетчиков <tex>cnt</tex>. Затем счетчики используются для вычисления размеров корзин и определения границ разделения массива. В соответствии с этими границами сортируемые объекты переносятся во вспомогательный массив <tex>c</tex>, в котором размещены корзины.
После того как корзины сформированы, содержимое вспомогательного массива <tex>c</tex> переносится обратно в исходный массив <tex>A</tex> и выполняется рекурсивное разделение новых частей по следующему разряду в пределах границ корзин, полученных на предыдущем шаге.
Изначально запускаем функцию так <tex>mradixSort(A, 1, A.length, 1)</tex> — максимальное количество разрядов в сортируемых объектах
'''for''' j = 0 '''to''' k + 1
cnt[j] = 0
'''for''' i = l '''to''' r
j = digit(A[i], d)
cnt[j + 1] = cnt[j + 1] + 1
'''for''' j = 2 '''to''' k
cnt[j] += cnt[j] + cnt[j - 1]
'''for''' i = l '''to''' r
j = digit(A[i], d)
c[l + cnt[j]] = A[i]
'''for''' i = l '''to''' r
A[i] = c[i]
Если количество разрядов {{---}} константа, а <tex> k = O(n) </tex>, то сложность цифровой сортировки составляет <tex> O(n) </tex>, то есть она линейно зависит от количества сортируемых чисел.
Сложность MSD-сортировки оценивается величиной <tex>O(n \log_k n)</tex>. При больших k величина <tex>\log_k n</tex> становится малой и сложность становится линейной функцией <tex>O(n)</tex> Существует так же модификация MSD-сортировки, при которой рекурсивный процесс останавливается при небольших размерах текущего кармана и вызывается более быстрая сортировка основанная на сравнениях (например, сортировка вставками). Таким образом, если k небольшое, то лучше использовать LSD-сортировку, при больших k {{---}} MSD-сортировку.== Литература Источники информации ==
* Дональд Кнут Искусство программирования, том 3. Сортировка и поиск
* Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн, К. Алгоритмы: построение и анализ
* [http://rain.ifmo.ru/cat/view.php/vis/sorts/linear-2005 Визуализатор 1] — Java-аплет.
* [http://rain.ifmo.ru/cat/view.php/vis/sorts/linear-2001 Визуализатор 2] — Java-аплет.
== Смотри также ==
* [[Сортировка подсчетом]]
* [[Сортировка вставками]]
* [[wikipedia:ru:Поразрядная сортировка|Википедия {{---}} Цифровая сортировка]]
[[Категория: Дискретная математика и алгоритмы]]
[[Категория: Сортировки]]