it-swarm.com.de

c ++ - STL-Satzdifferenz

Hat die C++ - STL-Set-Datenstruktur einen Set-Differenzoperator?

61
Steve

Ja, das ist in <algorithm> und heißt: std::set_difference . Die Verwendung ist:

#include <algorithm>
#include <set>
#include <iterator>
// ...
std::set<int> s1, s2;
// Fill in s1 and s2 with values
std::set<int> result;
std::set_difference(s1.begin(), s1.end(), s2.begin(), s2.end(),
    std::inserter(result, result.end()));

Am Ende enthält die Menge result den s1-s2.

123
PierreBdR

Ja, es gibt eine set_difference Funktion im Algorithmus-Header.

Bearbeitungen:

Zu Ihrer Information kann die eingestellte Datenstruktur diesen Algorithmus effizient verwenden, wie in Dokumentation angegeben. Der Algorithmus funktioniert auch nicht nur für Mengen, sondern für jedes Paar von Iteratoren über sortierte Sammlungen.

Wie bereits erwähnt, handelt es sich hierbei um einen externen Algorithmus und nicht um eine Methode. Vermutlich ist das für Ihre Anwendung in Ordnung.

11
Mr Fooz

Kein "Operator" im Sprachensinn, aber es gibt den set_difference-Algorithmus in der Standardbibliothek:

http://www.cplusplus.com/reference/algorithm/set_difference.html

Natürlich sind auch die anderen grundlegenden Mengenoperationen vorhanden - (union etc), wie im Abschnitt "Siehe auch" am Ende des verknüpften Artikels vorgeschlagen.

4
philsquared

Die gewählte Antwort ist korrekt, weist jedoch einige Syntaxfehler auf.

Anstatt 

#include <algorithms>

benutzen

#include <algorithm>

Anstatt

std::insert_iterator(result, result.end()));

benutzen

std::insert_iterator<set<int> >(result, result.end()));
2

Noch einmal zur Rettung:

#include <string>
#include <set>
#include <boost/range/algorithm/set_algorithm.hpp>

std::set<std::string> set0, set1, setDifference;
boost::set_difference(set0, set1, std::inserter(setDifference, setDifference.begin());

setDifference enthält set0-set1.

1
strickli

Nicht als Methode, aber es gibt die externe Algorithmusfunktion set_difference

template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1,
                              InputIterator2 first2, InputIterator2 last2,
                              OutputIterator result);

http://www.sgi.com/tech/stl/set_difference.html

1
Ian G

Anscheinend tut es.

SGI - set_difference

1
LeppyR64

C++ definiert keinen Set-Differenz-Operator, Sie können jedoch einen eigenen definieren (mithilfe von Code, der in anderen Antworten angegeben ist):

template<class T>
set<T> operator -(set<T> reference, set<T> items_to_remove)
{
    set<T> result;
    std::set_difference(
        reference.begin(), reference.end(),
        items_to_remove.begin(), items_to_remove.end(),
        std::inserter(result, result.end()));
    return result;
}
0
astraujums

Alle Antworten, die ich hier sehe, sind O (n). Wäre das nicht besser ?:

template <class Key, class Compare, class Allocator>   
std::set<Key, Compare, Allocator> 
set_subtract(std::set<Key, Compare, Allocator>&& lhs,
             const std::set<Key, Compare, Allocator>& rhs) {
    if (lhs.empty()) { return lhs; }
    // First narrow down the overlapping range:
    const auto rhsbeg = rhs.lower_bound(*lhs.begin());
    const auto rhsend = rhs.upper_bound(*lhs.rbegin());
    for (auto i = rhsbeg; i != rhsend; ++i) {
        lhs.erase(*i);
    }
    return std::move(lhs);
}

Das scheint das Richtige zu tun. Ich bin nicht sicher, wie man mit dem Fall umgehen soll, dass der Typ von Compare sein Verhalten nicht vollständig spezifiziert, als wäre Compare eine std::function<bool(int,int)>, aber abgesehen davon scheint das richtig zu funktionieren und sollte wie O ((überlappende num) sein • log (lhs.size())).

Falls lhs nicht *i enthält, ist es wahrscheinlich möglich, die Optimierung weiter zu optimieren, indem eine O (log (rhs.size())) Suche nach dem nächsten Element von rhs durchgeführt wird, das> = das nächste Element von lhs ist. Dies würde den Fall optimieren, dass lhs = {0, 1000} und rhs = {1, 2, ..., 999} die Log-Zeit subtrahieren.

0
Ben