Подтвердить что ты не робот

Возврат наибольшего ключа строго меньше заданного ключа на карте С++

Есть ли способ, которым поддерживают С++ STL Maps, поскольку lower_bound и upper_bound на картах строго возвращают значение, большее, чем переданное значение.

Нижний ключ

Случай использования У меня есть карта со временем как ключи отсортированным образом, поэтому в MAP

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

В этом случае, если я перехожу к этому MAP t2.3, тогда он должен дать мне значение2. Делает меньшее значение на карте и возвращает один элемент, эквивалентный "возвращающемуся наибольшему ключу строго меньше заданного ключа" i.e

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

Ответ 1

Да, для этого можно использовать 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() было true). Если он был на .begin, тогда нет меньшего ключа. Хорошая идея из комментариев - вернуть .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.

Ответ 2

Если вы не заботитесь о заказе, вы можете использовать map:: upper_bound для получения нужного элемента, но вам нужно определить класс карты с помощью std:: больше для аргумента признаков, так что порядок высокого к низкому.

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)

Ответ 3

Ваш метод будет работать, но вам нужно проверить, чтобы вы не вернулись к началу карты. Кроме того, вам нужно lower_bound, а не upper_bound.

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

Ответ 4

Я бы использовал std:: find_if() с обратными итераторами, что-то вроде:

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

Вам нужно определить функцию предиката is_less_than().

(cf. http://www.cplusplus.com/reference/algorithm/find_if.html)

Ответ 5

Я всегда нахожу, чтобы вычислять пол (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;