【问题标题】:intersecting vectors in c++C ++中的相交向量
【发布时间】:2015-07-14 05:23:59
【问题描述】:

我有一个大小为 44,000 的 vector<vector<int> > A;。现在我需要将“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 &lt; all elements of A[j]'s vector if i&lt;j.

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

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

但是,我不明白为什么我使用两种代码获得几乎相同的性能。有人可以帮我理解这一点

【问题讨论】:

  • @BaummitAugen 解决方案是使用 back_inserter ......但我的问题在这里不同......我的向量 A 已排序......我正在寻找一种更有效的方法来相交它...
  • @StegVerner 我相信您可以通过从向量构造两个unordered_maps 来使运算成为线性而不是二次。
  • @TheParamagneticCroissant 你能用一个例子解释一下吗
  • 相交的结果是什么? A 和 B 中都存在的向量

标签: c++ c++11 vector


【解决方案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 是输出迭代器。

我试图删除所有多余的比较,同时保持代码的可读性。有一个冗余检查——我们检查b!=e 然后b==e 在我们用完rhs 内容的单一情况下。由于这应该只发生一次,因此为清晰而付出的代价是不值得的。

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

【讨论】:

  • @ComeRaczy 谢谢,我确实错过了++mb。但是我您的编辑有一些我试图避免的冗余检查。你会检查b!=eb==e 的额外次数等于我相信的MetaIt 容器的数量。我同意你的更干净,我有一个错误就证明了这一点!
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2013-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-15
    • 2010-09-16
    • 2011-09-07
    • 1970-01-01
    • 2015-09-12
    相关资源
    最近更新 更多