简体   繁体   English

C++ map lower_bound/upper_bound

[英]C++ map lower_bound/upper_bound

I understand that the underlying data structure for map in C++ is a self-balancing Binary Search Tree.我了解mapC++的底层数据结构是一个自平衡二叉搜索树。 Since in these data structures, finding a lower bound and an upper bound to a key has lots of use, you'd think that map lower_bound, and upper_bound functions will give you that capability.由于在这些数据结构中,找到键的下限和上限有很多用途,您可能会认为 map 的 lower_bound 和 upper_bound 函数将为您提供这种能力。 It's a bummer that these functions don't deliver that.令人遗憾的是,这些功能无法实现这一点。 Does anyone know why lower_bound behaves the way it does?有谁知道为什么 lower_bound 的行为方式如此? (it gives you the key that is NOT BEFORE the given key). (它为您提供不在给定密钥之前的密钥)。

This is not only in the map.这不仅在 map 中。 It is in STL.它位于 STL 中。

lower_bound for your x find such y that x <= y .您的xlower_bound找到x <= y y And the upper_bound x < y .和上upper_bound x < y

I've been using C++ since before SGI even introduced the STL, and for some reason still manage to mess up using these methods, including even embarrassing myself when presenting them to a class.自从 SGI 推出 STL 之前,我就一直在使用 C++,并且由于某种原因仍然设法弄乱了使用这些方法,包括在将它们呈现给 ZA2F2ED4F8EBC2CABBB4C21A2DC 时甚至让自己感到尴尬。 I think my problems are that:我认为我的问题是:

  1. The names already have an intuitive but different meaning in mathematics.这些名称在数学中已经具有直观但不同的含义。 Given the mathematical meanings, it seems weird that in a big set or map, upper_bound and lower_bound are actually the same or adjacent elements.鉴于数学含义,在一个大集合或 map 中, upper_boundlower_bound实际上是相同或相邻的元素似乎很奇怪。

  2. The names "upper_bound" and "lower_bound" sound like there is a some kind of symmetry between the two, when there is absolutely not. “upper_bound”和“lower_bound”这两个名字听起来好像两者之间存在某种对称性,但绝对没有。 I'd have a much easier time if the names were something like least_ge (least greater than or equal to) for lower_bound and least_gt (least greater than) for upper_bound.如果名称类似于lower_bound 的least_ge (最小大于或等于)和upper_bound 的least_gt (最小大于),我会轻松得多。

If someone has a mnemonic or logic to make these easy to internalize, please share it.如果有人有助记符或逻辑使这些易于内化,请分享。 Otherwise, it just feels like they wrote two useful functions but used two random mathematical terms to name those functions, with no way to derive the semantics from the names.否则,感觉就像他们写了两个有用的函数,但使用了两个随机的数学术语来命名这些函数,无法从名称中推导出语义。 At that point, why not use up made up names like egptr and pbase ?到那时,为什么不使用像egptrpbase这样的虚构名称呢? I mean at least I don't have any pre-existing intuitions to overcome about the names of streambuf methods...我的意思是至少我没有任何预先存在的直觉来克服streambuf方法的名称......

At any rate here are what I believe are the basic rules you have to remember:无论如何,我认为这是您必须记住的基本规则:

  • lower_bound(X) returns the lowest element v such that v >= X lower_bound(X)返回满足v >= X的最低元素v

  • upper_bound(X) returns the lowest element v such that v > X upper_bound(X)返回满足v > X的最低元素v

  • To traverse the half-open interval [L,H), start with lower_bound(L) and stop at (don't process) lower_bound(H) .要遍历半开区间 [L,H),从lower_bound(L)开始并在(不处理) lower_bound(H)处停止。 This is usually what you want , because it's most common to traverse half-open intervals in C++--eg, [ buf , buf+nbytes ), or [ 0 , array_size ), or [ begin() , end() ).这通常是您想要的,因为在 C++ 中遍历半开区间是最常见的——例如,[ buf , buf+nbytes ) 或 [ 0 , array_size ) 或 [ begin() , end() )。

  • To traverse the closed interval [L,H], start at lower_bound(L) and stop at upper_bound(H) .要遍历闭区间 [L,H],从lower_bound(L)开始,在upper_bound(H)停止。

  • To traverse the open interval (L,H), start at upper_bound(L) and stop at lower_bound(H) .要遍历开区间 (L,H),从upper_bound(L)开始,在lower_bound(H)停止。

  • In a non-empty container, the mirror image of lower_bound(X) is std::prev(upper_bound(X)) and the mirror image of upper_bound(X) is std::prev(lower_bound(X)) .在非空容器中, lower_bound(X)的镜像是std::prev(upper_bound(X))upper_bound(X) (X) 的镜像是std::prev(lower_bound(X)) Of course, if an element is equal to begin() , then you can't step it backwards with std::prev , so you need extra logic to deal with the fact that this point cannot be represented with an iterator value.当然,如果一个元素等于begin() ,那么你不能用std::prev将它倒退,所以你需要额外的逻辑来处理这个点不能用迭代器值表示的事实。

  • In a multiset/multimap, the first v is lower_bound(v) if that element is indeed v .在多重集/多重映射中,如果该元素确实是v ,则第一个vlower_bound(v) The last v is std::prev(upper_bound(v)) if the container is not empty and that element is v , but remember to check that the container is not empty before attempting prev on end() .如果容器不为空且该元素为v ,则最后一个vstd::prev(upper_bound(v)) ,但请记住在尝试prev on end()之前检查容器是否为空。

From the point view of usual math convention, the upper_bound is the "least true upper-bound" (never equal) and the lower_bound is the "least upper-bound" (could equal).从通常的数学约定的角度来看, upper_bound是“最不真实的上界”(永远不相等),而lower_bound是“最小的上界”(可能相等)。 The fact that lower_bound is actually an "upper-bound" in usual math convention may cause confusion among users.在通常的数学约定中, lower_bound实际上是“上限”这一事实可能会导致用户混淆。

A way to rationalize the name of lower_bound / upper_bound is considering them in the context of another method called equal_range .一种使lower_bound / upper_bound名称合理化的方法是在另一种称为equal_range的方法的上下文中考虑它们。 The lower_bound is really the "lower_bound" of the equal_range , similarly the upper_bound . lower_bound实际上是equal_range的“lower_bound”,与upper_bound类似。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM