web-dev-qa-db-fra.com

c ++ STL set difference

La structure de données d'ensemble C++ STL a-t-elle un opérateur de différence d'ensemble?

61
Steve

Oui, il est dans <algorithm> et s'appelle: std::set_difference . L'utilisation est:

#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()));

En fin de compte, la variable result contiendra le s1-s2.

123
PierreBdR

Oui, il existe une fonction set_difference dans l'en-tête de l'algorithme.

Edits:

Pour votre information, la structure de données d'ensemble est capable d'utiliser efficacement cet algorithme, comme indiqué dans sa documentation . L'algorithme fonctionne également non seulement sur les ensembles, mais sur toute paire d'itérateurs sur des collections triées.

Comme d'autres l'ont mentionné, il s'agit d'un algorithme externe, pas d'une méthode. Je suppose que c'est bien pour votre application.

11
Mr Fooz

Ce n'est pas un "opérateur" au sens du langage, mais il y a l'algorithme set_difference dans la bibliothèque standard:

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

Bien entendu, les autres opérations de base sont également présentes (union, etc.), comme le suggère la section "Voir aussi" à la fin de l'article lié.

4
philsquared

La réponse choisie est correcte, mais présente des erreurs de syntaxe.

Au lieu de 

#include <algorithms>

utilisation

#include <algorithm>

Au lieu de

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

utilisation

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

Encore une fois, relancez à la rescousse:

#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 contiendra set0-set1.

1
strickli

Pas comme méthode, mais il y a la fonction d'algorithme externe 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

Apparemment c'est le cas.

SGI - set_difference

1
LeppyR64

C++ ne définit pas d'opérateur de différence entre ensembles mais vous pouvez définir le vôtre (en utilisant le code donné dans d'autres réponses):

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

Toutes les réponses que je vois ici sont O (n). Ne serait-ce pas mieux ?:

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

Cela semble faire la bonne chose. Je ne suis pas sûr de savoir comment traiter le cas où le type de Compare ne spécifie pas complètement son comportement, comme dans le cas où Compare est un std::function<bool(int,int)>, mais à part cela, cela semble fonctionner correctement et devrait ressembler à O ((chevauchement de chiffres) • log (lhs.size())).

Si lhs ne contient pas *i, il est probablement possible d'optimiser davantage en effectuant une recherche O (log (rhs.size())) pour le prochain élément de rhs qui est> = le prochain élément de lhs. Cela optimiserait le cas où lhs = {0, 1000} et rhs = {1, 2, ..., 999} effectueraient la soustraction dans le temps de log.

0
Ben