我一直在寻找如何提出我可以应用笛卡尔积的代码。假设我有两个数组:
int M[2]= {1,2};
int J[3] = {0,1,2};
因此代码将采用这两个数组应用规则M X J 因此我们将得到对(1,0)(1,1)(1,2)(2,0)(2,1)(2,2)并且我希望将新结果保存到新数组中数组中的每个索引都包含一对,例如c [0] =(1,0)。 请帮助:(
答案 0 :(得分:4)
#include <iostream>
#include <iterator>
#include <vector>
#include <utility>
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,A)(1,B)(1,C)(1,d)(1,E)(1,F)(2,)(2,B)(2,C)(2 ,d)(2,E)(2,F)(3,)(3,b)(3,C)(3,d)(3,E)(3,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,0)(1,1)(1,2)(2,0)(2,1)(2,2)
答案 1 :(得分:1)
这是使用矢量实现笛卡尔积的简单示例。向量是更好的选择,因为我们不需要担心它的大小,因为它会动态地改变它。
#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;
}
}
以下是我实现上述代码的link。虽然我不会直接发布与您的问题相关的解决方案,但评论中发布的链接已经包含了我发布的答案。
答案 2 :(得分:1)
我认为使用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 :: vector要好得多 - 它在开发时间方面要快得多,并且可以避免许多错误。
答案 3 :(得分:0)
这里是一个实现,其中值的序列是一个参数(而不是在所有其他实现中都是众所周知的):
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'.
}
答案 4 :(得分:0)
没有 for 循环的解决方案。
#include<array>
#include<iostream>
#include<tuple>
#include<utility>
template
<typename T, typename Tuple, std::size_t... I>
auto cartesian_product_base(
const T& a,
const Tuple& t,
std::index_sequence<I...>) {
return std::make_tuple(std::make_pair(a, std::get<I>(t))...);
}
template
<typename T, typename... Ts, std::size_t... I>
std::array<T, sizeof...(Ts) + 1> to_array(std::tuple<T, Ts...> t, std::index_sequence<I...>) {
return {std::get<I>(t)...};
}
template
<typename Tuple1, typename Tuple2, std::size_t... I>
auto cartesian_product_impl(
const Tuple1& t1,
const Tuple2& t2,
std::index_sequence<I...>) {
return std::tuple_cat(cartesian_product_base(
std::get<I>(t1),
t2,
std::make_index_sequence<std::tuple_size<Tuple2>::value>{})...);
}
template
<typename T1, std::size_t N1, typename T2, std::size_t N2>
auto cartesian_product(
const std::array<T1, N1>& a1,
const std::array<T2, N2>& a2) {
return to_array(
cartesian_product_impl(a1, a2, std::make_index_sequence<N1>{}),
std::make_index_sequence<N1 * N2>{});
}
using namespace std;
int main() {
array<int, 2> M = {1, 2};
array<int, 3> J = {0, 1, 2};
auto C = cartesian_product(M, J);
cout << C.size() << endl;
cout << "{";
for (size_t i = 0; i != C.size(); ++i) {
if (i != 0) {
cout << ", ";
}
cout << "(" << C[i].first << ", " << C[i].second << ")";
}
cout << "}" << endl;
}