是否有用于存储离散间隔的集合?

时间:2019-04-12 07:31:24

标签: c++ algorithm stl

我需要将离散范围存储在集合中,并在插入时加入相邻范围。 STL中是否有已经具有这种功能的结构?

我尝试了boost :: intervals,但是它很沉重,对我想做的事情来说有点过分。

例如,假设集合为空,并插入以下元素:

[64, 96]
[0, 4]
[11, 15]
[5, 10]

间隔设置的预期内容应如下:

[0, 15]
[64, 96]

2 个答案:

答案 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)