如何比较两个std::set?

58

我在比较两个 std::set

#include <cstdlib>
#include <cstdio>
using namespace std;

#include <vector>
#include <set>


int main(int argc, char** argv)
{
    int myints1[]= {10,20,30,40,50};
    int myints2[]= {50,40,30,20,10};
    std::set<int> s1 (myints1,myints1+5);
    std::set<int> s2(myints2,myints2+5);
    if(s1==s2){
        printf("sets: true");
    }else printf("sets: false");
    std::set<int>::iterator it2=s2.begin();
    for(std::set<int>::iterator it1=s1.begin();it1!=s1.end();it1++){
                printf("\ns1: %d  s2: %d",*it1,*it2);
        it2++;
    }
}

输出:

sets: true
s1: 10  s2: 10
s1: 20  s2: 20
s1: 30  s2: 30
s1: 40  s2: 40
s1: 50  s2: 50

问题:

这样做是正确的吗?还有没有其他(特别的)比较两个集合的方法?


3
如果 std::set 实现了 operator==,我会期望它是正确的。 - Mark Ransom
1
如果您正在寻找一种确定元素s1s2没有共同点的方法,您可能需要查看<algorithm>头文件中的std::set_symmetric_difference函数。 - jogojapan
我不确定std::set是否实现了==(http://www.cplusplus.com/reference/set/set/)。如果你有一些对象(没有重载`==`),而不是`int`,我不确定你是否会得到相同的结果。 - Bill
2
我在 s1==s2 中使用运算符 ==,我想知道这样做是否正确。如果是,请回答我会接受它,否则应该如何处理? - user2313793
1
@DrewDormann 看待问题的方式不错... 不过,现在已经太晚了... - jogojapan
显示剩余3条评论
5个回答

76

是的,operator==对于所有标准容器都定义正确(根据标准除了无序容器-基于23.2.5.2),通常会进行字典比较。例如请参见这里。相关引用如下:

检查lhs和rhs的内容是否相等,也就是说,lhs.size() == rhs.size()并且lhs中的每个元素在相同位置上都有等价元素在rhs中。

由于std::set是一个有序容器,任何具有相同大小和相同元素(假设比较器相同)的集合将必然处于相同的位置,因此将比较相等。


但是数学上相同元素在不同位置的两个集合是相等的,那么在std::set == 中它们也相等吗?我认为是的,但是迭代和比较会导致误导性的结果。 - user2313793
10
std::set 不会按照插入顺序保留元素,而是对它们进行排序。因此,迭代方式与 == 的工作方式相同(同时 std::equal 也是这样工作的)。 - jogojapan
@gumtree 这就是关键 - set 是有序的(第二个模板参数是一个比较运算符),因此具有相同比较器和相同元素的两个集合不能在不同位置上拥有它们。 - Yuushi
5
无序容器也有operator==运算符(查看这里或者更好的,这里)。 - rubenvb

34

在C++标准库头文件<algorithm>中有几个集合操作。

std::set_difference返回属于第一个集合但不属于第二个集合的元素。

std::set_intersection返回两个集合中共有的元素。

std::set_symmetric_difference返回出现在其中一个集合中但不同时出现在两个集合中的元素。

std::set_union返回属于第一个集合或第二个集合中的元素。

上述算法也适用于除std::set以外的STL容器,但容器需要先进行排序(std::set默认已排序)。


5
另一种方法是这样的:
template<typename Set>

bool set_compare(Set const &lhs, Set const &rhs){
    return lhs.size() == rhs.size() 
        && equal(lhs.begin(), lhs.end(), rhs.begin());
}

受这里优雅的答案 启发


2

C++11标准中std::set==运算符

其他人已经提到operator==确实可以比较std::set的内容,并且有效,但是这里有一段引自C++11 N3337标准草案的话,我相信这意味着:

这段引文与std::vector的引文完全相同,我在C++:比较两个向量中详细解释了它。

为了避免与其他答案重复,以下是简要总结:

  • 23.2.1“通用容器要求”指出,所有容器都使用equal()来进行operator==
  • 25.2.11“Equal”定义了equal,并明确表示它会迭代两个容器并比较每个元素

1
在C++11及以上版本中,您可以使用==来比较两个集合是否相等。
std::set<int> contOne{ 10,20,30,40,50 };
std::set<int> contTwo{ 50,40,30,20,10 };
std::cout << (contOne == contTwo) ? 1 : 0; // 1

此外,您也可以使用==来比较两个无序集合
std::unordered_set<int> contOne{ 10,20,30,40,50 };
std::unordered_set<int> contTwo{ 50,40,30,20,10 };
std::cout << (contOne == contTwo) ? 1 : 0; // 1

只要键相同且大小相同,容器将比较相等,无论键的顺序如何。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接