std::vector::reserve(未知m),我知道m<<;N(通常)并且知道N
std::vector::reserve( unknown m ), I know that m<<N (usually) and know N
我有一些代码可以处理N
对象,然后根据一些自定义条件,只返回某些m
索引的结果。
这里有一个坚实的例子(查询字符串str
上的所有' '
字符):-
std::vector<int> reports; //will keep index of ' ' in "str"
for(int i=0;i<N;i++){ // str.size() = "N"
bool condition = str.at(i)==' '; //"str" is string #B
if(condition){ //rarely true
reports.push_back(i);
}
}
//now reports.size() = m
在这些块中,我知道m
总是小于或等于N
,并且通常m << N
。
在现实生活中,区块更复杂,但共享类似的算法:-
//int "N" is a local variable, it is not a constant.
std::vector<Input> inputs;
std::vector<Report> reports; //"Report" is any type of result, actually
int outOfLoopVariable=0;
for(int i=0;i<N;i++){
bool condition = some logic #B about "inputs[i]" and "outOfLoopVariable";
outOfLoopVariable= ....; //some complex logic #B
int var1 = ....; //some complex logic #B
//var2, var3, etc.
if(condition){ //rarely true
reports.push_back(Report(i,var1,var2,...));
}
}
原始问题
算法#B
的总复杂度=O(N)
,
但std::vector::push_back
的总复杂程度=
O(m*log(m))
在大多数情况下(当m<<N
时)- 最坏情况下的
O(N*log(N))
(当m~N
时)
正如oLen所指出的,这是完全错误的。然而,我决定把它留作参考
问题
(编辑)算法#B
需要多次重新分配vector
。
问题
如何使上述块的复杂性为O(N)
(编辑,感谢oLen)如何避免不必要的vector
内部预订(1->2->4->…)?
我糟糕的解决方案
多年来,我一直通过以下方法来解决这个问题:-
reports.reserve(N)
在第一个语句中-在大多数情况下,这是一个过度保留
当report
是一个大对象,而N
非常大(profiled,10000+)时,这真的很糟糕- 循环两次。
- 第一个循环确定
m
- 然后是CCD_ 22
- 最后,第二个循环执行实际的
reports.push_back(i);
- 这不方便。代码重复往往会导致轻微的可维护性问题
(可以通过lambda[&]
部分解决,稍微牺牲可读性) - 此外,粗略地说,
#B
的复杂性现在是O(2*n)
- 。。。或者CCD_ 27,如果我可以省略第一个循环的一些计算
- 第一个循环确定
我希望有更好的方法。
答案:只是不要更改代码,也不要使用reserve
。
std::vector::push_back
的复杂度是恒定的(考虑到摊销时间),所以只要使用它就可以了
有第三种方法:使用链表report
。没有超额预订。没有额外的循环。
但速度可能较慢。
相关文章:
- C/C++编译器通常会删除重复的库吗
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 呼叫运营商<<临时
- 如何防止clang格式在流运算符调用之间添加换行符<<
- <<操作员在下面的行中工作
- C++通常的算术转换不转换
- 如何定义自定义生成配置类型,其中通常是.exe的目标改为 DLL
- OpenGL通常"Up"方向?
- 在向量中查找大于 0(或通常为 k)的最小元素的最佳方法是什么?
- 通常使用什么方法来检测时间情况?
- 从 OpenCV 3 切换到 OpenCV 4 会导致网络摄像头以最大 5 fps 的速度录制,而不是通常的 30 f
- 为什么"std::uninitialized_copy"通常取消对未初始化内存的迭代器的引用不是未定
- 为什么智能指针不能用通常的指针方式声明
- 是否有任何 2 补充平台/编译器,其中有符号移位不做通常的事情?
- 如何显式调用运算符<<
- 当迭代器(输入参数)通常不是constexpr时,constexpr算法真的有用吗
- 比较两个std::矢量/阵列,或者通常比较两个stl连续器
- 使用通常称为 API 实现C++多个客户和生产者解决方案,这是否有效?
- 是否可以重用通常的迭代器来构建常量迭代器?
- std::vector::reserve(未知m),我知道m<<;N(通常)并且知道N