【问题标题】:C++ map lower_bound/upper_boundC++映射lower_bound/upper_bound
【发布时间】:2020-04-13 17:29:24
【问题描述】:

我了解C++map 的底层数据结构是一个自平衡二叉搜索树。由于在这些数据结构中,找到键的下限和上限有很多用途,您会认为 map lower_bound 和 upper_bound 函数将为您提供这种能力。令人遗憾的是,这些功能无法实现这一点。 有谁知道为什么 lower_bound 的行为方式如此? (它为您提供不在给定密钥之前的密钥)。

【问题讨论】:

  • 确认你的期望...std::prev(m.lower_bound(key))(忽略绑定检查)。
  • 因为这就是数学中上下界的工作方式? en.wikipedia.org/wiki/Upper_and_lower_bounds
  • 我不认为数学定义在这里有很大的相关性。但不想陷入那种讨论。我的主要观点是,我有很多用法可以找到具有最大键的元素,小于给定键。现在的情况是,我必须找到 lower_bound 并反向迭代才能找到它。

标签: c++ dictionary lower-bound


【解决方案1】:

在 SGI 甚至引入 STL 之前,我就一直在使用 C++,但由于某种原因,我仍然设法搞砸了使用这些方法,包括在向班级展示它们时甚至让自己感到尴尬。我认为我的问题是:

  1. 这些名称在数学中已经具有直观但不同的含义。考虑到数学含义,在一个大集合或映射中,upper_boundlower_bound 实际上是相同或相邻的元素似乎很奇怪。

  2. “upper_bound”和“lower_bound”这两个名字听起来像是在两者之间存在某种对称性,而实际上完全没有。如果名称类似于 least_ge(最小大于或等于)用于 lower_bound,least_gt(最小大于)用于上界。

如果有人有助记符或逻辑使这些易于内化,请分享。否则,感觉就像他们写了两个有用的函数,但使用了两个随机的数学术语来命名这些函数,无法从名称中推导出语义。到那时,为什么不使用像egptrpbase 这样的虚构名称呢?我的意思是,对于streambuf 方法的名称,我至少没有任何预先存在的直觉可以克服......

无论如何,我认为这是您必须记住的基本规则:

  • lower_bound(X) 返回最低元素v 使得v >= X

  • upper_bound(X) 返回最低元素v 使得v > X

  • 要遍历半开区间 [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)的镜像为std::prev(lower_bound(X))。当然,如果一个元素等于begin(),那么你不能用std::prev将它倒退,所以你需要额外的逻辑来处理这个点不能用迭代器值表示的事实。

  • 在多重集/多重映射中,第一个 vlower_bound(v),如果该元素确实是 v。如果容器不为空且该元素为v,则最后一个vstd::prev(upper_bound(v)),但请记住在尝试prev end() 之前检查容器是否为空。

【讨论】:

    【解决方案2】:

    这不仅在地图上。它在 STL 中。

    lower_bound 为您的x 找到这样的yx <= y。还有upper_boundx < y

    【讨论】:

    • 是的,不太清楚那有什么用。我希望能够提供一个密钥并找到比给定密钥小的最大密钥。 Map 被实现为 RB-Tree 更加证明了这个特性。
    【解决方案3】:

    从通常的数学约定的角度来看,upper_bound 是“最小的真正上界”(永远不相等),lower_bound 是“最小的上界”(可能相等)。 lower_bound 实际上是通常数学约定中的“上限”这一事实可能会引起用户的混淆。

    一种使lower_bound/upper_bound 名称合理化的方法是在称为equal_range 的另一种方法的上下文中考虑它们。 lower_bound 实际上是 equal_range 的“下界”,类似于 upper_bound

    【讨论】:

      猜你喜欢
      • 2021-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-26
      • 1970-01-01
      相关资源
      最近更新 更多