Быстрая сортировка с несколькими ключами , также известная как трехходовая радикальная быстрая сортировка , [1] — это алгоритм сортировки строк . Этот гибрид быстрой сортировки и радиальной сортировки был первоначально предложен П. Шеклтоном, как сообщалось в одной из основополагающих статей К. А. Р. Хоара по быстрой сортировке ; [ 2] : 14 его современное воплощение было разработано Джоном Бентли и Робертом Седжвиком в середине 1990-х годов. [3] Алгоритм разработан для использования того свойства, что во многих задачах строки, как правило, имеют общие префиксы .
Одним из применений алгоритма является построение массивов суффиксов , для чего он был одним из самых быстрых алгоритмов по состоянию на 2004 год. [4]
Трехходовой алгоритм быстрой сортировки по основанию сортирует массив из N ( указателей на) строк в лексикографическом порядке . Предполагается, что все строки имеют одинаковую длину K ; если строки имеют разную длину, они должны быть дополнены дополнительными элементами, которые меньше любого элемента в строках. [a] Псевдокод для алгоритма тогда будет [b]
алгоритм sort(a : массив строк, d : целое число) — если длина(a) ≤ 1 или d ≥ K, то возвращается p := pivot(a, d) i, j := partition(a, d, p) (Обратите внимание на одновременное назначение двух переменных.) сортировка(a[0:i), d) сортировка(a[i:j), d + 1) сортировать(a[j:длина(a)), d)
В отличие от большинства алгоритмов сортировки строк, которые просматривают множество байтов в строке, чтобы решить, является ли строка меньше, такой же или равной некоторой другой строке; а затем переключают свое внимание на некоторую другую пару строк, быстрая сортировка с несколькими ключами изначально просматривает только один байт каждой строки в массиве, byte d
, изначально первый байт каждой строки. Рекурсивный вызов использует новое значение d
и передает подмассив, где каждая строка в подмассиве имеет точно такую же начальную часть — символы перед character d
.
Функция pivot должна возвращать один символ. Бентли и Седжвик предлагают либо выбрать медиану a [0][d], ..., a[length(a)−1][d], либо какой-либо случайный символ в этом диапазоне. [3] Функция разбиения является вариантом той, которая используется в обычной трехсторонней быстрой сортировке : она перестраивает a так, что все a[0], ..., a[i−1] имеют элемент в позиции d, который меньше p , a[i], ..., a[j−1] имеют p в позиции d , а строки от j и далее имеют d -й элемент больше p . (Исходная функция разбиения, предложенная Бентли и Седжвиком, может быть медленной в случае повторяющихся элементов; для облегчения этого можно использовать разбиение с голландским национальным флагом . [5] )
Практическая реализация быстрой сортировки с несколькими ключами может выиграть от тех же оптимизаций, которые обычно применяются к быстрой сортировке: выбор медианы из трех, переключение на сортировку вставкой для небольших массивов и т. д. [6]