我需要将离散范围存储在集合中,并在插入时加入相邻范围。 STL中是否有已经具有这种功能的结构?
我尝试了boost :: intervals,但是它很沉重,对我想做的事情来说有点过分。
例如,假设集合为空,并插入以下元素:
[64, 96]
[0, 4]
[11, 15]
[5, 10]
间隔设置的预期内容应如下:
[0, 15]
[64, 96]
答案 0 :(得分:3)
这是一个众所周知的问题。有wikipedia page条关于您问题的可能解决方案。当然,在C ++ STL中,您可以使用std::map
来实现基于朴素方法的解决方案(如维基百科所述),因为地图是一棵红黑树,它是一种二叉搜索树。
答案 1 :(得分:2)
要合并间隔(如果它们彼此相邻),这一事实使您的任务比建议的间隔树方法容易得多。
相反,您可以使用Some programmer dude
提出的数据结构,并快速推出自己的实现。在这里,我提供了一种可能的实现方式:
class IntervalSet {
std::map<int, int> _intervals;
public:
void Add(int smaller, int bigger) {
const auto next = _intervals.upper_bound(smaller);
if (next != _intervals.cbegin()) {
const auto prev = std::prev(next);
if (next != _intervals.cend() && next->first <= bigger + 1) {
bigger = next->second;
_intervals.erase(next);
}
if (prev->second + 1 >= smaller) {
smaller = prev->first;
_intervals.erase(prev);
}
}
_intervals[smaller] = bigger;
}
const auto& Intervals() const { return _intervals; }
bool IsInsideInterval(int v) const {
const auto suspectNext = _intervals.upper_bound(v);
const auto suspect = std::prev(suspectNext);
return suspect->first <= v && v <= suspect->second;
}
};
小测试:
IntervalSet is;
is.Add(64, 96);
is.Add(0, 4);
is.Add(11, 15);
is.Add(5, 10);
for (const auto p : is.Intervals()) std::cout << "(" << p.first << ", " << p.second << ") ";
(0,15)(64,96)
它也适用于相交的间隔:
IntervalSet is;
is.Add(0, 10);
is.Add(5, 15);
is.Add(10, 20);
for (const auto p : is.Intervals()) std::cout << "(" << p.first << ", " << p.second << ") ";
(0,20)