在C 中的大量向量中搜索

Search within a big vector in C++

本文关键字:向量 搜索      更新时间:2023-10-16

我有以下向量:

std::vector<A*> vec;
std::vector<std::pair<A*, A*>> vec_pair;

vec_pair尺寸远远超过VEC尺寸。我想在VEC_PAIR中找到两个成员在VEC中的一对。

vec_pair的内容是恒定的。但是,在每次迭代之后,vec的内容都会改变,我想再次进行测试。

我知道我可以做一个循环并进行检查。但是,考虑大小差异作业的复发,我正在寻找一种智能有效的方法来完成。

如果您不要更改vec的内容,请创建一个具有相同内容的std::unordered_set<A*>并在那里搜索出现。在unordered_set中搜索大约是O(1(,因此这将是一个简单的胜利。

vector构造unordered_set的最简单和最有效的方法是使用构造函数,采用两个迭代器:

unordered_set<A*> us(vec.begin(), vec.end());

您可以使用unordered_set(您实际上不需要map(,该O(1) search insert 。>

1(从VEC构建unordered_set<A*> S;

2(对于vec_pair中的每对,您可以检查S中是否存在两个元素

类似以下的事情将在平均O(vec_pair.size())

中完成工作
std::vector<A*> vec;
std::vector<std::pair<A*, A*>> vec_pair;

unordered_set<A*> S;
for(auto a: vec)
    S.insert(a);
for(auto p : vec_pair){
    if(s.find(p.first)!=S.end() && 
        s.find(p.second)!=S.end())
    {
        //PAIR GOOD
    }else{
        //THIS PAIR IS NOT GOOD
    }
}

vec_pair尺寸大于 vec尺寸。

这应该用作线索使用std::map。将向量vec的所有元素放入地图中:myMap[vec[i]] = 1;然后在vec_pair中浏览每对,然后进行

if (myMap.find(vec_pair[i].first != myMap.end()) && 
    myMap.find(vec_pair[i].second != myMap.end()) ) 
{
    return FOUND; 
}
else 
    return NOT_FOUND;`

盖茨评论,使用unordered_map进行更快的操作。

我不知道您的确切要求,但是,如果vec_pair中的元素顺序并不重要,我想您可以用std::multimap替换它,或者我想更好的是std::unordered_multimap

我的意思是(使用等于 int的类型A(

   using A = int;
   std::vector<std::pair<A, A>> const vec_pair
    { {1, 1}, {1, 2}, {1, 3}, {1, 4},
      {2, 1}, {2, 2}, {2, 3}, {2, 4},
      {3, 1}, {3, 2}, {3, 3}, {3, 4},
      {4, 1}, {4, 2}, {4, 3}, {4, 4} };

您可以使用

   std::unordered_multimap<A, A> const cM
    { {1, 1}, {1, 2}, {1, 3}, {1, 4},
      {2, 1}, {2, 2}, {2, 3}, {2, 4},
      {3, 1}, {3, 2}, {3, 3}, {3, 4},
      {4, 1}, {4, 2}, {4, 3}, {4, 4} };

如果您需要vec_pair是对的矢量,则使用vec_pair是恒定的事实(我理解正确吗?(,您可以构成恒定的无序多映射。

此解决方案的优点是,如果您发现地图的密钥不在vec中,则可以避免使用相同键的所有值进行测试。

更多:如果构造set(或者更好,是unordered_set(,请从vec开始(这很少,如果我理解正确,则可以按以下方式检查对

   for ( auto ci = cM.cbegin() ; ci != cM.cend() ; )
    {
      auto val = ci->first;
      auto cnt = cM.count(val);
      if ( s.end() == s.find(val) )
       {
         for ( auto i = 0U ; i < cnt ; ++i )
            ++ci;
       }
      else for ( auto i = 0U ; i < cnt ; ++i, ++ci ) 
         if ( s.end() != s.find(ci->second) )
            std::cout << "- good for <" << val << ", " << ci->second
               << '>' << std::endl;
    }

我知道:不是优雅的解决方案。

另一种方法是使用地图和设置的组合(unorderd,更好(,而不是

   std::vector<std::pair<A, A>> const vec_pair
    { {1, 1}, {1, 2}, {1, 3}, {1, 4},
      {2, 1}, {2, 2}, {2, 3}, {2, 4},
      {3, 1}, {3, 2}, {3, 3}, {3, 4},
      {4, 1}, {4, 2}, {4, 3}, {4, 4} };

使用(或构造(

   std::unordered_map<A, std::unordered_set<A>> const cM
    { {1, {1, 2, 3, 4}}, {2, {1, 2, 3, 4}},
      {3, {1, 2, 3, 4}}, {4, {1, 2, 3, 4}} };

在这种情况下,搜索部分更优雅(IMHO(

   for ( auto const & p : cM2 )
      if ( s.end() != s.find(p.first) )
         for ( auto const & sec : p.second )
            if ( s.end() != s.find(sec) )
            std::cout << "- good for <" << p.first << ", " << sec
               << '>' << std::endl;

以下是两个解决方案的完整汇编示例

#include <vector>
#include <utility>
#include <iostream>
#include <unordered_map>
#include <unordered_set>
int main()
 {
   using A = int;
   std::unordered_multimap<A, A> const cM
    { {1, 1}, {1, 2}, {1, 3}, {1, 4},
      {2, 1}, {2, 2}, {2, 3}, {2, 4},
      {3, 1}, {3, 2}, {3, 3}, {3, 4},
      {4, 1}, {4, 2}, {4, 3}, {4, 4} };
   std::unordered_set<A> s { 4, 3 };
   for ( auto ci = cM.cbegin() ; ci != cM.cend() ; )
    {
      auto val = ci->first;
      auto cnt = cM.count(val);
      if ( s.end() == s.find(val) )
       {
         for ( auto i = 0U ; i < cnt ; ++i )
            ++ci;
       }
      else for ( auto i = 0U ; i < cnt ; ++i, ++ci ) 
         if ( s.end() != s.find(ci->second) )
            std::cout << "- good for <" << val << ", " << ci->second
               << '>' << std::endl;
    }
   std::unordered_map<A, std::unordered_set<A>> const cM2
    { {1, {1, 2, 3, 4}}, {2, {1, 2, 3, 4}},
      {3, {1, 2, 3, 4}}, {4, {1, 2, 3, 4}} };
   for ( auto const & p : cM2 )
      if ( s.end() != s.find(p.first) )
         for ( auto const & sec : p.second )
            if ( s.end() != s.find(sec) )
            std::cout << "- good for <" << p.first << ", " << sec
               << '>' << std::endl;
 }

VEC比VEC_PAIR小多少?VEC大小的平方仍然比VEC_PAIR的大小小吗?如果是这样,您可以从vec_pair中制作一个unordered_set,然后搜索从VEC中生成的每对可能的对。

为什么不能对两个容器进行排序?您可以制作每个分类的副本吗?如果是这样,请将指针指向两个列表的开始,并增加寻找匹配项。您仍然会是O(vec_pair的大小(,但是您的常数确实很小 - 通常只是一个指针比较。