[英]What is the fastest way to get the frequency of numbers in an array in C++?
我的方法创建了一个 std::map<int, int> 并通过遍历数组一次来用数字及其频率填充它,但我想知道是否有更快的方法而不使用 map。
std::unordered_map<int,int>
也可以计算频率,但其operator[]
具有复杂性( cppreference ):
平均情况:恒定,最坏情况:大小呈线性。
相比
容器大小的对数。
带有std::map
。
当最大数较小时,可以使用数组,直接计数:
for (const auto& number : array) counter[number]++;
诚然,这一切都已经在评论中说了,所以我还要补充一点:你需要衡量。 复杂性仅与渐近运行时有关,而对于给定的输入大小, std::map
实际上可以更快。
注意: ValueType, DifferenceType
被定义为
template <std::input_iterator I>
using ValueType = typename std::iterator_traits<I>::value_type;
template <std::input_iterator I>
using
DifferenceType = typename std::iterator_traits<I>::difference_type;
如果数组是sorted
,您可以使用std::equal_range
来查找等于x
的元素范围。 使用您编写的概念:
// I2 is homomorphic to std::pair<I, unsigned>
// [first, last) is partially ordered with respect to I::value_type
// return value is d_first + |{x | x in [first, last)}|
// R is a relation over I, compare element using R
template <std::random_access_iterator I, std::forward_iterator I2,
std::relation<bool, ValueType<I>> R = std::less<ValueType<I>>>
requires(std::regular<ValueType<I>> &&
std::is_constructible_v<ValueType<I2>, I, DifferenceType<I>>)
I2 frequency_sorted(I first, I last, I2 d_first, R r = R())
{
while(first != last)
{
auto [left, right] = std::equal_range(first, last, *first, r);
*d_first = {left, std::distance(left, right)};
++d_first;
first = right;
}
return d_first;
}
如果您的资源有限,您可以截断结果并拥有:
// I2 is homomorphic to std::pair<I, unsigned>
// [first, last) is partially ordered with respect to I::value_type
// return value is a pair, where the first element is
// the starting point of subsequence [first, last) where such
// subsequence is unevaluated
// the second element is
// - d_last if |{x | x in [first, last)}| >= d_last - d_first
// - d_first + |{x | x in [first, last)}| if otherwise
template <std::random_access_iterator I, std::forward_iterator I2,
std::relation<bool, ValueType<I>> R = std::less<ValueType<I>>>
requires(std::regular<ValueType<I>> &&
std::is_constructible_v<ValueType<I2>, I, DifferenceType<I>>)
std::pair<I, I2>
frequency_sorted_truncate(I first, I last, I2 d_first, I2 d_last, R r = R())
{
while(first != last && d_first != d_last)
{
auto [left, right] = std::equal_range(first, last, *first, r);
*d_first = {left, std::distance(left, right)};
++d_first;
first = right;
}
return {first, d_first};
}
这两个函数允许你传入任何关系,默认比较使用operator<
。
如果您的数组未排序,并且数组的大小足够大,那么对数组进行排序并使用算法可能是个好主意。 散列可能很诱人,但它会造成缓存未命中,并且可能不如您预期的那么快。 两种方法你都可以试试看哪一种比较快,欢迎告诉我结果。
我的编译器版本是g++ 11.2.11
,我认为代码可以用C++ 20
编译器编译。 如果您没有,只需将概念部分替换为typename
,我认为这样做您只需要一个C++ 17
编译器(由于结构绑定)。
请告诉我是否可以改进我的代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.