两个以上集合的高效安全相交 这里是一个C++程序,它使用STD::SETH2交集两次计算3个集合的交集,然后打印结果。它产生预期结果3,但:
在第二次调用set_交叉口时,将“新闻集”作为源集和目标集传递是否安全?据我所知,使用begin和end时,我会传递对这些集合的引用,所以我可能会意外地在输入上写东西吗 这里有更有效的方法吗?我应该按大小升序迭代集合吗?与多次调用std::set_交叉点相比,滚动我自己的多集交叉点有什么优势吗 你可以继续读下去 […]结果范围不能与任一输入范围重叠 所以你在未定义的行为领域 作为验证的证据,我可以告诉你,我复制了你的代码,编译了它,运行了它,对我来说,它打印了23个,所以你的正确结果只是巧合 因此,它看起来不得不依赖另一个临时的 STL似乎不包含两个以上集合相交的解决方案,而且您甚至不能以嵌套方式使用std::set_intersection,例如result=my_set_intersectionset_1,my_set_intersectionset_2,set_3,原因很简单:算法的接口被迭代器污染,即,它将开始和结束迭代器作为集合,而不是集合本身作为输入;它还返回一个迭代器 Porbably Boost有一些有用的东西,但我还没有找到。如您所读 […]结果范围不能与任一输入范围重叠 所以你在未定义的行为领域 作为验证的证据,我可以告诉你,我复制了你的代码,编译了它,运行了它,对我来说,它打印了23个,所以你的正确结果只是巧合 因此,它看起来不得不依赖另一个临时的 STL似乎不包含两个以上集合相交的解决方案,而且您甚至不能以嵌套方式使用std::set_intersection,例如result=my_set_intersectionset_1,my_set_intersectionset_2,set_3,原因很简单:算法的接口被迭代器污染,即,它将开始和结束迭代器作为集合,而不是集合本身作为输入;它还返回一个迭代器 Porbably Boost有一些有用的东西,但我还没有找到。问题1: 不安全,正如@Enrico所说,它与一个输入范围重叠 问题2: 您可以尝试引用一个经典问题的思想:使用优先级队列或称为heap的方法合并k个排序列表,或者改用std::set,因为您需要查找是否存在一个alement。集合合并问题的思想与此类似,您可以将复杂性从Onk增加到Onlogk,其中n是所有元素的数量,并且传输成本非常小。由于3太小,无法反映该算法的优点,因此3个集合可能是有效的,但当k远大于3时,原始方法将比此方法慢得多 请注意,在分析时间复杂度时,尽管许多集合操作的成本是Ologn,但对整个集合的迭代不仅是Ologn,而且是On。问题1: 不安全,正如@Enrico所说,它与一个输入范围重叠 问题2: 您可以尝试引用一个经典问题的思想:使用优先级队列或称为heap的方法合并k个排序列表,或者改用std::set,因为您需要查找是否存在一个alement。集合合并问题的思想与此类似,您可以将复杂性从Onk增加到Onlogk,其中n是所有元素的数量,并且传输成本非常小。由于3太小,无法反映该算法的优点,因此3个集合可能是有效的,但当k远大于3时,原始方法将比此方法慢得多两个以上集合的高效安全相交 这里是一个C++程序,它使用STD::SETH2交集两次计算3个集合的交集,然后打印结果。它产生预期结果3,但:,c++,set,C++,Set,在第二次调用set_交叉口时,将“新闻集”作为源集和目标集传递是否安全?据我所知,使用begin和end时,我会传递对这些集合的引用,所以我可能会意外地在输入上写东西吗 这里有更有效的方法吗?我应该按大小升序迭代集合吗?与多次调用std::set_交叉点相比,滚动我自己的多集交叉点有什么优势吗 你可以继续读下去 […]结果范围不能与任一输入范围重叠 所以你在未定义的行为领域 作为验证的证据,我可以告诉你,我复制了你的代码,编译了它,运行了它,对我来说,它打印了23个,所以你的正确结果只是巧合 因
请注意,在分析时间复杂度时,尽管许多集合操作的成本是Ologn,但遍历整个集合不仅是Ologn,而且是On。为什么不简单地阅读文档?为什么不简单地阅读文档?谢谢Enrico!在我的真实代码中,我发现,正如您所做的,我的方法失败了,所以我使用了您所说的临时集。这样处理内存感觉效率很低,但我想这是唯一的选择。就效率而言,我认为按大小排序可能会更快,但我不是100%确定。@JoeTodd,好吧,你可以编写自己的集合交叉点来处理3个集合,不是吗?您还可以考虑STD::MultSeT,您可以用其他3组来填充,然后用计数以外的元素筛选出3个元素。没有三个集合的算法的原因与迭代器、污染或其他无关。只是两个集合的交集比三个集合的交集更常见。
标准库并没有提供所有可能的算法变体,只提供普通算法。将接口更改为使用集合而不是成对的迭代器对这个设计决策没有任何影响。@PeteBecker,我可能误解了那一段。我指的是做ABC=intersectA,intersectB,C这样的事情是不可能的。我试着改进措辞;现在可以了吗?您显然不明白迭代器是用来做什么的。如果您想在函数接口中使用集合,可以在迭代器上实现。如果你想使用迭代器,你不能合理地在使用集合的函数之上实现它。例如,如果没有很多其他无用的开销,你的集合界面不能直接将公共元素写入屏幕。谢谢Enrico!在我的真实代码中,我发现,正如您所做的,我的方法失败了,所以我使用了您所说的临时集。这样处理内存感觉效率很低,但我想这是唯一的选择。就效率而言,我认为按大小排序可能会更快,但我不是100%确定。@JoeTodd,好吧,你可以编写自己的集合交叉点来处理3个集合,不是吗?您还可以考虑STD::MultSeT,您可以用其他3组来填充,然后用计数以外的元素筛选出3个元素。没有三个集合的算法的原因与迭代器、污染或其他无关。只是两个集合的交集比三个集合的交集更常见。标准库并没有提供所有可能的算法变体,只提供普通算法。将接口更改为使用集合而不是成对的迭代器对这个设计决策没有任何影响。@PeteBecker,我可能误解了那一段。我指的是做ABC=intersectA,intersectB,C这样的事情是不可能的。我试着改进措辞;现在可以了吗?您显然不明白迭代器是用来做什么的。如果您想在函数接口中使用集合,可以在迭代器上实现。如果你想使用迭代器,你不能合理地在使用集合的函数之上实现它。例如,如果没有大量无用的开销,set接口就不能直接将公共元素写入屏幕。
#include <algorithm>
#include <iostream>
#include <set>
int main()
{
std::set<int> set_1 = {1,2,3}, set_2 = {2,3}, set_3 = {3}, newset;
std::set_intersection(set_1.begin(), set_1.end(),
set_2.begin(), set_2.end(),
std::inserter(newset, newset.begin()));
std::set_intersection(newset.begin(), newset.end(),
set_3.begin(), set_3.end(),
std::inserter(newset, newset.begin()));
for(std::set<int>::iterator it = newset.begin(); it != newset.end(); it++){
std::cout << *it;
}
std::cout << std::endl;
return 0;
}