检查向量C 中的常见成员

Check for common members in vector c++

本文关键字:常见 成员 向量 检查      更新时间:2023-10-16

验证多个向量中是否有共同成员的最佳方法是什么?向量不一定具有相等的大小,它们可能包含自定义数据(例如包含两个代表2D坐标的整数的结构)。

例如:

vec1 = {(1,2); (3,1); (2,2)};
vec2 = {(3,4); (1,2)};

如何验证两个向量是否具有共同成员?

请注意,我正在尝试避免无缺的方法,例如浏览所有元素并检查相等的数据。

对于非平凡数据集,最有效的方法可能是对两个向量进行排序,然后使用std :: set_intersection函数定义在中,如下所示:

#include <vector>
#include <algorithm>

using namespace std;
typedef vector<pair<int, int>> tPointVector;
tPointVector vec1 {{1,2}, {3,1}, {2,2}};
tPointVector vec2 {{3,4}, {1,2}};
std::sort(begin(vec1), end(vec1));
std::sort(begin(vec2), end(vec2));
tPointVector vec3;
vec3.reserve(std::min(vec1.size(), vec2.size()));
set_intersection(begin(vec1), end(vec1), begin(vec2), end(vec2), back_inserter(vec3));

,如果您不需要知道哪些元素不同,而只有共同元素的数量,则可以通过非标准算法获得更好的性能,因为这样您可以避免创建共同元素的新副本。

无论如何,在我看来,通过对两个容器进行排序,将为您提供最佳的性能,其中包括几十个元素。

这是一个尝试编写算法的尝试,该算法只为您提供匹配元素的计数(未经测试):

auto it1 = begin(vec1);
auto it2 = begin(vec2);
const auto end1 = end(vec1);
const auto end2 = end(vec2);
sort(it1, end1);
sort(it2, end2);
size_t numCommonElements = 0;
while (it1 != end1 && it2 != end2) {
    bool oneIsSmaller = *it1 < *it2;
    if (oneIsSmaller) {
        it1 = lower_bound(it1, end1, *it2);
    } else {
        bool twoIsSmaller = *it2 < *it1;
        if (twoIsSmaller) {
            it2 = lower_bound(it2, end2, *it1);
        } else {
            // none of the elements is smaller than the other
            // so it's a match
            ++it1;
            ++it2;
            ++numCommonElements;
        }
    }
}

请注意,我正在尝试避免无缺的方法,例如浏览所有元素并检查相等的数据。

您需要至少浏览所有元素一次,我认为您暗示您不想检查所有组合。确实您不想这样做:
对于VEC1中的所有元素,请仔细阅读整个VEC2以检查该元素是否在此处。如果您的向量有大量元素,这将不会有效。

如果您喜欢线性时间解决方案,并且不介意使用额外的内存是您可以做的:

您需要一个哈希功能才能将元素插入unordered_map或unordered_set中 请参阅https://stackoverflow.com/a/13486174/2502814

// next_permutation example
#include <iostream>     // std::cout
#include <unordered_set> // std::unordered_set
#include <vector>       // std::vector
using namespace std;

namespace std {
  template <>
  struct hash<pair<int, int>>
  {
    typedef pair<int, int>      argument_type;
    typedef std::size_t  result_type;
    result_type operator()(const pair<int, int> & t) const
    {
       std::hash<int> int_hash;
       return int_hash(t.first + 6495227 * t.second);
    }
  };
}

int main () {
  vector<pair<int, int>> vec1 {{1,2}, {3,1}, {2,2}};
  vector<pair<int, int>> vec2 {{3,4}, {1,2}};

  // Copy all elements from vec2 into an unordered_set
  unordered_set<pair<int, int>> in_vec2;
  in_vec2.insert(vec2.begin(),vec2.end());
  // Traverse vec1 and check if elements are here
  for (auto& e : vec1)
  {
    if(in_vec2.find(e) != in_vec2.end()) // Searching in an unordered_set is faster than going through all elements of vec2 when vec2 is big.
    {
      //Here are the elements in common:
      cout << "{" << e.first << "," <<  e.second << "} is in common!" << endl;
    }
  }
  return 0;
}

输出:{1,2}共有!

您可以执行此操作,也可以将VEC1的所有元素复制到unordered_set中,然后将VEC2 traverse vec2复制。根据VEC1和VEC2的尺寸,一种解决方案可能比另一个解决方案更快。请记住,选择较小的向量将其插入Unordered_set也意味着您将使用较少的额外内存。

我相信您使用2D树在2个dimenstions中搜索。您指定的问题的最佳算法将属于几何算法类别。也许此链接对您有用:http://www.cs.princeton.edu/courses/archive/fall05/cos226/lectures/geosearch.pdf。