对于任何已排序的容器(即map、set、multimap 和 multiset),我们知道以下内容:
-
lower_bound(key) 返回第一个条目 >= key
-
upper_bound(key) 返回第一个条目 > key
如果没有条目,每个函数也会返回end() >= /> key。
所以我们有基于运算符 > 和 >= 的功能。我们可能会问,我们是否也可以拥有基于
要求第一个条目 key 有点微不足道(这是 begin() 或不在容器中)。然而,要求是最后一个这样的条目是有意义的。确实,您所要求的是最后一个条目key。
为了完整起见,我们也会考虑最后一个条目 key。
假设我们有这样的函数,如果没有这样的入口,它们应该怎么做?我们也可以比返回end() 做得更糟——它是一个可测试的值,与任何成功案例都不同。它也与lower_bound、upper_bound 和find 以及<algorithm> 标头中的大量独立搜索功能一致。底线是end() 通常用于表示“没有这样的条目”,所以这对我们来说也应该足够好了。
正如 Barry 和 Mark 所指出的,调用 lower_bound(key) 然后递减会得到我们想要的,除非 lower_bound(key) == begin()。在这种情况下,第一个(因此是 [joint-] 最小的)条目 >= key,因此没有条目 key - 正是我们刚才说我们应该返回 end() 的场景。
对于查找最后一个条目 key 的情况,我们可以做同样的事情,但使用 upper_bound,当 upper_bound(key) == begin() 时再次返回 end() 表示“没有这样的条目”。
让我们分别调用这些函数lower_bound_dec 和upper_bound_dec:
// Find the last entry < key, returning end() if all entries are >= key
// Container can be any that implements lower_bound, e.g. std::map, std::multimap, std::set or std::multiset
template<typename Container, typename Key>
typename Container::const_iterator lower_bound_dec(const Container &container, const Key &key) {
auto it = container.lower_bound(key);
if (it == std::begin(container))
it = std::end(container);
else
--it;
return it;
}
// Find the last entry <= key, returning end() if all entries are > key
// Container can be any that implements upper_bound, e.g. std::map, std::multimap, std::set or std::multiset
template<typename Container, typename Key>
typename Container::const_iterator upper_bound_dec(const Container &container, const Key &key) {
auto it = container.upper_bound(key);
if (it == std::begin(container))
it = std::end(container);
else
--it;
return it;
}
我们还可以定义基于迭代器的函数,它镜像std::lower_bound 和std::upper_bound,并且可以使用双向 迭代器对任何排序范围进行操作:
// Find the last entry < key, returning end() if all entries are >= key
// last must be reachable from first, and all entries in sorted order between them
template<typename Iterator, typename Key>
Iterator lower_bound_dec(Iterator first, Iterator last, const Key &key) {
auto it = container.lower_bound(first, last, key);
if (it == first)
it = last;
else
--it; // requires bidirectional iterators
return it;
}
upper_bound(first, last, key) 和带有比较器的表格作为练习留给读者/任何想通过编辑获得代表的人! :)
TL/DR:
使用 lower_bound 然后递减,需要注意的是“递减”begin() 会产生 end() 表示“没有这样的条目”。