«Перестановка p из n элементов, определяемых перестановкой индекса p (i) = (i + k) mod n, называется k- вращением ».- Степанов и МакДжонс
std::rotate
стал хорошо известным алгоритмом благодаря Шону Родителю , но как эффективно реализовать его для произвольной последовательности битов?Под эффективностью я подразумеваю сведение к минимуму по крайней мере двух вещей: i) количество записей и ii) сложность пространства в наихудшем случае.
То есть входные данные должны быть аналогичны std::rotate
, но по битамЯ думаю, вот так:
- Указатель на память, где начинается битовая последовательность.
- Трехбитные индексы:
first
, middle
и last
.
Тип указателя может быть любым целым без знака, и, предположительно, чем больше, тем лучше.(Boost.Dynamic Bitset называет это «блоком».)
Важно отметить, что все индексы могут быть смещены от начала блока на разные величины.
По словам Степанова иМакДжонс, поворот на данных произвольного доступа может быть реализован в n + gcd (n, k) назначениях.Алгоритм, который переворачивает каждый поддиапазон с последующим обращением всего диапазона, занимает 3n назначений.(Тем не менее, я согласен с комментариями ниже, что это фактически 2n присваиваний.) Поскольку биты в массиве могут быть доступны случайным образом, я предполагаю, что применяется та же самая оптимальная граница.Каждое назначение обычно требует двух чтений из-за различных смещений поддиапазона, но я меньше беспокоюсь о чтениях, чем о записи.
Существует ли эффективная или оптимальная реализация этого алгоритма в дикой природе с открытым исходным кодом?Если нет, то как можно это сделать?
Я просмотрел Восхищение Хакера и Том 4А Кнута, но не могу найти алгоритм для этого.