我设置了S1 = {s11,s12,s13),S2 = {s21,s22,s23)等等,直到SN.I需要生成包含S1,S2..SN等元素的所有排列。每个集合中只有1个元素。
例如:
S1 = {a,b,c}
S2 = {d,e,f}
S3 = {g,h,i}
我的意见将是:
{a,d,g}, {a,d,h}, {a,d,i}, {a,e,g}, {a,e,h}....
我该怎么做呢? (我可以随机地从每个中获取1并将它们合并,但这在我的知识中甚至是个坏主意。)
为了一般性,假设每组中都有'n'个元素。我正在考虑用C语言实现它。请注意'N'和'n'不是固定的。
答案 0 :(得分:0)
如果您确切地知道有多少套,并且它是一个小数字,通常可以使用嵌套循环。如果集合的数量大于2或3,或者它是可变的,则递归算法开始有意义。
如果这是作业,那么实现递归算法很可能是整个作业的对象。想一想,对于每一组,你可以递归地调用枚举函数并让它开始枚举下一组......
答案 1 :(得分:0)
如果它们在容器中,只需遍历每个容器:
#include <stdio.h>
int main(void)
{
int set1[] = {1, 2, 3};
int set2[] = {4, 5, 6};
int set3[] = {7, 8, 9};
for (unsigned i = 0; i < 3; ++i)
{
for (unsigned j = 0; j < 3; ++j)
{
for (unsigned k = 0; k < 3; ++k)
{
printf("(%d, %d, %d)", set1[i], set2[j], set3[k]);
}
}
}
return 0;
}
答案 2 :(得分:0)
通用解决方案:
typedef struct sett
{
int* nums;
int size;
} t_set;
inline void swap(t_set *set, int a, int b)
{
int tmp = set->nums[a];
set->nums[a] = set->nums[b];
set->nums[b] = tmp;
}
void permute_set(t_set *set, int from, void func(t_set *))
{
int i;
if (from == set->size - 1) {
func(set);
return;
}
for (i = from; i < set->size; i++) {
swap(set, from, i);
permute_set(set, from + 1, func);
swap(set, i, from);
}
}
t_set* create_set(int size)
{
t_set *set = (t_set*) calloc(1, sizeof(t_set));
int i;
set->size = size;
set->nums = (int*) calloc(set->size, sizeof(int));
for(i = 0; i < set->size; i++)
set->nums[i] = i + 1;
return set;
}
void print_set(t_set *set) {
int i;
if (set) {
for (i = 0; i < set->size; i++)
printf("%d ", set->nums[i]);
printf("\n");
}
}
int main(int argc, char **argv)
{
t_set *set = create_set(4);
permute_set(set, 0, print_set);
}
答案 3 :(得分:0)
这只是一个递归的问题。我们假设这些定义。
const int MAXE = 1000, MAXN = 1000;
int N; // number of sets.
int num[MAXN]; // number of elements of each set.
int set[MAXN][MAXE]; // elements of each set. i-th set has elements from
// set[i][0] until set[i][num[i]-1].
int result[MAXN]; // temporary array to hold each permutation.
功能是
void permute(int i)
{
if (i == N)
{
for (int j = 0; j < N; j++)
printf("%d%c", result[j], j==N-1 ? '\n' : ' ');
}
else
{
for (int j = 0; j < num[i]; j++)
{
result[i] = set[i][j];
permute(i+1);
}
}
}
要生成排列,只需拨打permute(0);
答案 4 :(得分:0)
这是一个相当简单的迭代实现,您应该能够根据需要进行调整:
#define SETSIZE 3
#define NSETS 4
void permute(void)
{
char setofsets[NSETS][SETSIZE] = {
{ 'a', 'b', 'c'},
{ 'd', 'e', 'f'},
{ 'g', 'h', 'i'},
{ 'j', 'k', 'l'}};
char result[NSETS + 1];
int i[NSETS]; /* loop indexes, one for each set */
int j;
/* intialise loop indexes */
for (j = 0; j < NSETS; j++)
i[j] = 0;
do {
/* Construct permutation as string */
for (j = 0; j < NSETS; j++)
result[j] = setofsets[j][i[j]];
result[NSETS] = '\0';
printf("%s\n", result);
/* Increment indexes, starting from last set */
j = NSETS;
do {
j--;
i[j] = (i[j] + 1) % SETSIZE;
} while (i[j] == 0 && j > 0);
} while (j > 0 || i[j] != 0);
}
答案 5 :(得分:0)
您可以将集合的元素视为循环计数器的值。 3组表示循环3(如GMan answare),N组表示N(模拟)循环:
#include <stdlib.h>
#include <stdio.h>
int set[3][2] = { {1,2}, {3,4}, {5,6} };
void print_set( int *ndx, int num_rows ){
for( int i=0; i<num_rows; i++ ) printf("%i ", set[i][ndx[i]] );
puts("");
}
int main(){
int num_cols = sizeof(set[0])/sizeof(set[0][0]);
int num_rows = sizeof(set)/sizeof(set[0]);
int *ndx = malloc( num_rows * sizeof(*ndx) );
int i=0; ndx[i] = -1;
do{
ndx[i]++; while( ++i<num_rows ) ndx[i]=0;
print_set( ndx, num_rows );
while( --i>=0 && ndx[i]>=num_cols-1 );
}while( i>=0 );
}
答案 6 :(得分:0)
我能提出的最有效的方法(在C#中):
string[] sets = new string[] { "abc", "def", "gh" };
int count = 1;
foreach (string set in sets)
{
count *= set.Length;
}
for (int i = 0; i < count; ++i)
{
var prev = count;
foreach (string set in sets)
{
prev = prev / set.Length;
Console.Write(set[(i / prev) % set.Length]);
Console.Write(" ");
}
Console.WriteLine();
}