奇怪的问题:STL set_intersect实现了什么算法?

时间:2010-10-27 04:51:32

标签: c++ stl set-intersection

我花了相当多的时间在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

3 个答案:

答案 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)。我到底怎么搞砸这个糟糕的实施? :(