【问题标题】:Check for common members in vector c++检查向量 C++ 中的常见成员
【发布时间】:2014-01-28 16:08:13
【问题描述】:

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

例如:

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

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

请注意,我试图避免使用无效的方法,例如遍历所有元素并检查相等的数据。

【问题讨论】:

  • 您需要遍历所有元素(或注意将它们添加到向量中)。除了向量之外,您还可以保留 std::setstd::unordered_set 元素。
  • 如果您遍历所有元素并检查是否相等,您希望如何找到匹配项?您必须检查答案,您可以构建一个“猜测”算法,但这只有在您事先知道结构时才有效。由于它们是向量,您可以可能迭代以找到一个接近的位置,但不确定这是否更有效。

标签: c++ vector compare


【解决方案1】:

对于非平凡的数据集,最有效的方法可能是对两个向量进行排序,然后使用定义的 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;
        }
    }
}

【讨论】:

  • 感谢您提供有用的答案,我在这个网站上学到了很多东西。实际上,我不得不采用另一种方法来解决我的问题,但这些都是很好的答案。
【解决方案2】:

请注意,我试图避免使用无效的方法,例如遍历所有元素并检查相等的数据。

您需要至少检查所有元素一次,我假设您暗示您不想检查每个组合。确实你不想这样做:
对于 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。 根据 vec1 和 vec2 的大小,一种解决方案可能比另一种更快。 请记住,选择较小的向量插入 unordered_set 也意味着您将使用更少的额外内存。

【讨论】:

  • 感谢您提供有用的答案,我在这个网站上学到了很多东西。实际上,我不得不采用另一种方法来解决我的问题,但这些都是很好的答案。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 2011-04-04
    • 1970-01-01
    • 1970-01-01
    • 2016-08-16
    • 1970-01-01
    • 1970-01-01
    • 2013-06-26
    • 2021-03-08
    • 2013-11-12
    相关资源
    最近更新 更多