Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/azure/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从向量中提取子向量的最佳方法?_C++_Stl_Vector_Range - Fatal编程技术网

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;