如何生成锯齿状阵列的笛卡尔积?

时间:2010-10-23 15:09:53

标签: c cartesian-product

我在弄清楚如何生成锯齿状阵列的笛卡尔积时遇到了一些麻烦。我google了,但我似乎无法找到迭代语言的实现。所以我想弄清楚自己,但我遇到了麻烦。让我们更清楚地定义问题

假设我有一个看起来像这样的数组数组

A = { {1}, {2, 3}, {4, 5, 6} }

我如何从那里走到

B = { {1, 2, 4}, {1, 2, 5}, {1, 2, 6}, {1, 3, 4}, {1, 3, 5}, {1, 3, 6} }

编辑:现在这只是一个例子,第一个数组可以包含动态数量的数组,每个数组都是动态大小。

如果x是外部数组中的元素数,并且y []是长度为x的动态数组,则元素包含内部数组中的元素数。那么A的x就变成了B的y,而B的x就是A中y的乘法和。(未经证实,从例子中假设)

由于A的x是动态的,因此该函数必须是递归的。继续我的尝试。

int** cartesian (int** A, int x, int* y, int* newx, int* newy) {
  *newy = x;
  *newx = 1;
  for (int i = 0; i < x; i++)
    *newx *= y[i];
  int** B = malloc(sizeof(int) * *newx * *newy);

  int xi = 0;
  int* tmp_prod = malloc(sizeof(int) * x);
  recurse(x, 0, y, A, &xi, tmp_prod, B);
  free(tmp_prod);

  return B;
}

void recurse(int x, int xi, int* y, int** A, int* newx, int* temp_inner, int** B) {
  if (xi < x) {
    for (int i = 0; i < y[xi]; i++) {
      temp_inner[xi] = A[xi][i];
      recurse(x, xi + 1, y, A, newx, temp_inner, B);
    }
  } else {
    for (int i = 0; i < x; i++) {
      B[*newx][i] = temp_inner[i];
    }
    (*newx)++;
  }
}

这是我已经得到的。递归函数构建一个[递归深度]的一个元素的临时数组,然后当它在maxdepth时,它分配该B,并增加Bs迭代器,回溯并选择[递归深度]的下一个元素,等等。角

问题是段错误,我无法弄清楚原因。

2 个答案:

答案 0 :(得分:1)

你首先说你找不到迭代实现,所以作为你问题的答案,我会提供一个。

从包含尽可能多的整数的数组开始,从0开始全部为整数。 每个整数代表一组。

const unsigned int x = 3;
unsigned int *ar = calloc(x, sizeof(unsigned int));

现在,向上计数,好像你的数组是一个里程表,但是当它达到相应集合中的元素数量时,每个数字都会翻转。

然后,您可以使用数组中的索引从集合中读取元素来读取元素:

{0, 0, 0} = {1, 2, 4}
{0, 0, 1} = {1, 2, 5}
...
{0, 1, 2} = {1, 3, 6}

0,1,2是整个阵列再次翻转之前的最后一个。

答案 1 :(得分:1)

问题在于你分配B的方式。你需要将它作为 newx 指针的数组分配给int,然后将每个元素分配为 newy 整数。

int** B = malloc(sizeof(int*) * *newx);
for (unsigned int i = 0 ; i < *newx; i++) {
   B[i] = malloc(sizeof(int) * *newy);
}

但我仍然支持我之前使用迭代解决方案的答案。