有三个原因:

  • 它更快:排序的容器,所有方法都受益于排序集合的快速对数搜索。此外,std::string方法实现了最优算法。

  • 它更自然:std::mapstd::multimap方法可以直接搜索键,而不像算法必须查找std::pair<key,Value>,因为它们的迭代器可以直接指向。

  • 它在某些情况下更正确:在排序容器(如mapset)中,所有方法都使用等价而不是相等,而某些算法(如std::countstd::find使用相等)则不是这样。

现在究如何把它应用到 STL 提供的各种容器来深入了解更多细节。

std::vector, std::deque, std::list 这些容器没有公开任何与搜索相关的方法,只能通过算法来搜索。

二、std::map/multimap, std::set/multiset

这些容器有5个类方法,它们跟一些算法共享它们的名称:countfindequal_rangelower_boundupper_bound

这些方法和算法的比较:

容器方法

比算法更正确?

比算法还快?

比算法更自然?

count

find

equal_range

相同

lower_bound

相同

upper_bound

相同

  • 更好的正确性是因为使用了等效而不是相等。

  • 更好的性能来自于为序列容器对元素进行排序这一事实。对于关联容器来说,这是因为它们的迭代器不是随机访问的,所以算法不能通过直接跳过所需的元素来执行分割(它们必须从头开始并向上移动到它们的位置),而容器的内部没有这种约束。

  • 它们对于映射来说更自然,因为传递给各种方法的参数是一个键,而不是std::pair<key, Value>

注意,没有跟std::binary_search等价的容器方法。检查容器中是否存在一个键:

  • 对于std::mapstd::set:比较find的结果与end迭代器的结果。或者使用count方法。count作为方法不会引起任何性能问题,因为,像find一样,它在第一个与搜索的键相等的键处停止(因为根据std::mapstd::set的定义,只能有一个键与搜索的键相等)。

  • 对于std::multimapstd::multiset:因为count不会在第一个与搜索的键相等的键处停止,所以find在这里比count有优势。

std::multimapstd::multiset中,find方法返回与搜索值相等的任何元素,而不一定是第一个元素。如果确实需要第一个元素,可以使用equal_range,因为它具有简单的接口;或者,如果觉得equal_range太慢(因为它显示了整个范围),而只是需要第一个元素,那么可以使用lower_bound。但是,lower_bound同样也有它的缺点,也必须付出代价。

三、std::string

string实际上有24个搜索方法。分成6组,每组有4个重载。对于所有组,4个重载的形式为:

  • 搜索由std::string给出的字符串。

  • 搜索由char*和size给出的字符串。

  • 搜索由char*给出的字符串(止于null字符)。

  • 搜索一个字符。

并且所有4个重载都以搜索字符串中的起始位置作为参数,默认值为0(从字符串的开头开始搜索)。

更多推荐