[英]C++: Differences between 2 arrays
我有两个单个简单元素类型的未分类随机访问数组(int / string / etc,所以有所有比较运算符,可以进行哈希处理等)。 任何一个数组中都不应该有重复的元素。
寻找给出这些数组A和B的一般algorthim会告诉我:
我想我可以用下面的set运算符来做这个,但是有一个更快的解决方案(例如,不需要我构建两个有序集合)?
r1 = std::set_intersection(a,b);
r2 = std::set_difference(a,b);
r3 = std::set_difference(b,a);
类似下面的算法会运行O(| A | + | B |)(假设来自unordered_map
O(1)行为):
onlyA
最初包含所有A,并且只列出onlyB
, bothAB
从空开始。 Amap
联营元素onlyA
,在其相应的迭代onlyA
。 B
每个元素b
bothAB
onlyA
删除b onlyB
在上面的算法结束时,
以下是上述的实现。 结果以元组< onlyA
, onlyB
, bothAB
>的形式返回。
template <typename C>
auto venn_ify (const C &A, const C &B) ->
std::tuple<
std::list<typename C::value_type>,
std::list<typename C::value_type>,
std::list<typename C::value_type>
>
{
typedef typename C::value_type T;
typedef std::list<T> LIST;
LIST onlyA(A.begin(), A.end()), onlyB, bothAB;
std::unordered_map<T, typename LIST::iterator> Amap(2*A.size());
for (auto a = onlyA.begin(); a != onlyA.end(); ++a) Amap[*a] = a;
for (auto b : B) {
auto ai = Amap.find(b);
if (ai == Amap.end()) onlyB.push_back(b);
else {
bothAB.push_back(b);
onlyA.erase(ai->second);
}
}
return std::make_tuple(onlyA, onlyB, bothAB);
}
首先,从你的问题来看,当你谈到排序集时,你的意思是std::set
是不明确的。 如果是这样,那么你的第一反应应该是在原始向量上使用std::vector
,如果可以的话。 只需对它们进行排序,然后:
std::vector<T> r1;
std::set_intersection( a.cbegin(), a.cend(), b.cbegin(), b.cend(), std::back_inserter( r1 ) );
对于r2
和r3
。
除此之外,我怀疑你能做多少事情。 只需一个循环可以改善一些事情:
std::sort( a.begin(), a.end() );
std::sort( b.begin(), b.end() );
onlyA.reserve( a.size() );
onlyB.reserve( b.size() );
both.reserve( std::min( a.size(), b.size() ) );
auto ita = a.cbegin();
auto enda = a.cend();
auto itb = b.cbegin();
auto endb = b.cend();
while ( ita != enda && itb != endb ) {
if ( *ita < *itb ) {
onlyA.push_back( *ita );
++ ita;
} else if ( *itb < *ita ) {
onlyB.push_back( *itb );
++ itb;
} else {
both.push_back( *ita );
++ ita;
++ itb;
}
}
onlyA.insert( onlyA.end(), ita, enda );
onlyB.insert( onlyB.end(), itb, endb );
reserve
可以产生影响,除非大多数元素最终都在同一个向量中,否则可能不会花费太多额外的内存。
您可以通过将A的元素放入unordered_map(其中A中的元素是键)来以线性时间执行此操作。 检查地图中键中B的元素是否存在。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.