【问题标题】:How to filter vector elements relative to other ones?如何过滤相对于其他元素的矢量元素?
【发布时间】:2013-09-24 15:21:05
【问题描述】:

I 一个向量的向量,每个向量代表一个集合(在数学意义上)。例如:

{{1, 3}, {4, 9, 14}, {1, 3}, {1, 4, 8, 9, 10, 14, 16}, {1, 3, 9}, {4, 9, 17, 22}}

我想让最有效的 C++ 函数能够过滤(如果可能的话)向量,以便删除包含另一个的每个项目。

例如,这里:

  • {1, 3} 包含在 {1, 3}{1, 3, 9}
  • {4, 9, 14} 包含在 {1, 4, 8, 9, 10, 14, 16}

结果向量将是:

{{1, 3}, {4, 9, 14}, {4, 9, 17, 22}}

当我开始使用 C++ 时,我真的不知道如何有效地做到这一点。我在这里的其他答案中发现了擦除/删除习语,这在这里似乎不太合适,除非通过将擦除闭包作为谓词传递。这在 C++ 中似乎不太习惯。

请注意,保持原始顺序无关紧要,每个集合中值的顺序也不重要。

【问题讨论】:

  • 如果您保持每个向量的排序顺序,那么您应该能够相当有效地做到这一点。
  • {1, 3, 9} 还是 {1, 3, 18}?
  • 我想你可以按照 Kerrek 所说的去做:对向量进行排序,然后使用带有适当比较函数的 std::unique 之类的东西。
  • 对每个向量进行排序,然后按字典顺序对整个集合进行排序。完成后,您可以穿越,只需要期待看看是否有适当的遏制。
  • “包含”是部分排序。执行拓扑排序,然后丢弃除叶子之外的所有内容。拓扑排序在顶点数加上边数上是线性的;在您的情况下,边数可能是二次的(例如 {{1}, {1, 2}, {1, 2, 3} ...} ),因此该算法是二次最坏情况,但如果图形更稀疏可能会更好。

标签: c++ algorithm vector stl filter


【解决方案1】:

鉴于我目前学到的知识,感谢您非常帮助的 cmets,我想出的解决方案是:

struct std::vector<size_t> colset;

bool less_colsets(const colset& a, const colset& b) {
  return a.size() < b.size();
}

void sort_colsets(std::list<colset>& l) {
  l.sort(less_colsets);
}

void strip_subsets(std::list<colset>& l) {
  sort_colsets(l);
  for (std::list<colset>::iterator i = l.begin(); i != l.end(); ++i) {
    std::list<colset>::iterator j = next(i, 1);
    while (j != l.end()) {
      if (includes((*j).begin(), (*j).end(), (*i).begin(), (*i).end())) {
        j = l.erase(j);
      }
      else {
        ++j;
      }
    }
  }
}

请注意,我用std::list 替换了最外层的std::vector,这对任何地方的元素删除都进行了优化。

这似乎按预期工作,但我需要更多测试来证明这一点。 下一步将使用比includes 更有效的比较函数,这将考虑到每个向量都是按词法排序的事实(程序保证)。我明天试试这个。

编辑:看起来std::includes 已经处理了这个事实。耶!

谢谢大家。

【讨论】:

  • std::includes 要求对两个范围都进行排序,并且正在使用此属性。它的复杂性在两个范围的总长度上是线性的。
  • 我没有看到那个属性...似乎比我当时想象的还要好。太好了!
猜你喜欢
  • 1970-01-01
  • 2017-04-22
  • 2013-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-12
  • 1970-01-01
相关资源
最近更新 更多