В таком случае, приходится добавлять функцию проверки, что элемент является младшим в последовательности: Код (C): #include <stdio.h> #define RANK 4 #define ITEMS (1 << RANK) #define TOTAL (ITEMS << 1) bool validate(size_t i) { size_t k = i; do { k = (k & 1) ? (k >> 1) | ITEMS : (k >> 1); if (k < i) return false; } while (k != i); return true; } int main() { int buf[TOTAL]; int tmp; for (size_t i=0; i<TOTAL; ++i) buf[i] = i; for (size_t i=1; i<ITEMS; ++i) { // Check that previous element in chain is not less than current if (!validate(i)) continue; size_t k = i; while (1) { k = (k & ITEMS) ? ((k << 1) & (TOTAL - 1)) | 1 : (k << 1); if (k == i) break; tmp = buf[i]; buf[i] = buf[k]; buf[k] = tmp; } printf("Shuffle i=%d", int(i)); for (size_t i=0; i<TOTAL; ++i) printf(" %02X", buf[i]); printf("\n"); } printf("Result:"); for (size_t i=0; i<TOTAL; ++i) printf(" %02X", buf[i]); printf("\n"); }
В природе существует алгоритм с линейным временем работы и константной памятью, но он очень сложный. См.: "Stable minimum space partitioning in linear time" Katajainen, Pasanen http://citeseer.ist.psu.edu/viewdoc/download?doi=10.1.1.25.5554&rep=rep1&type=pdf
maxdiver, формулировка этой задачи более общая. У нас частный случай, который, как раз, может выродиться в линейное количество перестановок + затрата времени на проверку, была ли выполнена перестановка ранее.
ежель я ничего не путаю ==>> надо перевести начальную цепочку в цепочку доменов, где каждый элемент домена состоит из итого элемента правой и левой подпоследовательностей? левый элемент домена должен быть по возможности чётом, а правый нечётом?