Algorithm to deal with set intervals

落花浮王杯 提交于 2019-12-10 15:59:14

问题


What is the best way to go about implementing a class which needs to keep track of set intervals in C++? I was hoping to leverage existing STL or Boost libraries but other than using standard containers, I had to resort to implementing the algorithm by hand which was surprisingly tricky to get right and I had to simplify it at the cost of some performance because of a work deadline. There must be a better way.

For example, I need the following type of behaviour:

class SubRange
{
public:
SubRange(const T& lower_bound, const T& upper_bound);
...
};

Subrange r1(1,3);
Subrange r2(5,6);
Subrange r3(6,9);

Subrange tot = r1+r2+r3;
cout << tot;  //displays (1,3) (5,9)

Subrange gaps = SubRange(1,9) - tot;
cout << gaps; // displays (4,4)

Notes A Subrange consists of a lower bound and an upper bound and denotes a contiguous set of elements from the lower bound to the upper bound, where both bounds are included in the set. The set is constructed starting from the lower bound and incrementing (operator++) until the upper bound is reached.

I have looked at Boost Interval which deals with interval arithmetic and doesn't seem to solve my problem but then the documentation is not easy for me to follow. If someone thinks that it will help, then could they please show me how to implement the above example.

For the curious. My use case was for a caching algorithm in a proxy server which needed to keep track of time-intervals of data requested by clients and optimally only ask for those portions of time-intervals from the server that had not already been cached. If client A asks for data from 1-Jan-2016 to 3-Jan-2016, client B asks for data from 5-Jan-2016 to 6-Jan-2016, client C asks for data from 6-Jan-2016 to 9-Jan-2016, then if client D asks for data from 1-Jan-2016 to 9-Jan-2016, then the proxy should only ask the server for 4-Jan-2016 because the rest of the dates are already cached.


回答1:


You could use the Boost Interval Container Library (ICL) for this task:

#include <iostream>
#include <boost/icl/interval_set.hpp>

int main()
{
    using IntervalSet = boost::icl::interval_set<int>;
    using Interval = boost::icl::interval<int>;

    IntervalSet set;

    set.insert(Interval::closed(1,3));
    set.insert(Interval::closed(5,6));
    set.insert(Interval::closed(6,9));

    std::cout << set << std::endl;

    IntervalSet total;
    total.insert(Interval::closed(1,9));

    std::cout << total << std::endl;

    IntervalSet diff_set = total - set;
    std::cout << diff_set << std::endl;

    for (auto it : diff_set)
    {
        // convert (possibly) open interval into closed
        std::cout << "[" << boost::icl::first(it) << "," << boost::icl::last(it) << "]"<< std::endl;
    }
}

output:

{[1,3][5,9]}
{[1,9]}
{(3,5)}
[4,4]

live example




回答2:


try this It worked for me
Note: you can use min and max to get the max sub interval.

    #include <iostream>
    #include <vector>

    using namespace std;

    struct val{
        int start = 0;
        int end = 0;
    };
    void FindSubSortbyStart(val *x,unsigned long n){
        for(int i = 1;i < n;i++)
            for(int j = i;j > 0;j--)
                if(x[j].start < x[j - 1].start )
                    swap(x[j],x[j-1]);
                else
                    break;
    }
    void FindSub(val *x,unsigned long n){
        vector<val> subval;

        int min = x[0].start;
        int max = x[0].end;

        for(int i = 1;i <n;i++){
            if(max  + 1>= x[i].start){
                if(x[i].end >= max)
                    max = x[i].end;
            }else{

                val temp;

                temp.start = max + 1;
                temp.end = x[i].start - 1;

                max = x[i].end;
                min = x[i].start;

                subval.push_back(temp);

                cout << subval[subval.size() - 1].start << "\t"<< subval[subval.size() - 1].end << endl;
            }
        }
    }

    int main(int argc, const char * argv[]) {

        unsigned long n = 3;

        val *x = new val[n];

        x[0].start = 1;
        x[0].end = 3;

        x[1].start = 5;
        x[1].end = 5;

        x[2].start = 7;
        x[2].end = 9;

        FindSubSortbyStart(x,n);
        FindSub(x,n);

        return 0;
    }


来源:https://stackoverflow.com/questions/34837663/algorithm-to-deal-with-set-intervals

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!