反復インターフェイスを使用するコード。時間計算量は O(n^2)、空間計算量には次のオーバーヘッドがあります: n のコピー (log n ビット)、反復変数 (log n ビット)、ni の追跡 (log n ビット)、現在の値のコピー(log n ビット)、p のコピー (n log n ビット)、次の値の作成 (log n ビット)、および使用される値のビット セット (n ビット)。n log n ビットのオーバーヘッドを回避することはできません。時間的に、これはビットを設定するための O(n^2) でもあります。これは少し減らすことができますが、使用された値を格納するために装飾されたツリーを使用するという犠牲が伴います。
これは、代わりに適切なライブラリへの呼び出しを使用することで、任意精度の整数とビット セットを使用するように変更できます。また、上記の境界は、移植可能に N=8 に制限されるのではなく、実際に開始されます (int は、短く、16 ビットと小さい)。9!= 362880 > 65536 = 2^16
#include <math.h>
#include <stdio.h>
typedef signed char index_t;
typedef unsigned int permutation;
static index_t permutation_next(index_t n, permutation p, index_t value)
{
permutation used = 0;
for (index_t i = 0; i < n; ++i) {
index_t left = n - i;
index_t digit = p % left;
p /= left;
for (index_t j = 0; j <= digit; ++j) {
if (used & (1 << j)) {
digit++;
}
}
used |= (1 << digit);
if (value == -1) {
return digit;
}
if (value == digit) {
value = -1;
}
}
/* value not found */
return -1;
}
static void dump_permutation(index_t n, permutation p)
{
index_t value = -1;
fputs("[", stdout);
value = permutation_next(n, p, value);
while (value != -1) {
printf("%d", value);
value = permutation_next(n, p, value);
if (value != -1) {
fputs(", ", stdout);
}
}
puts("]");
}
static int factorial(int n)
{
int prod = 1;
for (int i = 1; i <= n; ++i) {
prod *= i;
}
return prod;
}
int main(int argc, char **argv)
{
const index_t n = 4;
const permutation max = factorial(n);
for (permutation p = 0; p < max; ++p) {
dump_permutation(n, p);
}
}