Does the C++ STL set data structure have a set difference operator?
Apparently, it does.
SGI - set_difference
C++ does not define a set difference operator but you can define your own (using code given in other responses):
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;
}
Not as a method but there's the external algorithm function 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
All of the answers I see here are O(n). Wouldn't this be better?:
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);
}
That seems to do the right thing. I'm not sure how to deal with the case that Compare
's type doesn't fully specify its behavior, as in if Compare
is a std::function<bool(int,int)>
, but aside from that, this seems to work right and should be like O((num overlapping) • log(lhs.size()
)).
In the case that lhs
doesn't contain *i
, it's probably possible to optimize further by doing an O(log(rhs.size()
)) search for the next element of rhs
that's >= the next element of lhs
. That would optimize the case that lhs = {0, 1000}
and rhs = {1, 2, ..., 999}
to do the subtraction in log time.