"Cartiesian Product" C++ 中的方法

"Cartiesian Product" Method in C++

我在 C++ 中有以下代码,我需要将其转换为 C#

int** _cartesianProduct(int sizeA, int sizeB) {

    int** array = (int**)malloc(sizeof(int*) * sizeA * sizeB + sizeof(int) * 2 * sizeA * sizeB);

    int* ptr = (int*)(array + sizeA * sizeB);
    for (int i = 0; i < sizeA * sizeB; ++i)
        array[i] = (ptr + 2 * i);

    for (int i = 0; i < sizeA; ++i)
        for (int k = 0; k < sizeB; ++k) {
            array[i * sizeB + k][0] = i;
            array[i * sizeB + k][1] = k;
        }

    return array;
}

这会为传递给它的数字的所有可能组合创建一个 "Cartesian products" 数组。我在这里的具体困惑是这个块在做什么?

int* ptr = (int*)(array + sizeA * sizeB);
    for (int i = 0; i < sizeA * sizeB; ++i)
        array[i] = (ptr + 2 * i);

或者更具体地说,这一行 int* ptr = (int*)(array + sizeA * sizeB);?

这将分配单个内存块来存储二维数组,作为数组的数组。数组的 C 数组存储为指向更多数组的指针数组;我的第一个想法是 'yuck',但这里有一些优雅之处在于所有内容都作为单个内存块返回,之后可以一次性释放。

这段代码

  1. 为 (sizeA * sizeB) 个 int 指针分配 space,然后是 2 * sizeA * sizeB;将它存储为一个 int** 指针,即我们将使用它的第一个块作为我们二维数组的顶层
  2. (您引用的代码)设置顶级数组的指针指向剩余内存的两个整数块
  3. 使用二维数组存储 0-sizeA, 0-sizeB 范围内的值对

如何将其移植到 C#?这取决于您希望如何使用生成的值。我可能会将其设为一个值元组数组,

var array = Enumerable.Range(0, sizeA).SelectMany(a =>
                Enumerable.Range(0, sizeB).Select(b => (a,b))).ToList();

.ToArray()。如果你确实想要锯齿状数组版本,你可以 new[] { a, b } 而不是内部 select.

有点话题。

此代码可能看起来像 C++ 代码,但我会这样称呼它。它更像是伪装成 C++C 代码,因为 malloc 的结果被显式转换为 int**(在 C++ 和 [=12= 中需要) ] 已过时)。

它的 C++ 版本可能如下所示:

std::vector<std::array<int, 2>> cartesianProduct(int sizeA, int sizeB) {
    std::vector<std::array<int, 2>> result(sizeA * sizeB);

    for (int i = 0; i < sizeA; ++i) {
        for (int k = 0; k < sizeB; ++k) {
            result[i * sizeB + k] = { i, k };
        }
    }
    return result;
}