C++:2 个数组之间的差异
C++: Differences between 2 arrays
我有两个单一简单元素类型的未排序随机访问数组(int/string/etc,所以有所有的比较运算符,可以散列等(。两个数组中都不应有重复的元素。
寻找一个给定这些数组 A 和 B 的一般算法会告诉我:
- A 和 B 中都有哪些元素
- 哪些元素在 A 中,而不是 B 中
- 哪些元素在 B 中,而不是 A 中
我想我可以使用下面的集合运算符来做到这一点,但是有没有更快的解决方案(例如,不需要我构建两个排序集的解决方案(?
r1 = std::set_intersection(a,b);
r2 = std::set_difference(a,b);
r3 = std::set_difference(b,a);
首先,从你的问题中不清楚你的意思是 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
可能会有所作为,除非大多数元素最终位于同一个向量中,可能不会花费太多额外内存。
类似于以下算法的内容将运行 O(|A|+|B|((假设 O(1( 行为来自 unordered_map
(:
- 让列表
onlyA
最初包含所有 A,列表onlyB
和bothAB
开始时为空。 - 让哈希表
Amap
onlyA
中的元素与onlyA
中的相应迭代器相关联。 - 对于
B
中的每个元素 b- 如果 b 在 Amap 中找到对应的迭代器 ai
- 将 b 添加到
bothAB
- 使用 ai 从
onlyA
中删除 b
- 将 b 添加到
- 否则,将 b 添加到
onlyB
- 如果 b 在 Amap 中找到对应的迭代器 ai
在上述算法的最后,
- 只有 A 包含
- A 中的元素,但不包含 B 中的元素,
- 只有 B 包含 B 中的元素,但在 A 中不包含元素,
- bothAB 都包含 A 和 B 中的元素。
下面是上述内容的实现。结果以元组<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);
}
您可以通过将 A 的元素放入 A 中的元素作为键的unordered_map中来线性时间执行此操作。 检查映射中键中 B 的元素是否。
相关文章:
- 查找数组中第一个最小值和最后一个最大值元素之间的算术平均值
- 在 Python 和 c++ 2d 数组初始化之间.这是怎麽?为什么呢?
- 介于 [固定数组] 和 [带内存分配的指针] 之间的性能
- 动态分配的数组和静态数组之间的区别
- 删除[i] 数组和删除数组 [i] 之间的区别
- 当数组位于两个循环之间时,您可以调用数组的 void 函数吗?
- 处理数组时make_unique和make_shared之间的差异
- 在两个结构之间共享数组
- C++堆栈中数组之间的间隙
- 类型测试对象的动态数组的这两个声明之间的区别?
- 如何计算大小为 1000 x 1000 的 2D 数组中 2 个元素之间的步幅?C++
- sizeof(空结构)和sizeof(带有空数组的结构)之间的区别?
- 尝试查找数组中点之间的最小距离时的随机垃圾输出
- 如何在带有 mbed 的 nucleo f446re 之间通过带有 UARTSerial 类的 USB 发送字节数组?
- 在给定的整数数组中,可以找到在给定位置之间分类数组的整数之和
- 这两个代码之间的差异(为什么我的数组也有额外的空间,即使我限制了它)
- 使用STD :: String和字符数组之间的选择
- 如何在不复制数据的情况下在平面数组和多维数组之间进行转换?
- 在函数之间传递相同的数组
- 如果 strlen 在 char 数组之间遇到空格,它会怎么做