在C ++中的大向量内搜索

时间:2017-06-06 08:13:26

标签: c++ c++11

我有以下向量:

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

vec_pair的大小远远大于vec的大小。我想在vec_pair中找到一对,其中两个成员都在vec内部。

vec_pair的内容是不变的。但是,每次迭代后,vec的内容都会发生变化,我想再次进行测试。

我知道我可以做一个for循环并做检查。但是考虑到尺寸差异工作的重现,我正在寻找一种智能且高效的方法。

5 个答案:

答案 0 :(得分:3)

如果您不打算更改vec的内容,请创建具有相同内容的std::unordered_set<A*>并搜索其中的匹配项。在unordered_set中搜索大约为O(1),因此这将是一个简单的胜利。

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

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

答案 1 :(得分:2)

  

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来加快操作速度。

答案 2 :(得分:2)

您可以使用unordered_set(您真的不需要map),这允许O(1) 搜索插入

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
    }
}

答案 3 :(得分:1)

我不知道你的确切要求但是,如果vec_pair中元素的顺序不重要,我想你可以用std::multimap代替它,或者我想更好,{ {1}}。

我的意思是(使用等于std::unordered_multimap的{​​{1}}类型代替)

A

你可以使用

int

如果您需要 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)(这很少,如果我理解正确,您可以按以下方式检查对< / p>

unordered_set

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

另一种方法是使用map和set(unorderd,better)的组合而不是

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;
    }

在这种情况下,搜索部分更优雅(恕我直言)

   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}} };

答案 4 :(得分:0)

vec比vec_pair小多少? vec大小的平方是否仍然小于vec_pair的大小?如果是这样,你从vec_pair中创建一个unordered_set,然后搜索从vec中的两个东西生成的每个可能的对。

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