Is there a collection for storing discrete intervals?

This is a well known question. There is a wikipedia page on possible solutions to your question. Of course in the C++ STL you could implement a solution based on the Naive approach, explained in wikipedia, using a std::map because a map is a Red-Black Tree which is a type of Binary Search Tree.


The fact that you want to merge intervals in case they are adjacent to each other makes your task much easy than proposed interval tree approach.

Instead you can use data structures proposed by Some programmer dude and roll out your own implementation very quickly. Here i provide a possible implementation:

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;
    }
};

Small tests:

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)

It works with intersecting intervals as well:

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)

Tags:

Algorithm

C++

Stl