二进制搜索相当于`find_if`

时间:2014-11-23 20:40:51

标签: c++ stl stl-algorithm

假设一个容器(在本例中是一个普通数组)存储像

这样的元素
struct Foo
    {
    char id[8];
    // other members
    };

现在我想找到一个Foo,其ID以特定字符串S开头。由于数组按id排序,我想使用二进制搜索,所以我寻找一个使用与find_if相同的接口执行二进制搜索的函数。在STL中是否有这样的函数,可以使用algorithm中的其他元素构造,还是我需要自己实现它。

2 个答案:

答案 0 :(得分:7)

您正在寻找std::lower_boundstd::upper_boundstd::equal_range,其中包含输入范围,搜索值和可选比较器,并要求根据比较器对范围进行排序。 / p>

对于您的具体示例,我将std::lexicographical_compare用于比较器:

#include <algorithm>
#include <iterator>

struct IdCmp
{
  bool operator()(const Foo & lhs, const Foo & rhs) const
  {
    return std::lexicographical_compare(std::begin(lhs.id), std::end(lhs.id),
                                        std::begin(rhs.id), std::end(rhs.id));
  }
};

int main()
{
  Foo a[100];           // populate
  Foo b = make_needle();

  auto p = std::equal_range(std::begin(a), std::end(a), b, IdCmp());

  /* The elements with key equal to that of b are in [p.first, p.second). */
}

如果您希望能够直接搜索字符串,那么您的比较器需要使用一个Foo参数和一个字符串参数进行异构调用。例如:

struct IdCmp
{
  bool operator()(const Foo & lhs, const Foo & rhs) const
  {
    return std::lexicographical_compare(std::begin(lhs.id), std::end(lhs.id),
                                        std::begin(rhs.id), std::end(rhs.id));
  }

  bool operator()(const Foo & lhs, const char * id) const
  {
    return std::lexicographical_compare(std::begin(lhs.id), std::end(lhs.id),
                                        id, id + 8);
  }

  bool operator()(const char * id, const Foo & rhs) const
  {
    return std::lexicographical_compare(id, id + 8,
                                        std::begin(rhs.id), std::end(rhs.id));
  }
};

现在你可以搜索:

std::lower_bound(std::begin(a), std::end(a), "ABCD1234", IdCmp())

答案 1 :(得分:1)

我相信您正在寻找std::binary_searchstd::lower_bound