[ 簡単な説明 ]
2種類の順列生成ルーチンを紹介します。 ひとつは、高速順列生成ルーチンで、生成される順列は辞書式順序ではありません。; genperm1( ) もうひとつは、辞書式順序に順列を生成するルーチンです。; genperm2( ) 順列は、配列 int p[ ] に1〜nの数値で格納されます。 各順列の生成毎に showperm ルーチンを呼び出すので、実際の応用においては、ここ(showperm ルーチン)に各順列を使用した処理を書きます。 |
/* perm.c 順列生成 */ #include <stdio.h> #include <stdlib.h> extern void showperm(int p[], int n); /* このルーチンで各順列に対する処理を行う */ void genperm1(int p[], int n); /* 高速順列生成ルーチン,辞書式順序ではない */ void genperm2(int p[], int n); /* 辞書式順序の順列生成ルーチン */ void put(int p[], int pos, int k); void genperm1(int p[], int n) { int *c, *pc, *q; int k, t; c = (int *)malloc(sizeof(int) * n); if(c == NULL) { fprintf(stderr, "Error : out of memory in genperm1()\n"); exit(-1); } for(k = 1, q = p, pc = c; k <= n; ) *q++ = *pc++ = k++; k = 1; pc = c; do { t = *(p + k); *(p + k) = *(q = p + ((k & 1)? *pc: 0)); *q = t; showperm(p, n); k = 1; pc = c; while(*pc == 0) *pc++ = k++; (*pc)--; } while(k < n); free((char *)c); } int nn; int *ok; void genperm2(int p[], int n) { int k; ok = (int *)malloc(sizeof(int) * (n + 1)); if(ok == NULL) { fprintf(stderr, "Error : out of memory in genperm2()\n"); exit(-1); } nn = n; for(k = 1; k <= n; k++) *(ok + k) = 1; for(k = 1; k <= n; k++) put(p, 0, k); free((char *)ok); } void put(int p[], int pos, int k) { int j; *(p + pos) = k; if(pos == nn - 1) showperm(p, nn); else { *(ok + k) = 0; for(j = 1; j <= nn; j++) if(*(ok + j)) put(p, pos + 1, j); *(ok + k) = 1; } } |