|
[ 簡単な説明 ]
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;
}
}
|