使用迭代器按谓词重新排列

时间:2017-10-10 19:35:54

标签: c++ algorithm sorting iterator

在具有给定签名的函数中,我想以这样的方式重新排列序列[first,last]的元素,使得满足谓词的所有元素都放在那些不需要的元素之前,并将迭代器返回给第一个元素并不满足给定的谓词。

我的算法是

  • 开始按顺序迭代
  • 如果现有元素不满足谓词,则将其替换为最后一个
  • 再次检查同一位置上的新元素是否满足
  • 如果没有将其替换为(last-1),如果是,则继续进行
  • 重复,直到我们到达我们已经替换的其中一个元素

我的代码

template<class Iterator, class Predicate>
Iterator Rearrange(Iterator first, Iterator last, Predicate pred) {
  auto res = first;
  if (first == last) {
    ;
  }
  else {
    auto run = first;
    auto end = last;
    auto tmp = *first;
    while (run != end) {
      if (pred(*run) == false) {
      again: tmp = *(--end);
    *end = *run;
    *run = tmp;
    if (pred(*run) == false) {
      goto again;
    }
      }
      ++run;
    }
  }
  return res;
}

它给了我

terminate called after throwing an instance of 'std::range_error'
  what():  dereferencing end of sequence
Aborted

我无法找到并理解。也就是说,我可以读到某个地方,我试图在容器之外取消引用元素,但在我的程序中无法看到它。任何人都可以帮我修复编码错误或改进我的算法逻辑吗?

1 个答案:

答案 0 :(得分:3)

如果输入范围非空且其中没有元素满足谓词,则代码将停留在goto循环中,而不会再次到达while。最终,--end会在end之前first。{/ p>

如果这是一次学习练习,我建议你摆脱goto;你不想学习不好的做法,而goto可能有罕见的合法用途,替换循环不是其中之一。此外,tmp的舞蹈可以替换为std::swap

如果这不是一个学习练习,只需使用std::partition,它就能完全符合您的要求。