C++ 如何创建向量的笛卡尔积?
我有一个向量向量,表示不同大小的C++ 如何创建向量的笛卡尔积?,c++,vector,combinations,cartesian-product,C++,Vector,Combinations,Cartesian Product,我有一个向量向量,表示不同大小的向量项,如下所示 1,2,3 4,5 6,7,8 我想用这些向量的笛卡尔积来创建组合,比如 1,4,6 1,4,7 1,4,8 and so on till 3,5,8 我该怎么做?我查阅了几个链接,并在本文末尾列出了它们,但我无法解释,因为我对语言不太熟悉。有人能帮我吗 #include <iostream> #include <iomanip> #include <vector> using namespace std
向量项
,如下所示
1,2,3
4,5
6,7,8
我想用这些向量的笛卡尔积来创建组合,比如
1,4,6
1,4,7
1,4,8
and so on till
3,5,8
我该怎么做?我查阅了几个链接,并在本文末尾列出了它们,但我无法解释,因为我对语言不太熟悉。有人能帮我吗
#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;
int main()
{
vector<vector<int> > items;
int k = 0;
for ( int i = 0; i < 5; i++ ) {
items.push_back ( vector<int>() );
for ( int j = 0; j < 5; j++ )
items[i].push_back ( k++ );
}
cartesian ( items ); // I want some function here to do this.
}
#包括
#包括
#包括
使用名称空间std;
int main()
{
向量项;
int k=0;
对于(int i=0;i<5;i++){
items.push_back(向量());
对于(int j=0;j<5;j++)
项目[i]。推回(k++);
}
笛卡尔(items);//我需要一些函数来实现这一点。
}
这个程序有相等长度的向量,我这样做是为了更容易理解我的数据结构。这将是非常有帮助的,即使有人使用其他链接的其他答案,并与此集成,以获得结果。多谢各位
我看了几个链接
来自的程序:似乎您需要一个迭代器的
向量
,该迭代器在您个人的向量
上进行迭代
在开始处启动所有迭代器。通过迭代器拉出每个向量的元素来构造第一个乘积向量
增加最右边的一个,然后重复
到达终点后,将该终点重置为起点,并从下一个终点开始递增。您可以从迭代器向量中的相邻元素中提取“下一个到最后一个”迭代器
继续循环,直到最后一个和下一个到最后一个迭代器都在末尾。然后,重置它们,从最后一个迭代器开始增加第三个迭代器。一般来说,这可以是级联的
它就像里程表,但每个不同的数字都位于不同的基数中。首先,我将向您展示一个递归版本
// Cartesion product of vector of vectors
#include <vector>
#include <iostream>
#include <iterator>
// Types to hold vector-of-ints (Vi) and vector-of-vector-of-ints (Vvi)
typedef std::vector<int> Vi;
typedef std::vector<Vi> Vvi;
// Just for the sample -- populate the intput data set
Vvi build_input() {
Vvi vvi;
for(int i = 0; i < 3; i++) {
Vi vi;
for(int j = 0; j < 3; j++) {
vi.push_back(i*10+j);
}
vvi.push_back(vi);
}
return vvi;
}
// just for the sample -- print the data sets
std::ostream&
operator<<(std::ostream& os, const Vi& vi)
{
os << "(";
std::copy(vi.begin(), vi.end(), std::ostream_iterator<int>(os, ", "));
os << ")";
return os;
}
std::ostream&
operator<<(std::ostream& os, const Vvi& vvi)
{
os << "(\n";
for(Vvi::const_iterator it = vvi.begin();
it != vvi.end();
it++) {
os << " " << *it << "\n";
}
os << ")";
return os;
}
// recursive algorithm to to produce cart. prod.
// At any given moment, "me" points to some Vi in the middle of the
// input data set.
// for int i in *me:
// add i to current result
// recurse on next "me"
//
void cart_product(
Vvi& rvvi, // final result
Vi& rvi, // current result
Vvi::const_iterator me, // current input
Vvi::const_iterator end) // final input
{
if(me == end) {
// terminal condition of the recursion. We no longer have
// any input vectors to manipulate. Add the current result (rvi)
// to the total set of results (rvvvi).
rvvi.push_back(rvi);
return;
}
// need an easy name for my vector-of-ints
const Vi& mevi = *me;
for(Vi::const_iterator it = mevi.begin();
it != mevi.end();
it++) {
// final rvi will look like "a, b, c, ME, d, e, f"
// At the moment, rvi already has "a, b, c"
rvi.push_back(*it); // add ME
cart_product(rvvi, rvi, me+1, end); add "d, e, f"
rvi.pop_back(); // clean ME off for next round
}
}
// sample only, to drive the cart_product routine.
int main() {
Vvi input(build_input());
std::cout << input << "\n";
Vvi output;
Vi outputTemp;
cart_product(output, outputTemp, input.begin(), input.end());
std::cout << output << "\n";
}
这是我的解决办法。也是迭代的,但比上面的要短一点
void xp(const vector<vector<int>*>& vecs, vector<vector<int>*> *result) {
vector<vector<int>*>* rslts;
for (int ii = 0; ii < vecs.size(); ++ii) {
const vector<int>& vec = *vecs[ii];
if (ii == 0) {
// vecs=[[1,2],...] ==> rslts=[[1],[2]]
rslts = new vector<vector<int>*>;
for (int jj = 0; jj < vec.size(); ++jj) {
vector<int>* v = new vector<int>;
v->push_back(vec[jj]);
rslts->push_back(v);
}
} else {
// vecs=[[1,2],[3,4],...] ==> rslts=[[1,3],[1,4],[2,3],[2,4]]
vector<vector<int>*>* tmp = new vector<vector<int>*>;
for (int jj = 0; jj < vec.size(); ++jj) { // vec[jj]=3 (first iter jj=0)
for (vector<vector<int>*>::const_iterator it = rslts->begin();
it != rslts->end(); ++it) {
vector<int>* v = new vector<int>(**it); // v=[1]
v->push_back(vec[jj]); // v=[1,3]
tmp->push_back(v); // tmp=[[1,3]]
}
}
for (int kk = 0; kk < rslts->size(); ++kk) {
delete (*rslts)[kk];
}
delete rslts;
rslts = tmp;
}
}
result->insert(result->end(), rslts->begin(), rslts->end());
delete rslts;
}
较短的代码:
vector<vector<int>> cart_product (const vector<vector<int>>& v) {
vector<vector<int>> s = {{}};
for (const auto& u : v) {
vector<vector<int>> r;
for (const auto& x : s) {
for (const auto y : u) {
r.push_back(x);
r.back().push_back(y);
}
}
s = move(r);
}
return s;
}
vector cart\u产品(const vector&v){
向量s={{}};
用于(常数自动和u:v){
向量r;
用于(常量自动和x:s){
用于(常数自动y:u){
r、 推回(x);
r、 后退()。向后推(y);
}
}
s=移动(r);
}
返回s;
}
因为我需要相同的功能,所以我实现了一个迭代器,根据需要动态计算笛卡尔积,并对其进行迭代
它可以按如下方式使用
#include <forward_list>
#include <iostream>
#include <vector>
#include "cartesian.hpp"
int main()
{
// Works with a vector of vectors
std::vector<std::vector<int>> test{{1,2,3}, {4,5,6}, {8,9}};
CartesianProduct<decltype(test)> cp(test);
for(auto const& val: cp) {
std::cout << val.at(0) << ", " << val.at(1) << ", " << val.at(2) << "\n";
}
// Also works with something much less, like a forward_list of forward_lists
std::forward_list<std::forward_list<std::string>> foo{{"boo", "far", "zab"}, {"zoo", "moo"}, {"yohoo", "bohoo", "whoot", "noo"}};
CartesianProduct<decltype(foo)> bar(foo);
for(auto const& val: bar) {
std::cout << val.at(0) << ", " << val.at(1) << ", " << val.at(2) << "\n";
}
}
#包括
#包括
#包括
#包括“cartesian.hpp”
int main()
{
//使用向量的向量
向量测试{{1,2,3},{4,5,6},{8,9};
卡特尔产品cp(测试);
用于(自动常量和值:cp){
std::cout我刚刚被迫为我正在工作的一个项目实现了这一点,我想出了下面的代码。它可以被固定在一个标题中,它的使用非常简单,但它返回你可以从向量向量中得到的所有组合。它返回的数组只包含整数。这是一个有意识的决定,因为我只想通过这种方式,我可以索引到每个向量的向量,然后执行我/任何人都需要的计算…最好避免让CartesianProduct保存“东西”它本身是一个基于计数而不是数据结构的数学概念。我对C++是相当新的,但这是在解密算法中被彻底地测试的。有一些光递归,但总体上,这是一个简单计数概念的简单实现。
// Use of the CartesianProduct class is as follows. Give it the number
// of rows and the sizes of each of the rows. It will output all of the
// permutations of these numbers in their respective rows.
// 1. call cp.permutation() // need to check all 0s.
// 2. while cp.HasNext() // it knows the exit condition form its inputs.
// 3. cp.Increment() // Make the next permutation
// 4. cp.permutation() // get the next permutation
class CartesianProduct{
public:
CartesianProduct(int num_rows, vector<int> sizes_of_rows){
permutation_ = new int[num_rows];
num_rows_ = num_rows;
ZeroOutPermutation();
sizes_of_rows_ = sizes_of_rows;
num_max_permutations_ = 1;
for (int i = 0; i < num_rows; ++i){
num_max_permutations_ *= sizes_of_rows_[i];
}
}
~CartesianProduct(){
delete permutation_;
}
bool HasNext(){
if(num_permutations_processed_ != num_max_permutations_) {
return true;
} else {
return false;
}
}
void Increment(){
int row_to_increment = 0;
++num_permutations_processed_;
IncrementAndTest(row_to_increment);
}
int* permutation(){
return permutation_;
}
int num_permutations_processed(){
return num_permutations_processed_;
}
void PrintPermutation(){
cout << "( ";
for (int i = 0; i < num_rows_; ++i){
cout << permutation_[i] << ", ";
}
cout << " )" << endl;
}
private:
int num_permutations_processed_;
int *permutation_;
int num_rows_;
int num_max_permutations_;
vector<int> sizes_of_rows_;
// Because CartesianProduct is called first initially with it's values
// of 0 and because those values are valid and important output
// of the CartesianProduct we increment the number of permutations
// processed here when we populate the permutation_ array with 0s.
void ZeroOutPermutation(){
for (int i = 0; i < num_rows_; ++i){
permutation_[i] = 0;
}
num_permutations_processed_ = 1;
}
void IncrementAndTest(int row_to_increment){
permutation_[row_to_increment] += 1;
int max_index_of_row = sizes_of_rows_[row_to_increment] - 1;
if (permutation_[row_to_increment] > max_index_of_row){
permutation_[row_to_increment] = 0;
IncrementAndTest(row_to_increment + 1);
}
}
};
//CartesianProduct类的用法如下。请给它编号
//以及每行的大小。它将输出
//这些数字在各自行中的排列。
//1.调用cp.permutation()//需要检查所有0。
//2.而cp.HasNext()//它从输入中知道退出条件。
//3.cp.Increment()//进行下一次置换
//4.cp.permutation()//获取下一个置换
类卡特尔产品{
公众:
CartesianProduct(int num_行、向量大小_行){
置换=新整数[num_行];
num_rows=num_rows;
零输出项();
行的大小=行的大小;
num_max_置换=1;
对于(int i=0;i 这是C++11中的一个解决方案
可变大小数组的索引可以用模块化算法很好地完成
输出中的总行数是输入向量大小的乘积。即:
N = v[0].size() * v[1].size() * v[2].size()
因此,主循环将n
作为迭代变量,从0
到n-1
。原则上,n
的每个值编码足够的信息,以便为该迭代提取v
的每个索引。这是在使用重复模运算的子循环中完成的:
#include <cstdlib>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
void cartesian( vector<vector<int> >& v ) {
auto product = []( long long a, vector<int>& b ) { return a*b.size(); };
const long long N = accumulate( v.begin(), v.end(), 1LL, product );
vector<int> u(v.size());
for( long long n=0 ; n<N ; ++n ) {
lldiv_t q { n, 0 };
for( long long i=v.size()-1 ; 0<=i ; --i ) {
q = div( q.quot, v[i].size() );
u[i] = v[i][q.rem];
}
// Do what you want here with u.
for( int x : u ) cout << x << ' ';
cout << '\n';
}
}
int main() {
vector<vector<int> > v { { 1, 2, 3 },
{ 4, 5 },
{ 6, 7, 8 } };
cartesian(v);
return 0;
}
#包括
#包括
void笛卡尔(标准::向量常量和项目){
auto n=items.size();
自动下一步=[&](标准::向量和x){
对于(int i=0;i 此版本不支持迭代器或范围,但它是一个简单的直接实现,使用乘法运算符表示笛卡尔乘积,即
// Use of the CartesianProduct class is as follows. Give it the number
// of rows and the sizes of each of the rows. It will output all of the
// permutations of these numbers in their respective rows.
// 1. call cp.permutation() // need to check all 0s.
// 2. while cp.HasNext() // it knows the exit condition form its inputs.
// 3. cp.Increment() // Make the next permutation
// 4. cp.permutation() // get the next permutation
class CartesianProduct{
public:
CartesianProduct(int num_rows, vector<int> sizes_of_rows){
permutation_ = new int[num_rows];
num_rows_ = num_rows;
ZeroOutPermutation();
sizes_of_rows_ = sizes_of_rows;
num_max_permutations_ = 1;
for (int i = 0; i < num_rows; ++i){
num_max_permutations_ *= sizes_of_rows_[i];
}
}
~CartesianProduct(){
delete permutation_;
}
bool HasNext(){
if(num_permutations_processed_ != num_max_permutations_) {
return true;
} else {
return false;
}
}
void Increment(){
int row_to_increment = 0;
++num_permutations_processed_;
IncrementAndTest(row_to_increment);
}
int* permutation(){
return permutation_;
}
int num_permutations_processed(){
return num_permutations_processed_;
}
void PrintPermutation(){
cout << "( ";
for (int i = 0; i < num_rows_; ++i){
cout << permutation_[i] << ", ";
}
cout << " )" << endl;
}
private:
int num_permutations_processed_;
int *permutation_;
int num_rows_;
int num_max_permutations_;
vector<int> sizes_of_rows_;
// Because CartesianProduct is called first initially with it's values
// of 0 and because those values are valid and important output
// of the CartesianProduct we increment the number of permutations
// processed here when we populate the permutation_ array with 0s.
void ZeroOutPermutation(){
for (int i = 0; i < num_rows_; ++i){
permutation_[i] = 0;
}
num_permutations_processed_ = 1;
}
void IncrementAndTest(int row_to_increment){
permutation_[row_to_increment] += 1;
int max_index_of_row = sizes_of_rows_[row_to_increment] - 1;
if (permutation_[row_to_increment] > max_index_of_row){
permutation_[row_to_increment] = 0;
IncrementAndTest(row_to_increment + 1);
}
}
};
N = v[0].size() * v[1].size() * v[2].size()
#include <cstdlib>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
void cartesian( vector<vector<int> >& v ) {
auto product = []( long long a, vector<int>& b ) { return a*b.size(); };
const long long N = accumulate( v.begin(), v.end(), 1LL, product );
vector<int> u(v.size());
for( long long n=0 ; n<N ; ++n ) {
lldiv_t q { n, 0 };
for( long long i=v.size()-1 ; 0<=i ; --i ) {
q = div( q.quot, v[i].size() );
u[i] = v[i][q.rem];
}
// Do what you want here with u.
for( int x : u ) cout << x << ' ';
cout << '\n';
}
}
int main() {
vector<vector<int> > v { { 1, 2, 3 },
{ 4, 5 },
{ 6, 7, 8 } };
cartesian(v);
return 0;
}
1 4 6
1 4 7
1 4 8
...
3 5 8
int main()
{
vector< vector<long> > v{ { 1, 2, 3 }, { 4, 5 }, { 6, 7, 8 } };
(Cartesian<long>(v[0]) * v[1] * v[2]).ForEach(
[](long p_Depth, long *p_LongList)
{
std::cout << p_LongList[0] << " " << p_LongList[1] << " " << p_LongList[2] << std::endl;
}
);
}
#include <vector>
#include <iostream>
#include <functional>
#include <string>
using namespace std;
template <class T>
class Cartesian
{
private:
vector<T> &m_Vector;
Cartesian<T> *m_Cartesian;
public:
Cartesian(vector<T> &p_Vector, Cartesian<T> *p_Cartesian=NULL)
: m_Vector(p_Vector), m_Cartesian(p_Cartesian)
{};
virtual ~Cartesian() {};
Cartesian<T> *Clone()
{
return new Cartesian<T>(m_Vector, m_Cartesian ? m_Cartesian->Clone() : NULL);
};
Cartesian<T> &operator *=(vector<T> &p_Vector)
{
if (m_Cartesian)
(*m_Cartesian) *= p_Vector;
else
m_Cartesian = new Cartesian(p_Vector);
return *this;
};
Cartesian<T> operator *(vector<T> &p_Vector)
{
return (*Clone()) *= p_Vector;
};
long Depth()
{
return m_Cartesian ? 1 + m_Cartesian->Depth() : 1;
};
void ForEach(function<void (long p_Depth, T *p_ParamList)> p_Action)
{
Loop(0, new T[Depth()], p_Action);
};
private:
void Loop(long p_Depth, T *p_ParamList, function<void (long p_Depth, T *p_ParamList)> p_Action)
{
for (T &element : m_Vector)
{
p_ParamList[p_Depth] = element;
if (m_Cartesian)
m_Cartesian->Loop(p_Depth + 1, p_ParamList, p_Action);
else
p_Action(Depth(), p_ParamList);
}
};
};