c ++中的交叉向量

时间:2015-07-13 16:53:17

标签: c++ c++11 vector

我的vector<vector<int> > A;大小为44,000。现在我需要将'A'与另一个向量相交:vector<int> B,大小为400,000。 A矢量的内部矢量的大小是可变的,并且最大大小为9,000个元素,我使用以下代码:

for(int i=0;i<44000;i++)
  vector<int> intersect;
  set_intersection(A[i].begin(),A[i].end(),B.begin(),B.end(),
                std::back_inserter(intersect));

我是否有某种方法可以使代码高效。矢量A中的所有元素都被排序,即它们的形式为((0,1,4,5),(7,94,830,1000)), etc。也就是all elements of A[i]'s vector < all elements of A[j]'s vector if i<j.

编辑:我想到的解决方案之一是使用以下方法将所有A [i]合并到另一个向量mergedB中:

  vector<int> mergedB;
  for(int i=0;i<44000;i++)
       mergedB.insert(mergedB.begin(),mergedB.end(),A[i])
  vector<int> intersect;
  set_intersection(mergedB.begin(),mergedB.end(),B.begin(),B.end(),
                std::back_inserter(intersect));

但是,我没有理由为什么我的两个代码的性能几乎相同。有人可以帮我理解这个

2 个答案:

答案 0 :(得分:1)

碰巧,set_itersection很容易写。

一种奇特的方法是创建一个连接迭代器,并遍历lhs向量的每个元素。但手动编写set_intersection更容易。

template<class MetaIt, class FilterIt, class Sink>
void meta_intersect(MetaIt mb, MetaIt me, FilterIt b, FilterIt e, Sink sink) {
  using std::begin; using std::end;
  if (b==e) return;
  while (mb != me) {
    auto b2 = begin(*mb);
    auto e2 = end(*mb);
    if (b2==e2) {
      ++mb;
      continue;
    }
    do {
      if (*b2 < *b) {
        ++b2;
        continue;
      }
      if (*b < *b2) {
        ++b;
        if (b==e) return;
        continue;
      }
      *sink = *b2;
      ++sink; ++b; ++b2;
      if (b==e) return;
    } while (b2 != e2);
    ++mb;
  }
}

这不会复制元素,而不是复制到输出向量中。它假设MetaIt是容器的迭代器,FilterIt是兼容容器的迭代器,Sink是输出迭代器。

我试图删除所有冗余比较,同时保持代码可读性。有一个冗余检查 - 在我们用完rhs内容的单个案例中检查b!=e然后b==e。因为这应该只发生一次,清晰度的成本是不值得的。

您可以通过现代硬件上的矢量化使上述效率更高。我不是那方面的专家。将矢量化与元迭代混合是很棘手的。

答案 1 :(得分:0)

由于您的向量已排序,因此最简单,最快的算法将是

  1. 将两个向量的当前元素设置为第一个值
  2. 比较两个当前元素。如果相等,你有一个交互,所以增加两个向量&#39;
  3. 如果不相等则增加具有最小当前元素的向量。
  4. 转到2。