![](/img/trans.png)
[英]using lower_bound or upper_bound on Structure in C++
[英]C++ map lower_bound/upper_bound
我了解map
中C++
的底层数据结构是一个自平衡二叉搜索树。 由于在这些数据结构中,找到键的下限和上限有很多用途,您可能会认为 map 的 lower_bound 和 upper_bound 函数将为您提供这种能力。 令人遗憾的是,这些功能无法实现这一点。 有谁知道为什么 lower_bound 的行为方式如此? (它为您提供不在给定密钥之前的密钥)。
这不仅在 map 中。 它位于 STL 中。
您的x
的lower_bound
找到x <= y
y
和上upper_bound
x < y
。
自从 SGI 推出 STL 之前,我就一直在使用 C++,并且由于某种原因仍然设法弄乱了使用这些方法,包括在将它们呈现给 ZA2F2ED4F8EBC2CABBB4C21A2DC 时甚至让自己感到尴尬。 我认为我的问题是:
这些名称在数学中已经具有直观但不同的含义。 鉴于数学含义,在一个大集合或 map 中, upper_bound
和lower_bound
实际上是相同或相邻的元素似乎很奇怪。
“upper_bound”和“lower_bound”这两个名字听起来好像两者之间存在某种对称性,但绝对没有。 如果名称类似于lower_bound 的least_ge
(最小大于或等于)和upper_bound 的least_gt
(最小大于),我会轻松得多。
如果有人有助记符或逻辑使这些易于内化,请分享。 否则,感觉就像他们写了两个有用的函数,但使用了两个随机的数学术语来命名这些函数,无法从名称中推导出语义。 到那时,为什么不使用像egptr
和pbase
这样的虚构名称呢? 我的意思是至少我没有任何预先存在的直觉来克服streambuf
方法的名称......
无论如何,我认为这是您必须记住的基本规则:
lower_bound(X)
返回满足v >= X
的最低元素v
upper_bound(X)
返回满足v > X
的最低元素v
要遍历半开区间 [L,H),从lower_bound(L)
开始并在(不处理) lower_bound(H)
处停止。 这通常是您想要的,因为在 C++ 中遍历半开区间是最常见的——例如,[ buf
, buf+nbytes
) 或 [ 0
, array_size
) 或 [ begin()
, end()
)。
要遍历闭区间 [L,H],从lower_bound(L)
开始,在upper_bound(H)
停止。
要遍历开区间 (L,H),从upper_bound(L)
开始,在lower_bound(H)
停止。
在非空容器中, lower_bound(X)
的镜像是std::prev(upper_bound(X))
, upper_bound(X)
(X) 的镜像是std::prev(lower_bound(X))
。 当然,如果一个元素等于begin()
,那么你不能用std::prev
将它倒退,所以你需要额外的逻辑来处理这个点不能用迭代器值表示的事实。
在多重集/多重映射中,如果该元素确实是v
,则第一个v
是lower_bound(v)
。 如果容器不为空且该元素为v
,则最后一个v
为std::prev(upper_bound(v))
,但请记住在尝试prev
on end()
之前检查容器是否为空。
从通常的数学约定的角度来看, upper_bound
是“最不真实的上界”(永远不相等),而lower_bound
是“最小的上界”(可能相等)。 在通常的数学约定中, lower_bound
实际上是“上限”这一事实可能会导致用户混淆。
一种使lower_bound
/ upper_bound
名称合理化的方法是在另一种称为equal_range
的方法的上下文中考虑它们。 lower_bound
实际上是equal_range
的“lower_bound”,与upper_bound
类似。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.