Это то, что я называю алгоритмом «перестановки из».В C-подобном языке это будет выглядеть следующим образом:
for (i_dst_first = 0; i_dst_first < n; ++i_dst_first)
{
/* Check if this element needs to be permuted */
i_src = indices[i_dst_first];
assert(i_src < n);
if (i_src == i_dst_first)
/* This element is already in place */
continue;
i_dst = i_dst_first;
pending = a[i_dst];
/* Follow the permutation cycle */
do
{
a[i_dst] = a[i_src];
indices[i_dst] = i_dst;
i_dst = i_src;
i_src = indices[i_src];
assert(i_src != i_dst);
} while (i_src != i_dst_first);
a[i_dst] = pending;
indices[i_dst] = i_dst;
}
Обратите внимание, что этот алгоритм уничтожает массив index
.Я называю это «перестановка из», так как значение index[i]
указывает из , где взять i-й элемент результирующей последовательности.
Обратите также внимание, что номер элемента перемещается«Операции, необходимые для перестановки на месте последовательности, равны number of misplaced elements
+ number of cycles in the permutation
.Этот алгоритм достигает этого предела, поэтому с точки зрения количества ходов лучший алгоритм невозможен.
Потенциальная проблема этого алгоритма состоит в том, что он основан на подходе "жонглирования", что делает поведение его кэша далеко от оптимального.Таким образом, хотя этот алгоритм является лучшим в теории, он может проиграть некоторым более «практичным» алгоритмам в реальной жизни.
Можно также реализовать алгоритм «перестановки», где значение index[i]
указывает, гдепереместить исходный i-й элемент.