Это длинный текст. Пожалуйста, несите меня. Вопрос: Есть ли работоспособный алгоритм сортировки по методу места на месте?
Предварительный
У меня есть огромное количество небольших строк фиксированной длины, в которых используются только буквы "A", "C", "G" и "T" (да, вы догадались: DNA), который я хочу сортировать.
В настоящий момент я использую std::sort
, который использует introsort во всех распространенных реализациях STL. Это работает очень хорошо. Тем не менее, я убежден, что radix sort идеально подходит для моей задачи и на практике лучше работает намного.
Подробнее
Я испробовал это предположение с очень наивной реализацией и относительно небольшими затратами (порядка 10 000), это было верно (ну, по крайней мере, более чем в два раза быстрее). Тем не менее, время выполнения ухудшается, когда размер проблемы увеличивается (N > 5 000 000).
Причина очевидна: для сортировки radix требуется копирование всех данных (более одного раза в моей наивной реализации, фактически). Это означает, что я поместил ~ 4 GiB в свою основную память, которая, очевидно, убивает производительность. Даже если это не так, я не могу позволить себе использовать эту большую память, так как размеры проблем фактически становятся еще большими.
Использовать случаи
В идеале, этот алгоритм должен работать с любой длиной строки от 2 до 100 для ДНК, а также ДНК5 (что позволяет использовать дополнительный символ подстановки "N" ) или даже ДНК с IUPAC коды неопределенности (в результате получается 16 различных значений). Однако я понимаю, что все эти случаи не могут быть покрыты, поэтому я доволен любым улучшением скорости, которое я получаю. Код может решить динамически, какой алгоритм должен отправляться.
Исследование
К сожалению, статья статьи Википедии о сортировке счисления бесполезно. Раздел о вариантах на месте - полный мусор. Раздел NIST-DADS для сортировки по методу radix находится рядом с несуществующим. Там есть многообещающая бумага под названием Эффективная адаптивная корреляция радиального размещения на месте, которая описывает алгоритм "MSL" . К сожалению, эта статья тоже разочаровывает.
В частности, существуют следующие вещи.
Во-первых, алгоритм содержит несколько ошибок и оставляет много необъяснимых. В частности, он не детализирует вызов рекурсии (я просто предполагаю, что он увеличивает или уменьшает некоторый указатель для вычисления текущих значений сдвига и маски). Кроме того, он использует функции dest_group
и dest_address
, не давая определений. Я не вижу, как эффективно реализовать это (т.е. В O (1), по крайней мере dest_address
не является тривиальным).
И последнее, но не менее важное: алгоритм реализует in-place-ness путем замены индексов массива на элементы внутри входного массива. Это, очевидно, работает только на числовых массивах. Мне нужно использовать его в строках. Конечно, я мог бы просто накрутить сильную печать и предположить, что память будет терпеть мое хранение индекса, где он не принадлежит. Но это работает только до тех пор, пока я могу сжать свои строки в 32 бит памяти (предполагая 32-битные целые числа). Это всего 16 символов (пусть игнорирует на данный момент 16 > log (5 000 000)).
Другая статья одного из авторов не дает никакого точного описания, но дает время выполнения MSL как сублинейное, что неверно.
Напомнить. Есть ли надежда найти рабочую ссылочную реализацию или, по крайней мере, хороший псевдокод/описание работающего на месте радиального сорта, который работает на цепочках ДНК?