Американский флаг сортировка - American flag sort - Wikipedia

An Американский флаг сортировка эффективный, на месте вариант радиальная сортировка который распределяет предметы в ведра. Алгоритмы несравнительной сортировки, такие как сортировка по основанию и сортировка по американскому флагу, обычно используются для сортировки больших объектов, таких как строки, для которых сравнение не является единичной операцией.[1]Сортировка по американскому флагу выполняет итерацию по битам объектов, одновременно рассматривая несколько бит каждого объекта. Для каждого набора битов сортировка по американскому флагу выполняет два прохода через массив объектов: первый для подсчета количества объектов, которые попадут в каждую ячейку, а второй для помещения каждого объекта в его корзину. Это особенно хорошо работает при сортировке байтов за раз с использованием 256 сегментов. С некоторыми оптимизациями он в два раза быстрее, чем быстрая сортировка для больших наборов струны.[1]

Название американский флаг сортировка приходит аналогия с Проблема национального флага Нидерландов на последнем этапе: эффективно раздел массив на множество «полосок».

Алгоритм

Алгоритмы сортировки обычно сортируют список объектов в соответствии с некоторой схемой упорядочения. В отличие от алгоритмы сортировки на основе сравнения, Такие как быстрая сортировка, Сортировка по американскому флагу может сортировать только целые числа (или объекты, которые можно интерпретировать как целые числа). Алгоритмы сортировки на месте, включая сортировку по американскому флагу, выполняются без выделения значительного объема памяти сверх того, который используется исходным массивом. Это существенное преимущество как в экономии памяти, так и во времени при копировании массива.

Сортировка по американскому флагу работает путем последовательного деления списка объектов на сегменты на основе первой цифры их представления по основанию N (используемая база называется основание). Когда N равно 3, каждый объект можно переместить в нужное ведро с помощью Алгоритм национального флага Нидерландов. Когда N тем не менее, объекты не могут быть немедленно заменены на место, поскольку неизвестно, где должно начинаться и заканчиваться каждое ведро. Сортировка по американскому флагу позволяет обойти эту проблему, сделав два прохода через массив. Первый проход подсчитывает количество объектов, которые принадлежат каждому из N ведра. Затем вычисляется начало каждого сегмента как сумма размеров предыдущих сегментов. Второй проход помещает каждый объект в правильное ведро.

Сортировка по американскому флагу наиболее эффективна с основанием системы счисления, равным степени 2, потому что вместо дорогостоящих операций можно использовать битовые операции. возведения в степень для вычисления значения каждой цифры. При сортировке строк с использованием 8- или 7-битных кодировок, таких как ASCII, обычно используется система счисления 256 или 128, что соответствует посимвольной сортировке.[1]

Соображения производительности

Стоит отметить, что для текста с чистым английским алфавитом гистограмма счетчиков всегда разреженная. В зависимости от оборудования, возможно, стоит очистить счетчики в соответствии с завершением корзины (как в исходной статье). Или может быть стоит поддерживать максимальное и минимальное активное ведро или более сложную структуру данных, подходящую для разреженных массивов. Также важно использовать более простой метод сортировки для очень маленьких наборов данных, за исключением патологических случаев, когда ключи могут иметь очень длинные префиксы.

Наиболее важно то, что этот алгоритм следует случайной перестановке и, следовательно, особенно недружелюбен к кешированию для больших наборов данных.[2] Это подходящий алгоритм в сочетании с kалгоритм слияния.[нужна цитата ] (Первоначальная статья была написана до того, как кэшированная память стала широко использоваться.)

Псевдокод

american_flag_sort (Array, Radix) для каждой цифры D: # первый проход: вычисление счетчиков Counts <- нулей (Radix) для объекта X в массиве: Counts [цифра D объекта X в базовом Radix] + = 1 # вычисление смещений сегментов Offsets < - [sum (Counts [0..i]) for i in 1..Radix] # заменять объекты на место для объекта X в Array: заменять X на сегмент, начиная с Offsets [цифра D из X в базовом Radix] для каждого Ведро: american_flag_sort (Bucket, Radix)

Пример реализации на Python

Этот пример, написанный на языке программирования Python, будет выполнять сортировку по американскому флагу для любого основания 2 или выше. Простота изложения предпочтительнее умного программирования, поэтому вместо техники сдвига битов используется функция журнала.

def get_radix_val(Икс, цифра, основание) -> int:    возвращаться int(этаж(Икс / основание ** цифра)) % основаниеdef compute_offsets(список, Начните: int, конец: int, цифра, основание):    считает = [0 за _ в классифицировать(основание)]    за я в классифицировать(Начните, конец):        вал = get_radix_val(список[я], цифра, основание)        считает[вал] += 1    смещения = [0 за _ в классифицировать(основание)]    сумма = 0    за я в классифицировать(основание):        смещения[я] = сумма        сумма += считает[я]    возвращаться смещенияdef замена(список, смещения, Начните: int, конец: int, цифра, основание) -> Никто:    я = Начните    next_free = копировать(смещения)    cur_block = 0    пока cur_block < основание - 1:        если я >= Начните + смещения[cur_block + 1]:            cur_block += 1            Продолжить        radix_val = get_radix_val(список[я], цифра, основание)        если radix_val == cur_block:            я += 1            Продолжить        swap_to = Начните + next_free[radix_val]        список[я], список[swap_to] = список[swap_to], список[я]        next_free[radix_val] += 1def american_flag_sort_helper(список, Начните: int, конец: int, цифра, основание) -> Никто:    смещения = compute_offsets(список, Начните, конец, цифра, основание)    замена(список, смещения, Начните, конец, цифра, основание)    если цифра == 0:        возвращаться    за я в классифицировать(len(смещения) - 1):        american_flag_sort_helper(список, смещения[я], смещения[я + 1], цифра - 1, основание)def american_flag_sort(список, основание) -> Никто:    за Икс в список:        утверждать тип(Икс) == int    max_val = Максимум(список)    max_digit = int(этаж(бревно(max_val, основание)))    american_flag_sort_helper(список, 0, len(список), max_digit, основание)

Смотрите также

Рекомендации

  1. ^ а б c Макилрой, Питер М .; Бостик, Кейт; Макилрой, М. Дуглас (1993). "Инженерная радиксная сортировка" (PDF). Вычислительные системы. 6 (1): 5–27.
  2. ^ "алгоритм - Сортировка по основанию на месте". Переполнение стека. Получено 2020-10-18.

Общий