到目前为止,我已经将数组存储在向量中,然后循环遍历向量以找到匹配元素,然后返回索引。
在C ++中有更快的方法吗?我用来存储数组的STL结构对我来说并不重要(它不一定是矢量)。我的数组也是唯一的(没有重复元素)和有序(例如,及时的日期列表)。
答案 0 :(得分:7)
由于元素已排序,您可以使用二进制搜索来查找匹配元素。 C ++标准库具有std::lower_bound
算法,可用于此目的。为了清晰和简单,我建议将其包装在您自己的二进制搜索算法中:
/// Performs a binary search for an element
///
/// The range `[first, last)` must be ordered via `comparer`. If `value` is
/// found in the range, an iterator to the first element comparing equal to
/// `value` will be returned; if `value` is not found in the range, `last` is
/// returned.
template <typename RandomAccessIterator, typename Value, typename Comparer>
auto binary_search(RandomAccessIterator const first,
RandomAccessIterator const last,
Value const& value,
Comparer comparer) -> RandomAccessIterator
{
RandomAccessIterator it(std::lower_bound(first, last, value, comparer));
if (it == last || comparer(*it, value) || comparer(value, *it))
return last;
return it;
}
(C ++标准库有一个std::binary_search
,但如果范围包含元素bool
,则返回true
:false
。如果你没有用它想要元素的迭代器。)
一旦你有一个元素的迭代器,你可以使用std::distance
算法来计算范围内元素的索引。
这两种算法同样适用于任何随机访问序列,包括std::vector
和普通数组。
答案 1 :(得分:7)
如果要将值与索引关联并快速查找索引,可以使用std::map
或std::unordered_map
。您还可以将这些与其他数据结构(例如std::list
或std::vector
)结合使用,具体取决于您要对数据执行的其他操作。
例如,在创建矢量时,我们还创建了一个查找表:
vector<int> test(test_size);
unordered_map<int, size_t> lookup;
int value = 0;
for(size_t index = 0; index < test_size; ++index)
{
test[index] = value;
lookup[value] = index;
value += rand()%100+1;
}
现在只需查看索引:
size_t index = lookup[find_value];
使用基于散列表的数据结构(例如unordered_map)是一个相当经典的空间/时间权衡,并且当您需要进行大量查找时,可以胜过执行这种“反向”查找操作的二进制搜索。另一个优点是,当矢量未排序时,它也可以工作。
为了好玩:-)我在VS2012RC中做了一个快速的基准测试,将James的二进制搜索代码与线性搜索进行比较,并使用unordered_map进行查找,所有这些都在一个向量上:
~50000个元素unordered_set显着(x3-4)优于显示预期的O(log N)行为的二分搜索,有点令人惊讶的结果是unordered_map失去了超过10000个元素的O(1)行为,可能是由于哈希冲突,也许是一个实现问题。
编辑:无序映射的max_load_factor()为1,因此不应该发生冲突。二进制搜索和非常大的向量的哈希表之间的性能差异似乎与缓存相关,并且根据基准中的查找模式而变化。
Choosing between std::map and std::unordered_map讨论了有序和无序地图之间的区别。