Метод "Cartiesian Product" в C ++ - PullRequest
       14

Метод "Cartiesian Product" в C ++

2 голосов
/ 28 апреля 2020

У меня есть следующий код на 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;
}

Это создает массив «декартовых произведений» для всех возможных комбинаций переданных ему чисел. Моя конкретная путаница c заключается в том, что делает этот блок?

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);?

Ответы [ 2 ]

4 голосов
/ 28 апреля 2020

Это выделяет один блок памяти для хранения двумерного массива в виде массива массивов. C массивы массивов хранятся в виде массива указателей на дальнейшие массивы; Моей первой мыслью было «гадость», но здесь есть некоторая элегантность в том, что все возвращается как один блок памяти, который может быть освобожден () за один go впоследствии.

Этот код

  1. выделяет место для int-указателей (sizeA * sizeB), а затем 2 * sizeA * sizeB; сохраните это как указатель типа int **, т.е. мы будем использовать первый блок этого как верхний уровень нашего 2D-массива
  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 } во внутреннем выделении.

2 голосов
/ 28 апреля 2020

Немного топи c.

Этот код может выглядеть как 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...