C++中的笛卡尔积

C++中的笛卡尔积,c++,cartesian-product,C++,Cartesian Product,我已经搜索了几个星期,研究如何找到一段可以应用笛卡尔积的代码。假设我有两个数组: int M[2]= {1,2}; int J[3] = {0,1,2}; 因此,代码将采用这两个数组来应用规则mxj 因此,我们将有对1,01,11,22,02,12,2,我希望新结果保存到一个新数组中,数组中的每个索引都包含一对,例如c[0]=1,0。 请帮助:下面是一个使用向量实现笛卡尔积的简单示例。向量是更好的选择,因为我们不需要担心它的大小,因为它会动态地改变它 #include <iostream

我已经搜索了几个星期,研究如何找到一段可以应用笛卡尔积的代码。假设我有两个数组:

int M[2]= {1,2};
int J[3] = {0,1,2};
因此,代码将采用这两个数组来应用规则mxj 因此,我们将有对1,01,11,22,02,12,2,我希望新结果保存到一个新数组中,数组中的每个索引都包含一对,例如c[0]=1,0。
请帮助:

下面是一个使用向量实现笛卡尔积的简单示例。向量是更好的选择,因为我们不需要担心它的大小,因为它会动态地改变它

#include <iostream>
#include <vector>
#include <utility>
using namespace std;

int main() {
    int M[2]= {1,2};
    int J[3] = {0,1,2};
    vector<pair<int,int>> C;

    for (int i = 0; i < sizeof(M)/sizeof(M[0]); i++)
    {
        for (int j = 0; j < sizeof(J)/sizeof(J[1]); j++)
        {
            C.push_back(make_pair(M[i],J[j]));
        }  
    }

    /*
    for (vector<int>::iterator it = C.begin(); it != C.end(); it++)
    {
        cout << *it << endl;
    }

    */

    for (int i = 0; i < C.size(); i++)
    {
        cout << C[i].first << "," << C[i].second << endl;
    }
}

下面是我实现上述代码的地方。虽然我不会发布与您的问题直接相关的解决方案,但在评论中发布的链接已经包含了答案,这就是我发布的原因。

这里是一个使用vector实现笛卡尔积的简单示例。向量是更好的选择,因为我们不需要担心它的大小,因为它会动态地改变它

#include <iostream>
#include <vector>
#include <utility>
using namespace std;

int main() {
    int M[2]= {1,2};
    int J[3] = {0,1,2};
    vector<pair<int,int>> C;

    for (int i = 0; i < sizeof(M)/sizeof(M[0]); i++)
    {
        for (int j = 0; j < sizeof(J)/sizeof(J[1]); j++)
        {
            C.push_back(make_pair(M[i],J[j]));
        }  
    }

    /*
    for (vector<int>::iterator it = C.begin(); it != C.end(); it++)
    {
        cout << *it << endl;
    }

    */

    for (int i = 0; i < C.size(); i++)
    {
        cout << C[i].first << "," << C[i].second << endl;
    }
}

下面是我实现上述代码的地方。虽然我不会发布直接与你的问题有关的解决方案,但是评论中的链接已经包含了答案,这就是我为什么发布的。

< P>我认为使用C++二维数组是一个很坏的想法,但是如果你想,你可能可以使用这个代码

    #include <iostream>    
    int** cartesian_prod( int* s1, int* s2, int s1size, int s2size )
    {
        int ressize = s1size*s2size;
        int** res = new int*[ressize];
        for ( int i = 0; i < s1size; i++ )
            for ( int j = 0; j < s2size; j++ )
            {
                res[i*s2size+j] = new int[2];
                res[i*s2size+j][0] = s1[i];
                res[i*s2size+j][1] = s2[j];
            }
        return res;
    }
    int main() {
        int M[2]= {1,2};
        int J[3] = {0,1,2};
        int** res;
        int Msize = sizeof(M)/sizeof(M[0]);
        int Jsize = sizeof(J)/sizeof(J[1]);
        res = cartesian_prod(M, J, Msize, Jsize);
        for ( int i = 0; i < Msize*Jsize; i++ )
            std::cout << res[i][0] << " " << res[i][1] << std::endl;
        for (int i = 0; i < Msize*Jsize; i++)
            delete[] res[i];
        delete[] res;
        return 0;
    }

<>但是最好是处理STD::向量——它在开发时间上要快得多,并且可以避免很多错误。

< P>我认为使用C++二维数组是一个很坏的想法,但是如果你想,你可能可以使用这个代码< /P>
    #include <iostream>    
    int** cartesian_prod( int* s1, int* s2, int s1size, int s2size )
    {
        int ressize = s1size*s2size;
        int** res = new int*[ressize];
        for ( int i = 0; i < s1size; i++ )
            for ( int j = 0; j < s2size; j++ )
            {
                res[i*s2size+j] = new int[2];
                res[i*s2size+j][0] = s1[i];
                res[i*s2size+j][1] = s2[j];
            }
        return res;
    }
    int main() {
        int M[2]= {1,2};
        int J[3] = {0,1,2};
        int** res;
        int Msize = sizeof(M)/sizeof(M[0]);
        int Jsize = sizeof(J)/sizeof(J[1]);
        res = cartesian_prod(M, J, Msize, Jsize);
        for ( int i = 0; i < Msize*Jsize; i++ )
            std::cout << res[i][0] << " " << res[i][1] << std::endl;
        for (int i = 0; i < Msize*Jsize; i++)
            delete[] res[i];
        delete[] res;
        return 0;
    }
#include <iostream>
#include <iterator>
#include <vector>
#include <utility>
#include <tuple>

template<typename Range1, typename Range2, typename OutputIterator>
void cartesian_product(Range1 const &r1, Range2 const &r2, OutputIterator out) {
    using std::begin; using std::end;
    
    for (auto i = begin(r1);i != end(r1); ++i) {
        for (auto j = begin(r2); j != end(r2); ++j) {
            *out++ = std::make_tuple(*i, *j);
        }
    }
}

int main() {
    std::vector<int> a{1,2,3};
    std::vector<char> b{'a','b','c','d','e','f'};
    
    std::vector<std::tuple<int, char>> c;
    cartesian_product(a, b, back_inserter(c));
    
    for (auto &&v : c) {
        std::cout << "(" << std::get<int>(v) << "," << std::get<char>(v) << ")";
    }
}
但是处理std::vector要好得多——它在开发时间方面要快得多,并且可以避免许多错误

#include <iostream>
#include <iterator>
#include <vector>
#include <utility>
#include <tuple>

template<typename Range1, typename Range2, typename OutputIterator>
void cartesian_product(Range1 const &r1, Range2 const &r2, OutputIterator out) {
    using std::begin; using std::end;
    
    for (auto i = begin(r1);i != end(r1); ++i) {
        for (auto j = begin(r2); j != end(r2); ++j) {
            *out++ = std::make_tuple(*i, *j);
        }
    }
}

int main() {
    std::vector<int> a{1,2,3};
    std::vector<char> b{'a','b','c','d','e','f'};
    
    std::vector<std::tuple<int, char>> c;
    cartesian_product(a, b, back_inserter(c));
    
    for (auto &&v : c) {
        std::cout << "(" << std::get<int>(v) << "," << std::get<char>(v) << ")";
    }
}
印刷品:

1、a1、b1、c1、d1、e1、f2、a2、b2、c2、d2、e2、f3、a3、b3、c3、d3、e3、f

您还可以将该功能应用于您的案例:

template<typename T, int N> constexpr int size(T (&)[N]) { return N; }

int main() {
    int M[2] = {1,2};
    int J[3] = {0,1,2};

    std::tuple<int, int> product[size(M) * size(J)];

    cartesian_product(M, J, product);

    for (auto &&v : product) {
        std::cout << "(" << std::get<0>(v) << "," << std::get<1>(v) << ")";
    }
}
输出为:

1,01,11,22,02,12,2

印刷品:

1、a1、b1、c1、d1、e1、f2、a2、b2、c2、d2、e2、f3、a3、b3、c3、d3、e3、f

您还可以将该功能应用于您的案例:

template<typename T, int N> constexpr int size(T (&)[N]) { return N; }

int main() {
    int M[2] = {1,2};
    int J[3] = {0,1,2};

    std::tuple<int, int> product[size(M) * size(J)];

    cartesian_product(M, J, product);

    for (auto &&v : product) {
        std::cout << "(" << std::get<0>(v) << "," << std::get<1>(v) << ")";
    }
}
输出为:

1,01,11,22,02,12,2


以下是一个实现,其中值序列是一个参数,而不是所有其他实现中预先知道的参数:

void CartesianRecurse(vector<vector<int>> &accum, vector<int> stack,
    vector<vector<int>> sequences, int index)
{
    vector<int> sequence = sequences[index];
    for (int i : sequence)
    {       
        stack.push_back(i);
        if (index == 0)
            accum.push_back(stack);
        else
            CartesianRecurse(accum, stack, sequences, index - 1);
        stack.pop_back();
    }
}
vector<vector<int>> CartesianProduct(vector<vector<int>> sequences)
{
    vector<vector<int>> accum;
    vector<int> stack;
    if (sequences.size() > 0)
        CartesianRecurse(accum, stack, sequences, sequences.size() - 1);
    return accum;
}

main() {
    vector<vector<int>> sequences = { {1,2,7},{3,4},{5,6} };
    vector<vector<int>> res = CartesianProduct(sequences);
    // now do something with the result in 'res'.
}

以下是一个实现,其中值序列是一个参数,而不是所有其他实现中预先知道的参数:

void CartesianRecurse(vector<vector<int>> &accum, vector<int> stack,
    vector<vector<int>> sequences, int index)
{
    vector<int> sequence = sequences[index];
    for (int i : sequence)
    {       
        stack.push_back(i);
        if (index == 0)
            accum.push_back(stack);
        else
            CartesianRecurse(accum, stack, sequences, index - 1);
        stack.pop_back();
    }
}
vector<vector<int>> CartesianProduct(vector<vector<int>> sequences)
{
    vector<vector<int>> accum;
    vector<int> stack;
    if (sequences.size() > 0)
        CartesianRecurse(accum, stack, sequences, sequences.size() - 1);
    return accum;
}

main() {
    vector<vector<int>> sequences = { {1,2,7},{3,4},{5,6} };
    vector<vector<int>> res = CartesianProduct(sequences);
    // now do something with the result in 'res'.
}


一个std::vector应该可以。我不擅长于vector。。。你有关于数组的例子吗?请@rsahu也许,你应该看看。我读了所有的文章,但他们都使用向量,我不擅长向量。关于向量,你有什么想法如何在数组中使用它。。。非常感谢您的帮助:@kvorbieva std::vector应该可以。我对vectors不太在行。。。你有关于数组的例子吗?请@rsahu也许,你应该看看。我读了所有的文章,但他们都使用向量,我不擅长向量。关于向量,你有什么想法如何在数组中使用它。。。感谢您的帮助:@kvorbievi有一个问题:为什么不使用常规for循环来打印c数组?类似于int i=0;iA笛卡尔积实际上并不会将这些值相乘。它创建所有可能的元素对,这样每对元素都有来自每个输入集的一个元素@梅洛,你可以像那样打印向量。见编辑solution@mello因为使用迭代器是处理stl容器的一种常规方法。@bames53 Oops,我想在盲目发布解决方案之前,我应该先研究一下我认为是乘法的mxj。我将研究并编辑我的解决方案。谢谢。我有一个问题:为什么不使用常规for循环来打印c数组?类似于int i=0;iA笛卡尔积实际上并不会将这些值相乘。它创建所有可能的元素对,这样每对元素都有来自每个输入集的一个元素@梅洛,你可以像那样打印向量。见编辑solution@mello因为使用迭代器是处理stl容器的一种常规方法。@bames53 Oops,我想在盲目发布解决方案之前,我应该先研究一下我认为是乘法的mxj。我将研究并编辑我的解决方案。谢谢,梅洛,好的。我添加了更多的代码作为用法示例。@mello我修复了代码中的一些错误,请查看新版本。谢谢。。。你今天帮了我很多忙:@mello是的。我添加了更多的代码作为用法示例。@mello我修复了代码中的一些错误,请查看新版本。谢谢。。。你今天帮了我很多忙:我试着运行代码,它说笛卡尔的产品不是declare@mello我猜您复制了第二个示例,但没有包括第一个示例中的程序的其余部分。您的程序运行正常。。。我有一些问题:用于显示结果的for循环。。你能给我一些解释吗,因为我从来没有在我的生活中使用模板lol。。我刚用谷歌搜索了一下,就好像你在使用下一个级别的东西。@mello The forauto&&v:c是一个c++11的特性,叫做基于范围的for循环。T
冒号后的表达式必须符合支持访问范围内每个元素的特定API。数组和向量都可以工作。冒号前的部分是一个变量的声明,该变量将使用范围中的每个元素初始化。循环v的第一次是第一个元素,第二次是第二个元素,等等@mello循环体是std::cout的基本用法,除了我打印的是一个元组。元组发音为“两拉”的元组将成对、三元组、四元组等概念推广到任何数字。在这个例子中,我只使用了两个项目,所以它本质上是一对。C++构造STD::tuple有一个通用的方法来从元组中获取特定的项,即STD::get函数。getv get是索引0处的项,getv是索引1处的项,等等。所以代码只是打印这对中的每个项。我尝试运行代码,它说笛卡尔_乘积不是declare@mello我猜您复制了第二个示例,但没有包括第一个示例中的程序的其余部分。您的程序运行正常。。。我有一些问题:用于显示结果的for循环。。你能给我一些解释吗,因为我从来没有在我的生活中使用模板lol。。我刚用谷歌搜索了一下,就好像你在使用下一个级别的东西。@mello The forauto&&v:c是一个c++11的特性,叫做基于范围的for循环。冒号后的表达式必须符合支持访问范围内每个元素的特定API。数组和向量都可以工作。冒号前的部分是一个变量的声明,该变量将使用范围中的每个元素初始化。循环v的第一次是第一个元素,第二次是第二个元素,等等@mello循环体是std::cout的基本用法,除了我打印的是一个元组。元组发音为“两拉”的元组将成对、三元组、四元组等概念推广到任何数字。在这个例子中,我只使用了两个项目,所以它本质上是一对。C++构造STD::tuple有一个通用的方法来从元组中获取特定的项,即STD::get函数。getv get是索引0处的项,getv是索引1处的项,等等。因此代码只是打印这对中的每个项。