当两个向量之间存在任何元素匹配时,我希望函数返回true,
Note : My vectors are not sorted
以下是我的源代码,
bool CheckCommon( std::vector< long > &inVectorA, std::vector< long > &inVectorB )
{
std::vector< long > *lower, *higher;
size_t sizeL = 0, sizeH = 0;
if( inVectorA.size() > inVectorB.size() )
{
lower = &inVectorA;
sizeL = inVectorA.size();
higher = &inVectorB;
sizeH = inVectorB.size();
}
else
{
lower = &inVectorB;
sizeL = inVectorB.size();
higher = &inVectorA;
sizeH = inVectorA.size();
}
size_t indexL = 0, indexH = 0;
for( ; indexH < sizeH; indexH++ )
{
bool exists = std::binary_search( lower->begin(), lower->end(), higher->at(indexH) );
if( exists == true )
return true;
else
continue;
}
return false;
}
当向量B的大小小于向量A的大小时,这工作正常,但是当向量B的大小大于向量A的大小时,即使存在匹配,也返回false。
答案 0 :(得分:5)
发布代码的问题是,当矢量未排序时,您不应使用std::binary_search
。仅针对排序范围定义行为。
如果未对输入向量进行排序,则可以使用find_first_of
检查是否存在找到的第一个公共元素。
bool CheckCommon(std::vector<long> const& inVectorA, std::vector<long> const& nVectorB)
{
return std::find_first_of (inVectorA.begin(), inVectorA.end(),
nVectorB.begin(), nVectorB.end()) != inVectorA.end();
}
find_first_of
的复杂度在inVectorA.size()*inVectorB.size()
中达到线性;它会比较元素,直到找到匹配为止。
如果你想修复原始算法,那么你可以复制一个向量并std::sort
它,然后std::binary_search
使用它。
在容器之间进行大量此类匹配的实际程序中,容器通常保持分类。然后,搜索的复杂性在inVectorA.size()+inVectorB.size()
中达到线性。
std::find_first_of
比对两个范围进行排序更有效,然后在两个范围相当短或第二个范围短于第一个范围长度的二进制对数时搜索匹配。
答案 1 :(得分:1)
您可以使用名为std::set_intersection
的定义明确的算法来检查这些向量之间是否存在任何共同元素。
前提条件: - 两个向量都要排序。
答案 2 :(得分:1)
这是一个使用有序向量的实现,不构造一个新容器,并且只具有线性复杂度(更详细:O(container1.size()+ container2.size())
:
template< class ForwardIt1, class ForwardIt2 >
bool has_common_elements( ForwardIt1 first, ForwardIt1 last, ForwardIt2 s_first, ForwardIt2 s_last )
{
auto it=first;
auto s_it=s_first;
while(it<last && s_it<s_last)
{
if(*it==*s_it)
{
return true;
}
*it<*s_it ? ++it : ++s_it; //increase the smaller of both
}
return false;
}
答案 3 :(得分:0)
您可以执行以下操作。迭代第一个向量。对于每个元素,使用std::find
查看它是否存在于另一个向量中。如果你找到它,它们至少有一个共同元素,所以返回true。否则,移动到第一个向量的下一个元素并重复此过程。如果你在没有找到公共元素的情况下完成第一个向量,那么就没有交集,所以返回false。
bool CheckCommon(std::vector<long> const& inVectorA, std::vector<long> const& nVectorB)
{
for (auto const& num : inVectorA)
{
auto it = std::find(begin(nVectorB), end(nVectorB), num);
if (it != end(nVectorB))
{
return true;
}
}
return false;
}
答案 4 :(得分:0)
使用std::set_intersection
是一种选择。由于向量的元素已排序,因此代码可以简化为:
#include <algorithm>
#include <iterator>
bool CheckCommon( const std::vector< long > &inVectorA, const std::vector< long > &inVectorB )
{
std::vector< long > temp;
std::set_intersection(inVectorA.begin(), inVectorA.end(),
inVectorB.begin(), inVectorB.end(),
std::back_inserter(temp));
return !temp.empty()
}
缺点是正在执行set_intersection
时正在创建一个临时向量(但是如果你想知道哪些元素是常见的,将来可能会被视为“特征”。< / p>
答案 5 :(得分:0)
您的代码使用std::binary_search
,其前提条件是(来自http://en.cppreference.com/w/cpp/algorithm/binary_search):
要使
std::binary_search
成功,范围[first, last)
必须至少部分排序,即它必须满足以下所有要求:
- 根据
element < value
或comp(element, value)
进行分区
- 根据
进行分区!(value < element)
或!comp(value, element)
- 对于所有元素,如果
element < value
或comp(element, value)
为true
,则!(value < element)
或!comp(value, element)
也为true
完全排序的范围符合这些条件,调用
std::partition
产生的范围也是如此。
您用于测试的样本数据(在http://ideone.com/XCYdM8处发布)不符合该要求。而不是使用:
vectorB.push_back(11116);
vectorB.push_back(11118);
vectorB.push_back(11112);
vectorB.push_back(11120);
vectorB.push_back(11190);
vectorB.push_back(11640);
vectorB.push_back(11740);
如果你使用如下的排序矢量
vectorB.push_back(11112);
vectorB.push_back(11116);
vectorB.push_back(11118);
vectorB.push_back(11120);
vectorB.push_back(11190);
vectorB.push_back(11640);
vectorB.push_back(11740);
你的功能会很好。
PS 您设计了代码,如果排序的std::vector
越长,该功能就能正常运行。
PS2 另一种选择是在调用函数之前对较长的std::vector
进行排序。
std::sort(B.begin(), B.end());