2012-12-20 9 views
5

Poszukuję klasy C++, która może obsługiwać 1-wymiarową listę zakresów.Wymagane: klasa C++ do obsługi 1-wymiarowej listy zakresów

Każdy zakres jest zdefiniowany jako para (start,len).

Chcę móc dodawać dodatkowe zakresy do listy i automatycznie je konsolidować. Oznacza to, że jeśli mamy na liście (0,5) i (10,5) i zostanie dodana (5,5), nowa lista powinna zawierać tylko (0,15).

Zakresy nigdy nie są usuwane z listy.

Czy coś takiego istnieje?

Dzięki.

Odpowiedz

5

Poszukujesz narzędzia Boost.Icl. Robi dokładnie to, co opisałeś.

http://www.boost.org/doc/libs/1_52_0/libs/icl/doc/html/index.html

+0

To nie jest dla mnie jasne, czy Boost.lcl będzie łączyć sąsiadujące zasięgi. Czy wiesz na pewno, że tak jest? Będziemy mieć setki tysięcy ciągłych rozszerzeń. – vy32

+0

Tak, będzie. Używam go w ten sposób przez cały czas. Sprawdź tę stronę: http: //www.boost.org/doc/libs/1_52_0/libs/icl/doc/html/index.html#boost_icl.introduction.interval_combining_styles – Zeks

+0

Świetnie. Dzięki! Właśnie tego potrzebowałem. – vy32

2

Oto przykład implementacja prostego przedziale pojemnika:

#include <iostream> 
#include <vector> 
#include <memory> 
#include <algorithm> 

using std::vector; 
using std::pair; 
using std::make_pair; 

typedef pair<int, int> interval;  

struct interval_container 
{ 
    void add(int start, int len) 
    { 
     _data.emplace_back(make_pair(start, len)); 
    } 

    void consolidate() 
    { 
     // sort intervals first by start then by length 
     std::sort(_data.begin(), _data.end()); 

     // create temp data 
     vector<interval> consolidated; 

     // iterate over all sorted intervals 
     for(const interval& i : _data) 
     { 
      int start = i.first; 
      int len = i.second; 

      // special case: first interval 
      if (consolidated.empty()) 
      { 
       consolidated.emplace_back(i); 
      } 
      // all other cases 
      else 
      { 
       // get last interval in the consolidated array 
       interval& last = consolidated.back(); 
       int& last_start = last.first; 
       int& last_len = last.second; 


       // if the current interval can be merged with the last one 
       if ((start >= last_start) and (start < (last_start + last_len))) 
       { 
        // merge the interval with the last one 
        last_len = std::max(last_len, (start + len - last_start)); 
       } 
       // if the current interval can't be merged with the last one 
       else 
       { 
        consolidated.emplace_back(i); 
       } 
      } 
     } 

     // copy consolidated data 
     _data = consolidated; 
    } 


    vector<interval>& data() { return _data; } 

private: 
    vector<interval> _data; 
}; 


int main() 
{ 
    interval_container intervals; 

    intervals.add(0, 2); 
    intervals.add(1, 3); 
    intervals.add(5, 3); 

    intervals.consolidate(); 

    int c(0); 
    for(interval i : intervals.data()) 
    { 
     std::cout << (c++) << ": from " << i.first << " to " << (i.first + i.second) << std::endl; 
    } 
} 
+0

Dzięki. Pytanie --- Widziałem całą masę ludzi definiujących klasy z 'struct', tak jak tutaj, zamiast z właściwą deklaracją klasy C++. Po co definiować klasę jako strukturę? – vy32

+1

Zobacz [tutaj] (http://stackoverflow.com/questions/92859/what-are-the-differences-between-struct-and-class-in-c) dla pytania SO dotyczącego różnic między strukturą a klasą. Osobiście robię to, ponieważ zawsze deklaruję publiczne metody na szczycie klasy i nie chcę zawsze wpisywać "public:". Z czasem stało się to nawykiem. – Gigi

+0

Huh. W porządku. Dzięki. – vy32