如何确定两个向量的差异?
我有vector<int> v1和vector<int> v2;
我要找的是一个只包含v1或v2元素的vector<int> vDifferences。
有没有一种标准的方法来做到这一点?
发布于 2011-10-16 05:05:30
这是完整的正确的答案。在使用set_symmetric_difference算法之前,必须对源范围进行排序:
using namespace std; // For brevity, don't do this in your own code...
vector<int> v1;
vector<int> v2;
// ... Populate v1 and v2
// For the set_symmetric_difference algorithm to work,
// the source ranges must be ordered!
vector<int> sortedV1(v1);
vector<int> sortedV2(v2);
sort(sortedV1.begin(),sortedV1.end());
sort(sortedV2.begin(),sortedV2.end());
// Now that we have sorted ranges (i.e., containers), find the differences
vector<int> vDifferences;
set_symmetric_difference(
sortedV1.begin(),
sortedV1.end(),
sortedV2.begin(),
sortedV2.end(),
back_inserter(vDifferences));
// ... do something with the differences应该注意的是,排序是一个开销很大的操作(即O(n log n) for common STL implementations)。特别是对于容器中的一个或两个都非常大(即,数百万个整数或更多)的情况,基于算法复杂度,使用散列表的不同算法可能是优选的。以下是该算法的高级描述:
通过标准化unordered_multiset容器,C++11为我们提供了这样的解决方案的一些功能。我还使用了auto关键字的新用法进行显式初始化,以使以下基于哈希表的解决方案更简洁:
using namespace std; // For brevity, don't do this in your own code...
// The remove_common_items function template removes some and / or all of the
// items that appear in both of the multisets that are passed to it. It uses the
// items in the first multiset as the criteria for the multi-presence test.
template <typename tVal>
void remove_common_items(unordered_multiset<tVal> &ms1,
unordered_multiset<tVal> &ms2)
{
// Go through the first hash table
for (auto cims1=ms1.cbegin();cims1!=ms1.cend();)
{
// Find the current item in the second hash table
auto cims2=ms2.find(*cims1);
// Is it present?
if (cims2!=ms2.end())
{
// If so, remove it from both hash tables
cims1=ms1.erase(cims1);
ms2.erase(cims2);
}
else // If not
++cims1; // Move on to the next item
}
}
int main()
{
vector<int> v1;
vector<int> v2;
// ... Populate v1 and v2
// Create two hash tables that contain the values
// from their respective initial containers
unordered_multiset<int> ms1(v1.begin(),v1.end());
unordered_multiset<int> ms2(v2.begin(),v2.end());
// Remove common items from both containers based on the smallest
if (v1.size()<=v2.size)
remove_common_items(ms1,ms2);
else
remove_common_items(ms2,ms1);
// Create a vector of the union of the remaining items
vector<int> vDifferences(ms1.begin(),ms1.end());
vDifferences.insert(vDifferences.end(),ms2.begin(),ms2.end());
// ... do something with the differences
}为了确定哪种解决方案更适合特定情况,分析这两种算法将是一个明智的行动过程。虽然基于哈希表的解决方案是O(n),但它需要更多的代码,并且每次找到重复项都要做更多的工作(即哈希表删除)。它还(遗憾地)使用了一个自定义的差分函数,而不是标准的STL算法。
应该注意的是,这两种解决方案的不同之处很可能与元素在原始容器中出现的顺序完全不同。有一种方法可以通过使用哈希表解决方案的变体来解决此问题。下面是高级描述(仅在步骤4中与前面的解决方案不同):
为了保持原来的顺序,步骤4已经变得比以前的解决方案更昂贵,特别是当删除的项目数量很多时。这是因为:
https://stackoverflow.com/questions/7771796
复制相似问题