C++中的 "Cartiesian Product "方法

问题描述 投票:0回答:1

我有下面的代码,在来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;
}

这将为传递给它的所有可能的数字组合创建一个 "笛卡尔乘积 "数组。我在这里的具体困惑是这个块在做什么?

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# c++ code-translation
1个回答
4
投票

这就分配了一个内存块来存储一个二维数组,作为一个数组的数组。C语言中的数组是以指向更多数组的指针数组的形式存储的;我的第一反应是 "呸",但这里有一些优雅的地方,因为所有的东西都是作为一个单一的内存块返回的,可以在之后一次性的free()ed。

这段代码

  1. 为(sizeA * sizeB)int-pointers分配空间,然后2 * sizeA * sizeB;将其存储为int**指针,即我们将使用其中的第一个块作为我们的2D数组的顶层。
  2. (你所引用的代码)设置顶层数组的指针指向剩余内存的两个int块。
  3. 使用2D数组来存储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 } 而不是在内部选择。


2
投票

说点题外话。

这段代码可能看起来像一个 C++ 代码,但我会这样称呼它。它更像是 C 伪装的代码 C++的结果,因为 malloc 明确地投向 int** (需要在 C++C 陈旧的)。)

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;
}
© www.soinside.com 2019 - 2024. All rights reserved.