C++ 从向量中提取子向量的最佳方法?
假设我有一个C++ 从向量中提取子向量的最佳方法?,c++,stl,vector,range,C++,Stl,Vector,Range,假设我有一个std::vector(我们称之为myVec),大小为N。构建由元素X到Y的副本组成的新向量的最简单方法是什么,其中当M是子向量的大小时,0可以与O(M)性能一起使用。std::vector(输入迭代器,输入迭代器),在您的例子中是foo=std::vector(myVec.begin()+100000,myVec.begin()+150000),例如参见vector::const_iterator first=myVec.begin()+100000; vector::const_
std::vector
(我们称之为myVec
),大小为N
。构建由元素X到Y的副本组成的新向量的最简单方法是什么,其中当M是子向量的大小时,0可以与O(M)性能一起使用。std::vector(输入迭代器,输入迭代器),在您的例子中是foo=std::vector(myVec.begin()+100000,myVec.begin()+150000)代码>,例如参见vector::const_iterator first=myVec.begin()+100000;
vector::const_iterator last=myVec.begin()+101000;
向量newVec(第一个,最后一个);
构建新向量是一个O(N)操作,但实际上没有更好的方法。投射非线性时间的集合的唯一方法是惰性地这样做,由此产生的“向量”实际上是委托给原始集合的子类型。例如,Scala的List#subseq
方法在固定时间内创建一个子序列。但是,只有当收集是不可变的并且底层语言使用垃圾收集时,这才有效。只需使用向量构造函数即可
std::vector<int> data();
// Load Z elements into data so that Z > Y > X
std::vector<int> sub(&data[100000],&data[101000]);
std::vector<T> newVector;
newVector.reserve(1000);
std::copy_n(&vec[100000], 1000, std::back_inserter(newVector));
std::vector data();
//将Z元素加载到数据中,以便Z>Y>X
标准::矢量子(&data[100000],&data[101000]);
如果两者都不需要修改(不添加/删除项-只要注意线程问题,修改现有项就可以了),您只需传递数据.begin()+100000
和数据.begin()+101000
,并假装它们是开始()
和结束()
较小的向量
或者,由于矢量存储保证是连续的,您可以简单地传递1000项数组:
T *arrayOfT = &data[0] + 100000;
size_t arrayOfTLength = 1000;
这两种技术都需要固定的时间,但要求数据长度不增加,从而触发重新分配。仅为其他人发布此延迟。我打赌第一个编码器现在已经完成。
对于简单的数据类型,不需要复制,只需恢复到良好的旧C代码方法
std::vector <int> myVec;
int *p;
// Add some data here and set start, then
p=myVec.data()+start;
std::vector myVec;
int*p;
//在此处添加一些数据并设置开始,然后
p=myVec.data()+开始;
然后将指针p和len传递给任何需要子向量的对象
诺特伦一定是len
您没有提到什么类型std::vector myVec
,但是如果它是一个不包含指针的简单类型或结构/类,并且您希望获得最佳效率,那么您可以直接进行内存复制(我认为这将比提供的其他答案更快)。以下是std::vector myVec
的一般示例,其中type
在本例中为int
:
typedef int type; //choose your custom type/struct/class
int iFirst = 100000; //first index to copy
int iLast = 101000; //last index + 1
int iLen = iLast - iFirst;
std::vector<type> newVec;
newVec.resize(iLen); //pre-allocate the space needed to write the data directly
memcpy(&newVec[0], &myVec[iFirst], iLen*sizeof(type)); //write directly to destination buffer from source buffer
typedef int-type//选择自定义类型/结构/类
int iFirst=100000//要复制的第一个索引
int iLast=101000//最后一个索引+1
int iLen=iLast-iFirst;
std::vector newVec;
新向量调整大小(iLen)//预先分配直接写入数据所需的空间
memcpy(&newVec[0],&myVec[iFirst],iLen*sizeof(type))//从源缓冲区直接写入目标缓冲区
也许GSL库中的是一个不错的选择
这里还有一个单文件实现:。现在,我们使用span
s!所以你会写:
#include <gsl/span>
...
auto start_pos = 100000;
auto length = 1000;
auto span_of_myvec = gsl::make_span(myvec);
auto my_subspan = span_of_myvec.subspan(start_pos, length);
(但我不太喜欢这一点,因为每个数字参数的含义并不完全清楚;如果长度和起始位置的数量级相同,情况会变得更糟。)
无论如何,记住这不是一个副本,它只是向量中数据的一个视图,所以要小心。如果您想要实际副本,可以执行以下操作:
std::vector<T> new_vec(my_subspan.cbegin(), my_subspan.cend());
std::vector new_vec(my_subspan.cbegin(),my_subspan.cend());
注:
gsl
代表指南支持库。有关gsl的更多信息,请参阅:
- 有几种
gsl
实现。例如:
- C++20提供了
span
的实现。您可以使用std::span
和#include
而不是#include
- 有关跨距的详细信息,请参见:
std::vector
有无数的构造函数,很容易落入你不想使用的构造函数中,所以要小心
轻松地将元素从一个向量复制到另一个向量
在本例中,我使用成对向量使其易于理解
`
向量v(n);
//我们需要一半的元素在向量a中,另一半在向量b中
向量a(v.begin(),v.begin()+n/2);
向量b(v.begin()+n/2,v.end());
//如果v=[(1,2)、(2,3)、(3,4)、(4,5)、(5,6)]
//然后a=[(1,2)、(2,3)]
//和b=[(3,4)、(4,5)、(5,6)]
//如果v=[(1,2)、(2,3)、(3,4)、(4,5)、(5,6)、(6,7)]
//然后a=[(1,2)、(2,3)、(3,4)]
//和b=[(4,5)、(5,6)、(6,7)]
"
如您所见,您可以轻松地将元素从一个向量复制到另一个向量,例如,如果您希望将元素从索引10复制到16,那么我们将使用
vector<pair<int, int> > a(v.begin()+10, v.begin+16);
向量a(v.begin()+10,v.begin+16);
若你们想要从索引10中的元素到从末尾的某个索引,那个么在这种情况下
vector<pair<int, int> > a(v.begin()+10, v.end()-5);
向量a(v.begin()+10,v.end()-5);
希望这有帮助,只需记住最后一个例子v.end()-5>v.begin()+10
还有另一个选项:
例如,在无法使用构造函数的推力::设备_向量
和推力::主机_向量
之间移动时非常有用
std::vector<int> data();
// Load Z elements into data so that Z > Y > X
std::vector<int> sub(&data[100000],&data[101000]);
std::vector<T> newVector;
newVector.reserve(1000);
std::copy_n(&vec[100000], 1000, std::back_inserter(newVector));
std::vector newVector;
新向量保留区(1000);
std::copy_n(&vec[100000],1000,std::back_inserter(newVector));
也应该是O(N)
您可以将此与顶级anwer代码结合使用
vector<T>::const_iterator first = myVec.begin() + 100000;
vector<T>::const_iterator last = myVec.begin() + 101000;
std::copy(first, last, std::back_inserter(newVector));
vector::const_iterator first=myVec.begin()+100000;
vector::const_iterator last=myVec.begin()+101000;
std::copy(第一个、最后一个std::back_插入器(newVector));
您可以使用insert
vector<type> myVec { n_elements };
vector<type> newVec;
newVec.insert(newVec.begin(), myVec.begin() + X, myVec.begin() + Y);
向量myVec{n_元素};
向量newVec;
newVec.insert(newVec.begin(),myVec.begin()+X,myVec.begin()+Y);
vector<type> myVec { n_elements };
vector<type> newVec;
newVec.insert(newVec.begin(), myVec.begin() + X, myVec.begin() + Y);
Big vector: 5;12;4;6;7;8;9;9;31;1;1;5;76;78;8;
Subvector: 6;7;8;9;9;31;1;1;5;76;