Поскольку у вас есть неперекрывающиеся интервалы, вы можете использовать std::lower_bound
с настраиваемым компаратором:
template <typename It>
It find_interval(It first, It last, int value) {
// See explanation below.
auto it = std::lower_bound(first, last, value,
[](const std::unique_ptr<interval>& i1, int value) {
return i1->start < value;
});
if (it != last && (*it)->start == value) {
return it;
}
--it;
// Change this to: (*it)->end > value ? it : last
// ...if the upper bound of the interval are not included.
return (*it)->end < value ? last : it;
}
std::lower_bound
найдет первый интервал, который не меньше (т. Е. больше или равен), чем значение. Поскольку мы сравниваем с началом, у нас есть два случая:
- Значение - это начало интервала, и в этом случае будет возвращен сам интервал (first
if
);
- Значение не является началом интервала, и в этом случае будет возвращен следующий интервал, поэтому нам нужно уменьшить
it
(--it
).
Поскольку мы проверяем только начало в std::lower_bound
, нам нужно проверить конец перед возвратом.
std::lower_bound
имеет логарифмическую сложность, и приведенный выше вызов действителен, потому что диапазон [first, last)
упорядочен по отношению к компаратору, который мы предоставляем (лямбда) - я предполагаю, что db
сортируется в соответствии с началом интервалов.
См. http://rextester.com/FBHYH63411 для полной реализации.
Примечание. Если вы не часто вставляете / удаляете интервалы, возможно, вам лучше использовать отсортированный std::vector
.
Изменить: старый ответ. Вероятно, вы не можете использовать std::set::find
, чтобы найти свой интервал, потому что компаратор, который вы используете в db
, сравнивает два interval
, а не interval
и int
, а std::set::find
использует этот компаратор (даже с " фиктивный "интервал, вам понадобится действительное отношение, которое может быть трудно получить).
Либо вам нужно изменить структуру и использовать, например, Interval Tree, чтобы сохранить логарифмическую сложность, либо вы используете неспециализированный std::find
с линейной сложностью:
std::find(db.begin(), db.end(), [n](const std::unique_ptr<interval> &it) {
return it->start < n && n < it->end;
});
person
Holt
schedule
26.09.2016
map
илиunordered_map
, и вы можете легко искать по ключу. Они также обеспечивают логарифмический и амортизированный доступ к постоянному времени соответственно, поэтому вы ничего не теряете, кроме отхода отset
- person AndyG   schedule 26.09.2016unordered_map
, но меня обескуражили из-за того, что у меня будет избыточная информация. диапазон будет указан в ключе, а также в значении, которое является обработчиком - person Hanna Khalil   schedule 27.09.2016