【问题标题】:Returning the greatest key strictly less than the given key in a C++ Map在 C++ 映射中返回严格小于给定键的最大键
【发布时间】:2010-10-06 12:02:26
【问题描述】:

C++ STL Maps 有没有办法支持这一点,因为地图上的 lower_bound 和 upper_bound 严格返回大于传递值的值。

Lower key

用例我有一个以时间为键的地图,所以在地图中

time t1   = value1
time t2   = value2
time t2.5 = value3

在这种情况下,如果我传递给这个 MAP t2.3,那么它应该给我 value2。是否在地图上做一个 lower_bound 并返回一个等同于“返回最大键严格小于给定键”的元素,即

iterator = map.upper_bound(2.3)
and then 
iterator--;

【问题讨论】:

    标签: c++ stl


    【解决方案1】:

    如果你不关心排序,你可以使用 map::upper_bound 来获取你想要的元素,但是你需要为 traits 参数定义带有 std::greater 的 map 类,以便排序是从高到低。

    typedef std::map<double,MyClass,std::greater<double> > MyMap;
    MyMap myMap;
    myMap[1.5] = value1;
    myMap[2.0] = value2;
    myMap[3.0] = value3;
    
    MyMap::iterator elt = myMap.upper_bound(2.5); // should be pair(2.0,value2)
    

    【讨论】:

      【解决方案2】:

      我会将 std::find_if() 与反向迭代器一起使用,例如:

      find_if( map.rbegin(), map.rend(), is_less_than );
      

      您必须定义 is_less_than() 谓词函数。

      (参见http://www.cplusplus.com/reference/algorithm/find_if.html

      【讨论】:

      • 这是 O(n) 操作。
      【解决方案3】:

      是的,lower_bound 可以用来做这个,我以前见过它,并且是这样使用的。

      map_type::iterator it = map.lower_bound(2.3);
      if(it != map.begin()) {
          --it;
          // it now points at the right element
      }
      

      实际上会返回最大但更小的(如果 != map.begin() 为真)一个。如果它位于 .begin,则没有更小的键。 cmets 的好主意是返回 .end 如果没有更少的元素并将这些东西打包到一个函数中:

      template<typename Map> typename Map::const_iterator 
      greatest_less(Map const& m, typename Map::key_type const& k) {
          typename Map::const_iterator it = m.lower_bound(k);
          if(it != m.begin()) {
              return --it;
          }
          return m.end();
      }
      
      template<typename Map> typename Map::iterator 
      greatest_less(Map & m, typename Map::key_type const& k) {
          typename Map::iterator it = m.lower_bound(k);
          if(it != m.begin()) {
              return --it;
          }
          return m.end();
      }
      

      该模板也应该适用于std::set

      【讨论】:

      • 我想你会想返回 end() 作为一个信号,如果你要将它打包到一个函数中,那么 lower_bound() 返回 begin() (听起来像 OP 正在做的事情做)
      • 为什么他们不直接实现这个函数,而不是给我们两个几乎完全一样的函数呢?事实上,如果键不存在,lower_bound 是一个完全误导性的名称
      【解决方案4】:

      您的方法可以使用,但您需要检查以确保您没有回到地图的开头。另外你需要lower_bound,而不是upper_bound。

      iterator = map.lower_bound(2.3)
      if (iterator != map.begin())
          --iterator;
      

      【讨论】:

        【解决方案5】:

        我总是发现计算 floor(x) 和 ceil(x) 非常有用

        floor(x) -> greatest element <=x 
        ceil(x) -> smallest element >= x
        
        floor_it = m.lower_bound(x); 
        if (floor_it != m.end() && floor_it->first != x)
              --floor_it;
        
        ceil_it = m.upper_bound(x);
        if (ceil_it != m.end() && (ceil_it-1)->first == x)
            --ceil_it; 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-07-10
          • 2021-10-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-01-29
          相关资源
          最近更新 更多