当前位置:  开发笔记 > 编程语言 > 正文

从向量中提取子向量的最佳方法?

如何解决《从向量中提取子向量的最佳方法?》经验,为你挑选了6个好方法。

假设我有一个std::vector(让我们称之为myVec)大小N.构造由元素X到Y的副本组成的新向量的最简单方法是什么,其中0 <= X <= Y <= N-1?例如,myVec [100000]通过myVec [100999]大小的向量150000.

如果使用向量无法有效地完成此操作,是否应该使用另一种STL数据类型?



1> Greg Rogers..:
vector::const_iterator first = myVec.begin() + 100000;
vector::const_iterator last = myVec.begin() + 101000;
vector newVec(first, last);

这是构造新向量的O(N)操作,但实际上并没有更好的方法.


@orip嗯,那么它毕竟是O(N).
@GregRogers:使用big-O表示法是没有意义的,其中N是一个特定的数字.Big-O传达了N的变化速度.约翰:最好不要以两种方式使用一个变量名.我们通常会说"O(YX)",或者我们说"O(Z),其中Z = YX".
为什么不只是`vector newVec(myVec.begin()+ 100000,myVec.begin()+ 101000);`?
+1,也是O(YX),小于或等于O(N)(在他的例子中少得多)
@GregRogers通过这种方式,我们需要声明一个新的向量.有没有办法改变原始矢量?像myVec(第一个,最后一个)?我知道这是错的,但我真的需要解决方案,因为我想在我的代码中使用递归,并且需要重复使用相同的向量(虽然已更改).谢谢!

2> Martin York..:

只需使用向量构造函数.

std::vector   data();
// Load Z elements into data so that Z > Y > X

std::vector   sub(&data[100000],&data[101000]);


@j_random_hacker:抱歉,不得不反对.std :: vector的STL规范已明确更改为支持此类过程.指针也是有效的迭代器类型.查找iterator_traits <>
获取这些向量元素的地址是一个不可移植的hack,如果向量存储实际上不是连续的,它将会中断.使用begin()+ 100000等.
@ taktak004不.请记住`operator []`返回一个引用.只有在您读取或写入引用时才会成为访问冲突.既然我们都没有,而是得到了我们没有调用UB的地址.
好的,我没有意识到从任意向量元素中获得迭代器是如此简单。
我的坏,显然标准保证了矢量存储是连续的.然而,使用这样的地址是不好的做法,因为它肯定不能保证适用于支持随机访问的所有容器,而begin()+ 100000则是.

3> Anteru..:

std::vector(input_iterator, input_iterator),在您的情况下foo = std::vector(myVec.begin () + 100000, myVec.begin () + 150000);,请参见此处


是的,当然,但是你输入std :: vector foo = std :: vector(...)或std :: vector foo(...)应该无关紧要.

4> einpoklum - ..:

这几天,我们用spans!所以你会写:

#include 

...
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);

得到1000个与myvecs 相同类型的元素.现在,这不是副本,它只是向量中的数据视图,所以要小心.如果你想要一个实际的副本,你可以这样做:

std::vector new_vec(my_subspan.cbegin(), my_subspan.cend());

笔记:

随着C++ 20你会用gslgsl,而不是gsl.

有关跨距的更多信息,请参阅:什么是"跨度"以及何时应该使用跨度?



5> Eclipse..:

如果两者都不会被修改(不添加/删除项目-修改现有的罚款,只要你留意线程问题),你可以简单地绕过data.begin() + 100000data.begin() + 101000,假装他们是begin()end()一个较小的载体.

或者,由于矢量存储保证是连续的,您可以简单地传递1000个项目数组:

T *arrayOfT = &data[0] + 100000;
size_t arrayOfTLength = 1000;

这两种技术都需要持续时间,但要求数据长度不会增加,从而触发重新分配.



6> MasterHD..:

你没有提到什么类型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 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


我想知道是否使用-O3,@ Anteru的"使用构造函数"`std :: vector(myVec.begin()+ 100000,myVec.begin()+ 150000);`,这个产品的较长版本不会准确同样的集会?
推荐阅读
我我檬檬我我186
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有