C ++ std :: binary_search()和std :: lower_bound()组合是否意味着我正在进行两次二进制搜索?

时间:2014-11-16 01:36:49

标签: c++ c++11 vector iterator binary-search

在我使用二进制搜索在向量中快速查找元素的搜索中,我找到了std :: binary_search函数但后来意识到它只返回一个bool,这让我很沮丧。

但后来我发现以这种方式查找元素的最常见解决方案是将binary_search()与lower_bound()配对。在仔细观察之后,我认为lower_bound()也使用二进制搜索esque情况搜索元素。那么,这并不意味着我要两次搜索它吗?

这是我所指的一个例子:     std :: vector haystack {1,3,4,5,9};     int needle = 5;

if (std::binary_search(haystack.begin(), haystack.end(), needle)) {
    std::cout << "Found " << needle << '\n';

    std::vector<int>::iterator it = lower_bound(haystack.begin(), haystack.end(), needle);

    int result = *it;

    cout << "Result " << result << endl;
}

我只是以错误的方式做这件事吗?还有另一种方法可以在向量中二进制搜索并找到实际找到的元素吗?

2 个答案:

答案 0 :(得分:4)

是的,您正在进行两次二进制搜索。只需使用lower_bound一次进行额外比较:

auto it = std::lower_bound(haystack.begin(), haystack.end(), needle);
if (it != haystack.end() && *it == needle) {
    // found it, here.
}

但只有在需要迭代器时才这样做。如果您只是想检查是否存在needle,我会使用std::binary_search()来提高您的用户的清晰度。从lower_bound开始,可以很好地实现这一点。来自cppreference

template<class ForwardIt, class T>
bool binary_search(ForwardIt first, ForwardIt last, const T& value)
{
    first = std::lower_bound(first, last, value);
    return (!(first == last) && !(value < *first));
}

答案 1 :(得分:1)

是的,这是重复的工作。即使您不确定元素是否在集合中,您也可以使用std::lower_bound;如果不是,它将返回结束迭代器。因此,您可以使用以下内容:

auto it = lower_bound(haystack.begin(), haystack.end(), needle);
if (it != haystack.end() && *it == needle) {
    cout << "Found " << needle << '\n';
    cout << "Result " << *it << '\n';
}

假设needle在大海捞针中。那么肯定needle将是第一个不小于needle的元素,所以你会发现它。

如果大约中没有needle且所有元素都小于needle,那么将返回结束迭代器并且it != haystack.end()检查将失败。

如果有一个小于needle的元素,则会返回一个迭代器it,但检查*it == needle将失败。

无论哪种方式,您都可以获得所需的结果。