2015-01-14 14 views
5

Gibt es in der C++ - Welt einen Container mit diesen Eigenschaften?Container mit den Eigenschaften std :: vector und std :: set?

  • Elemente sind einzigartig und mit Hilfe einer anpassbaren Komparator bestellt
  • einen Direktzugriffs Betreiber bereitzustellen.

bin Sammeln ich zur Zeit meine Daten in ein std::set<C,COMPARATOR> und danach eine std::copy(_set.begin(),_set.end(),std::back_inserter(_vec)) tun Direktzugriff auf die geordnete Sammlung haben zu können. Die Größe könnte jedoch in Hunderte von Millionen gehen.

+0

Würde ein Haufen helfen? Sie haben nicht die gesamte Bestellung, aber können das maximale Element auswählen. – Quentin

+0

@Quentin keine strenge Bestellung erforderlich ist – Oncaphillis

+2

Werden Sie viele Insertionen und/oder Löschungen in der Mitte der Daten tun? Das wird bei akzeptablen Lösungen einen großen Unterschied machen. Ihre aktuelle Lösung könnte verbessert werden, indem Sie den Vektor direkt hinzufügen und "std :: sort" ausführen, sollte es insgesamt etwas schneller sein. –

Antwort

7

Wenn Boost eine Option ist, werfen Sie einen Blick auf flat_set in the Containers library.

Die Schnittstelle für flat_set dem von std::set identisch ist, aber es bietet Random Access-Iteratoren, wie std::vector:

#include <boost/container/flat_set.hpp> 

[...] 

boost::container::flat_set<int> c; 
c.insert(1); 
c.insert(2); 
c.insert(3); 
c.insert(4); 

// unfortunately, no operator[] on the container itself, 
// but the iterator is random access 
int third_element = c.begin()[2]; 

Wenn Sie mit der Standardbibliothek stecken geblieben sind, können Sie eine sortierte vector für diesen Zweck verwenden können. Die Standardbibliothek bietet tatsächlich eine Menge von Algorithmen im Header <algorithm>, mit denen Sie so ziemlich alles tun können, was Sie mit einem set mit einem sortierten Iterator-Bereich tun können.

+0

Ich muss die Leistung für Einfügen/Löschen betrachten, aber ich denke, das ist es. Boost ist definitiv eine Option – Oncaphillis

+1

Sie bieten einen Direktzugriffs-Iterator, aber kein 'operator []'? Wundern Sie sich, was die Gründe dafür sind. – Barry

+1

Nun hatte ich einen Testlauf mit 10^6 Zufallszahlen-Einfügungen und es dauerte etw. wie 140 sek. Einfügen in ein std :: set mit späterem Kopieren in einen std :: vector tat es unter 1sec. Da ich nach der Initialisierung nicht viele Einfügungen/Löschungen mache, denke ich, dass ich bei meiner Lösung bleibe. Aber ich nehme diese Antwort immer noch als die richtige Lösung für meine erste Frage. – Oncaphillis

1

Keine, die ich kenne. Bei Hunderten von Millionen Elementen und einigen geordneten Zugriffen ist es jedoch möglich, dass die Speicherdarstellung kompakt und konsekutiv ist. Dies sind noch mehr Anforderungen für Ihre Containerklasse.

Ich würde mit std::vector gehen und den von Ihnen beschriebenen Ansatz oder einen anderen Sortieralgorithmus verwenden. Sie werden wahrscheinlich Ihre std::set danach nicht brauchen, damit Sie den Speicher freigeben können.

1

Nicht in der C++ - Standardbibliothek, nein. Sie haben entweder set/priority_queue für die Bestellung oder vector/deque für den wahlfreien Zugriff.

Aber nichts hält Sie davon ab, Ihren eigenen Wrapper um vector zu schreiben, der einfach die Bestellung erzwingt. Es ist nicht so viel Code. Einige Beispielfunktionen:

template <typename T, typename COMP = std::less<T>> 
class sorted_vec { 
    std::vector<T> vec_; 

public: 
    // random access 
    using iterator = typename std::vector<T>::iterator; 
    T& operator[](size_t idx) { return vec_[idx]; } 

    iterator begin() { return vec_.begin(); } 
    iterator end() { return vec_.end(); } 

    // insertion 
    void push(const T& val) { 
     vec_.insert(std::lower_bound(vec_.begin(), vec_.end(), COMP{}), 
        val); 
    } 
}; 
+0

Ich würde auch die 'const'-Version von' T & operator [] 'schreiben, so dass Sie die' const'-Referenz übergeben können. – vsoftco

+0

@vsoftco Richtig, das ist auf keinen Fall eine erschöpfende Liste von Funktionen (z. B. gibt es keine 'const_iterator', etc.) – Barry