Menu
Coddy logo textTech

Поразрядная сортировка

Последнее обновление

Поразрядная сортировка (radix sort) — это несравнивающая сортировка для целых чисел. Вместо сравнения значений она сортирует числа разряд за разрядом. Версия с наименее значащего разряда (LSD) обрабатывает сначала разряд единиц, затем десятков, затем сотен, используя на каждом разряде устойчивую сортировку подсчётом. Поскольку каждый проход устойчив, после обработки самого старшего разряда весь массив оказывается отсортированным. Нажмите «воспроизвести» выше, чтобы увидеть, как каждый проход по разряду переставляет столбики.

Поразрядная сортировка работает за время O(d·(n + k)), где d — число разрядов, а k — основание (здесь 10). Для целых чисел фиксированной ширины это фактически линейно — она может обойти сравнивающие сортировки с O(n log n) — но работает только с данными, которые можно разбить на разряды или ключи.

Временная и пространственная сложность

СлучайСложностьПримечания
ВремяO(d·(n + k))d разрядов, основание k (линейно при фиксированном d)
ПамятьO(n + k)Выходной массив + счётчики разрядов
УстойчиваяДаКаждый проход по разряду — устойчивая сортировка подсчётом
Сравнивающая?НетСортирует по разряду, а не сравнивая значения
Работает сЦелыми/ключамиНе с произвольными сравнимыми объектами

Шаг за шагом

ШагЧто происходит
1Найти максимальное значение, чтобы узнать, сколько разрядов обрабатывать.
2Начать с наименее значащего разряда (разряда единиц).
3Устойчиво отсортировать массив по этому разряду сортировкой подсчётом.
4Перейти к следующему более старшему разряду.
5Повторять, пока не обработаны все позиции разрядов.

Разобранный пример

Сортировка [170, 45, 75, 90, 2, 24, 66]:

ПроходМассивДействие
Начало[170, 45, 75, 90, 2, 24, 66]Максимум равен 170, поэтому нужны три прохода по разрядам.
Единицы[170, 90, 2, 24, 45, 75, 66]Устойчивая сортировка по разряду единиц: 0, 0, 2, 4, 5, 5, 6.
Десятки[2, 24, 45, 66, 170, 75, 90]Устойчивая сортировка по разряду десятков: 0, 2, 4, 6, 7, 7, 9 (170 сохраняет опережение над 75).
Сотни[2, 24, 45, 66, 75, 90, 170]Устойчивая сортировка по разряду сотен; только 170 имеет 1, поэтому оно уходит в конец. Отсортировано.

Когда использовать поразрядную сортировку

Использовать, когдаИзбегать, когда
Ключи — это целые числа или строки фиксированной длины, которые можно разбить на разряды.Нужно сортировать произвольные объекты с пользовательским компаратором.
У ключей малое, ограниченное число разрядов d, так что O(d·(n + k)) обходит O(n log n).Ключи очень длинные или неограниченные, из-за чего d велико, а проходы дороги.
Нужна устойчивая сортировка и вы можете позволить O(n + k) дополнительной памяти.Памяти мало, и буферы O(n + k) недопустимы.
Диапазон значений или основание k умеренны относительно n.k огромно, поэтому каждый проход сортировки подсчётом доминирует по времени работы.

Код Radix Sort

Чистая, готовая к запуску реализация Radix Sort на Python, JavaScript, Java, C++, C. Выберите язык, скопируйте код или откройте его уже загруженным в плейграунде Coddy.

Код Radix Sort на Python

Python
1def radix_sort(a):2    # Sort by each decimal digit, least significant first3    max_value = max(a)4    exp = 15    while max_value // exp > 0:6        a = sort_by_digit(a, exp)7        exp *= 108    return a9
10
11def sort_by_digit(a, exp):12    buckets = [[] for _ in range(10)]13    for value in a:14        digit = (value // exp) % 1015        buckets[digit].append(value)16    # Concatenating buckets 0..9 keeps the sort stable17    return [value for bucket in buckets for value in bucket]18
19
20nums = [170, 45, 75, 90, 802, 24, 2, 66]21print("Before:", nums)22print("After: ", radix_sort(nums))
Запустите этот код в плейграунде Python

Часто задаваемые вопросы о поразрядной сортировке

Какова временная сложность поразрядной сортировки?
Поразрядная сортировка — это O(d·(n + k)), где d — число разрядов, а k — основание. Для целых чисел фиксированной ширины это фактически O(n), что может быть быстрее сравнивающих сортировок. Она использует O(n + k) дополнительной памяти.
Устойчива ли поразрядная сортировка?
Да. LSD-поразрядная сортировка опирается на устойчивую сортировку подсчётом на каждом разряде; именно устойчивость заставляет разрядный подход давать корректно отсортированный результат.
Когда можно использовать поразрядную сортировку?
Поразрядная сортировка работает с данными, которые можно разложить на разряды или ключи фиксированного размера, такими как целые числа или строки фиксированной длины. Это не универсальная сравнивающая сортировка, поэтому она не может сортировать произвольные объекты с пользовательским компаратором.
Чем поразрядная сортировка отличается от сортировки подсчётом?
Сортировка подсчётом сортирует по одному ключу за один проход и требует массив счётчиков размером с диапазон значений, поэтому она деградирует, когда значения сильно разбросаны. Поразрядная сортировка применяет сортировку подсчётом разряд за разрядом, сохраняя массив счётчиков каждого прохода малым (основание k), что позволяет ей обрабатывать большие диапазоны значений, с которыми простая сортировка подсчётом не справилась бы.
Почему LSD-поразрядная сортировка начинает с наименее значащего разряда?
Начало с наименее значащего разряда позволяет каждому устойчивому проходу сохранять порядок, установленный всеми предыдущими, менее значащими разрядами. К моменту обработки самого старшего разряда равенства по этому разряду уже корректно упорядочены по младшим разрядам, поэтому массив в итоге полностью отсортирован. Сортировка сначала по старшему разряду нарушила бы это и потребовала бы другого, рекурсивного подхода (MSD-поразрядная сортировка).
Может ли поразрядная сортировка работать с отрицательными числами?
Не напрямую — базовое извлечение разрядов предполагает неотрицательные целые числа. Обычные решения — сдвинуть все значения, прибавив минимум, чтобы всё стало неотрицательным, либо отдельно отсортировать отрицательные и неотрицательные числа, а затем объединить. Игнорирование этого — частая ошибка при применении поразрядной сортировки к реальным данным.
Coddy programming languages illustration

Освойте алгоритмы с Coddy

НАЧАТЬ