要实现非重叠间隔的容器,我定义了以下内容:
set<unique_ptr<interval>> db;
确保定义了非重叠属性:
bool operator<(const unique_ptr<interval>& lhs,
const unique_ptr<interval>& rhs);
interval
类有2个字段:start
,last
,因此我可以确定某些int
是否属于某个interval
实例的范围。
现在我想要在集合中搜索int n
以查找包含它的区间。
我考虑使用unique_ptr<interval> dummy_interval
创建first=last=n
并搜索调用db.find(dummy_interval)
,但问题是类interval
是纯虚拟的,所以我无法创建它的任何实例。
我怎样才能克服这个问题?
答案 0 :(得分:1)
由于您有非重叠间隔,因此可以将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
会找到不小于的第一个区间(即大于或等于)而不是值。由于我们正在与开始进行比较,我们有两种情况:
if
); it
(--it
)。由于我们只检查std::lower_bound
中的开头,我们需要在返回之前检查结束。
std::lower_bound
具有对数复杂度,上述调用有效,因为相对于我们提供的比较器(lambda),范围[first, last)
有序 - 我是假设db
根据间隔的开始进行排序。
有关完整实施的信息,请参阅http://rextester.com/FBHYH63411。
旁注:如果您不经常插入/删除间隔,最好使用已排序的std::vector
。
编辑:旧答案 -
您可能无法使用std::set::find
来查找时间间隔,因为您在db
中使用的比较器会比较两个interval
,而不是interval
和int
,以及{ {1}}使用这个比较器(即使是“虚拟”间隔,你需要一个有效的关系,这可能很难获得)。
您需要更改结构并使用,例如Interval Tree以保持对数复杂度,或者使用非“专用”std::find
线性复杂度:
std::set::find