如果有任何STL算法产生与以下代码相同的结果,我就会徘徊:
std::vector<int> data;
std::vector<int> counter(N); //I know in advance that all values in data
//are between 0 and N-1
for(int i=0; i<data.size(); ++i)
counter[data[i]]++;
此代码只输出整数数据的直方图,预定义的bin大小等于1。
我知道我应该尽可能地避免循环,因为STL算法的等价物比大多数C ++程序员可能提出的要好得多。
有什么建议吗?
提前谢谢你,朱塞佩
答案 0 :(得分:3)
嗯,你当然至少可以清理一下循环:
for (auto i : data)
++count[i];
你可以(例如)改为使用std::for_each
:
std::for_each(data.begin(), data.end(), [&count](int i) { ++count[i]; });
......但这对我来说并没有太大的改善(如果有的话)。
答案 1 :(得分:1)
我认为没有更有效的方法。在大多数情况下,你是正确的避免循环和偏好STL,但这只适用于更大,更复杂的循环,这些循环更难编写和维护,因此可能不是最佳的。
在程序集级别查看问题,计算此问题的唯一方法就是在示例中使用它的方式。由于C / C ++循环非常有效地转换为汇编而没有不必要的开销,这使我相信没有STL函数可以比您的算法更快地执行此操作。
有一个名为count的STL函数,但它的复杂性是线性的(O(n)),因此也就是你的解决方案。
如果你真的想挤出每个CPU周期的最大值,那么考虑使用C风格的数组和一个单独的计数器变量。向量引入的开销几乎不可测量,但如果有的话,这是我在这里看到优化的唯一机会。不是我会建议它,但我担心这是你能让头发更快速的唯一方法。
答案 2 :(得分:0)
如果你考虑一下,为了计算向量中元素的出现次数,每个元素必须至少被“访问”一次,没有避免它。
像这样的简单循环已经是最有效的。您可以尝试展开它,但这可能是您可以做的最好的。 STL与否,我怀疑是否有更好的算法。
答案 3 :(得分:0)
您可以使用for_each和一个lambda函数。检查此示例:
#include <algorithm>
#include <vector>
#include <ctime>
#include <iostream>
const int N = 10;
using namespace std;
int main()
{
srand(time(0));
std::vector<int> counter(N);
std::vector<int> data(N);
generate(data.begin(),data.end(),[]{return rand()%N;});
for (int i = 0;i<N;i++)
cout<<data[i]<<endl;
cout<<endl;
for_each(data.begin(),data.end(),[&counter](int i){++counter[i];});
for (int i = 0;i<N;i++)
cout<<counter[i]<<endl;
}