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

Posted

技术标签:

【中文标题】使用迭代器按谓词重新排列【英文标题】:Rearrange by predicate using iterators 【发布时间】:2017-10-10 19:35:54 【问题描述】:

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

我的算法是

开始迭代序列 如果当前元素不满足谓词,则将其替换为最后一个 再次检查同一位置的新元素是否满足它 如果不替换为 (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

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

【问题讨论】:

我希望在 18 年前,当工作从 VB6 转移到 C++ 和 C# 时,我再也不必与 goto 打交道了。 【参考方案1】:

如果输入范围非空且其中没有元素满足谓词,您的代码将卡在goto 循环中,无法再次到达while。最终,--end 将在first 之前使用end

如果这是一个学习练习,我建议你摆脱goto;你不想学习不好的做法,虽然goto 可能有很少的合法用途,但替换循环不是其中之一。另外,tmp 的舞蹈可以替换为std::swap

如果这不是一个学习练习,只需使用 std::partition 即可。

【讨论】:

以上是关于使用迭代器按谓词重新排列的主要内容,如果未能解决你的问题,请参考以下文章

根据谓词插入不同容器的插入器迭代器

如何正确声明从非常量迭代器到指针的 const 指针

性能提升1400+倍,快来看MySQL Volcano模型迭代器的谓词位置优化详解

C ++迭代器模型与Java迭代器模型[关闭]

如何在 Java 中实现过滤迭代器?

计数和迭代序列的排列