我可以使用Boost interval_map来做到这一点吗?

时间:2011-11-02 02:14:02

标签: c++ algorithm boost data-structures boost-icl

我想要做的是有效地处理间隔。例如,在我的示例中,间隔如下所示:

[10, 20], [15, 25], [40, 100], [5, 14]

间隔是关闭的和整数,有些间隔可能会过度。我想找到给定查询的重叠间隔有效。例如,如果给出[16, 22]

[10, 20], [15, 25]

上述间隔应按计算间隔计算。

我目前正在编写一个基于红黑树的区间树(参考:CLRS,算法简介)。虽然找到所有重叠间隔可以是O(n),但运行时间应该更快。请注意,可以删除并插入间隔。


但是,我刚发现Boost有interval_mapinterval_sethttp://www.boost.org/doc/libs/1_46_1/libs/icl/doc/html/index.html

我试过了,但这种行为对我来说很奇怪。例如,如果先插入[2, 7],然后插入[3, 8],则生成的地图将包含[2, 3)[3, 7](7, 8]。也就是说,当插入新的间隔时,会自动完成分割。

我可以关闭此功能吗?或者,Boost的interval_map适合我的目的?

3 个答案:

答案 0 :(得分:4)

您要求的数据结构可以有效地找到重叠。这样做,通过在数据结构中存储重叠。现在你似乎在抱怨它已经这样做了。

这个例子解释了逻辑:

typedef std::set<string> guests;
interval_map<time, guests> party;
party += make_pair(interval<time>::right_open(time("20:00"), time("22:00")),
guests("Mary"));
party += make_pair(interval<time>::right_open(time("21:00"), time("23:00")),
guests("Harry")); 
// party now contains
[20:00, 21:00)->{"Mary"} 
[21:00, 22:00)->{"Harry","Mary"} //guest sets aggregated on overlap
[22:00, 23:00)->{"Harry"}

添加两个重叠间隔时,实际上会创建三个具有不同属性的间隔。重叠在两个原始间隔中,使其与原始间隔中的任一个具有逻辑上不同的间隔。现在,两个原始区间跨越了具有不同属性的时间(一些与原始区域重叠,一些不与原始区域重叠)。这种分裂使得查找重叠变得高效,因为它们是地图中它们自己的间隔。

无论如何,Boost允许您选择interval combining style。因此,如果您想强制使用更难找到重叠的结构,您可以这样做。

答案 1 :(得分:1)

我认为你可以使用interval_map<int, set<discrete_interval<int> > >。每当您想要添加时间间隔I时,只需将make_pair(I, II)添加到地图中,其中II是仅包含set的{​​{1}}。因此,对于上面的示例,您可以这样做:

I

请注意,强化文档表明#include <iostream> #include <boost/icl/interval_map.hpp> using namespace boost::icl; typedef std::set<discrete_interval<int> > intervals; intervals singleton(const discrete_interval<int> &value) { intervals result = { value }; return result; } int main() { interval_map<int, intervals> mymap; discrete_interval<int> i1 = discrete_interval<int>(2, 7); discrete_interval<int> i2 = discrete_interval<int>(3, 8); mymap.add(make_pair(i1, singleton(i1))); mymap.add(make_pair(i2, singleton(i2))); for (int i = 0; i < 10; ++i) { std::cout << "i: " << i << ", intervals: " << mymap(i) << std::endl; } } interval_map std::set std::set的效率不高,位于this page的底部。因此,这表明您可能希望编写自己的集合概念实现,或者使用与{{1}}不同的实现。

答案 2 :(得分:1)

我尝试了boost interval_map和interval_set。它们效率很低。设置成本非常高,因为实现基本上将每个子区间(交集)映射到包含它的所有区间。

我认为基于红黑树的CLRS“算法简介”中的实现要好得多。奇怪的是,即使std :: set和std :: map基于RB树,也没有允许扩充的红黑树实现。