You could use set_intersection
and test if the resulting set is empty, but I don't know if that's much faster.
The optimal implementation would stop the testing and return false
as soon as the first equal element is found. I don't know of any ready-made solution for that, though
template<class Set1, class Set2>
bool is_disjoint(const Set1 &set1, const Set2 &set2)
{
Set1::const_iterator it, itEnd = set1.end();
for (it = set1.begin(); it != itEnd; ++it)
if (set2.count(*it))
return false;
return true;
}
isn't too complex and should do the job nicely.
EDIT: If you want O(n) performance, use the slightly less compact
template<class Set1, class Set2>
bool is_disjoint(const Set1 &set1, const Set2 &set2)
{
Set1::const_iterator it1 = set1.begin(), it1End = set1.end();
if (it1 == it1End)
return true; // first set empty => sets are disjoint
Set2::const_iterator it2 = set2.begin(), it2End = set2.end();
if (it2 == it2End)
return true; // second set empty => sets are disjoint
// first optimization: check if sets overlap (with O(1) complexity)
Set1::const_iterator it1Last = it1End;
if (*--it1Last < *it2)
return true; // all elements in set1 < all elements in set2
Set2::const_iterator it2Last = it2End;
if (*--it2Last < *it1)
return true; // all elements in set2 < all elements in set1
// second optimization: begin scanning at the intersection point of the sets
it1 = set1.lower_bound(*it2);
if (it1 == it1End)
return true;
it2 = set2.lower_bound(*it1);
if (it2 == it2End)
return true;
// scan the (remaining part of the) sets (with O(n) complexity)
for(;;)
{
if (*it1 < *it2)
{
if (++it1 == it1End)
return true;
}
else if (*it2 < *it1)
{
if (++it2 == it2End)
return true;
}
else
return false;
}
}
(modified Graphics Noob's modification further, using only operator <)