我花了相当多的时间在Baeza-Yates的快速设置交集算法中为我的一个应用程序编码。虽然我稍微做了STL set_intersect,但事实上,在我对输出进行排序后,我在实现自己的算法时获得的任何时候都要求对结果集进行排序。鉴于STL set_intersect执行得很好,有人能指出我实际实现的算法吗?或者它是否实现了相同的Baeza-Yates算法,但只能以更有效的方式实现?
Baeza-Yates:http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.91.7899&rep=rep1&type=pdf
答案 0 :(得分:3)
STL不需要任何特定算法,它只是对某些操作的算法复杂性设置约束。由于它基于所有模板,因此您可以轻松查看特定实现的来源,以了解其工作原理。
答案 1 :(得分:2)
至少在我看过的实现中,实现相当简单 - 就这个一般顺序而言:
template <class inIt, class outIt>
outIt set_intersection(inIt start1, inIt end1, inIt start2, inIt end2, outIt out) {
while (start1 != end1 && start2 != end2) {
if (*start1 < *start2)
++start1;
else if (*start2 < *start1)
++start2;
else { // equal elements.
*out++ = *start1;
++start1;
++start2;
}
}
return out;
}
当然,我只是在脑海中输入它 - 它可能甚至不会编译,当然也不是很迂腐(例如,应该使用比较器函数而不是{{1直接,并应该有另一个模板参数,以允许start1 / end1与start2 / end2不同的类型。)
然而,从算法的角度来看,我猜大多数实际的实现都是如上所述。
答案 2 :(得分:0)
有趣。因此,算法中的比较次数与两组中的元素数量成线性比例。 Baeza-Yates算法就像这样(请注意,它假设两个输入集都已排序):
1)找出集合A的中位数(A是此处较小的集合) 2)在B中搜索A的中位数。 如果找到,请添加到结果中 否则,B中的中位数的插入等级是已知的。 3)将A的中间值分成两部分,并将B的插入等级设为两部分,并在两部分上递归重复该过程。 这一步有效,因为所有小于A中位数的元素只会与B中A的中位数插入等级之前的那些元素相交。
由于您可以使用二进制搜索来定位B中的A中位数,因此,此算法中的比较数量低于您提到的算法。事实上,在“最佳”情况下,比较的数量是O(log(m)* log(n)),其中m和n是集合的大小,在最坏的情况下,比较的数量是O(m + n)。我到底怎么搞砸这个糟糕的实施? :(