【问题标题】:check if second to last in an iterator检查迭代器中是否倒数第二个
【发布时间】:2014-07-19 02:55:57
【问题描述】:

是否有一种干净的方法来检查我当前是否位于 C++ 迭代中的倒数第二个元素?如:

for (vector::iterator it = v.begin(); it < v.end(); ++it)
{
   if (it points to second to last element)
      cout << "at second to last";
}

【问题讨论】:

  • 检查迭代器的位置对双向迭代器和前向迭代器更有意义。对于随机访问迭代器,你还不如只使用索引。

标签: c++ stl iterator


【解决方案1】:

最简单的方法是将您的迭代器与确实指向倒数第二个的迭代器进行比较。一个简单的方法是:

vector::iterator secondLast = v.end() - 2;

当然假设v.size() &gt;= 2。但以上内容并未推广到其他容器类型,您可以这样做:

vector::iterator secondLast = (++v.rbegin()).base();

这应该从最后一个元素倒退一步,然后转换为常规(正向)迭代器。这将适用于列表等其他容器类型。

或者对于一般解决方案可能更清楚:

vector::iterator secondLast = v.end();
std::advance(secondLast, -2);

同样,这需要大小为 2 和随机访问或双向类型的迭代器。

最后,一个 C++11 解决方案:

auto secondLast = std::prev(v.end(), 2);

【讨论】:

  • std::prev(v.end(), 2)也可以用。
  • @0x499602D2,不适用于forward_iterators,仅适用于双向,同样适用于std::advance
  • @vsoftco:我发布的解决方案都不适用于纯正向迭代器。
  • @JohnZwinck 抱歉,我现在才看到你的最后一行。对于最通用的迭代器,我想一个不能比O(n) 做得更好,但你的解决方案对于双向迭代器来说绝对是优雅的。
  • @JohnZwinck, std::advance 获取对迭代器的引用,然后将其推进,并返回 void。您可能指的是std::prev(v.end(), -2)std::advance(secondLast, -2),其中secondLast 之前已初始化为v.end()
【解决方案2】:

试试这样的:

vector::iterator end = v.end(), stl;
bool has_stl = (v.size() >= 2);
if (has_stl) stl = end-2;

for (vector::iterator it = v.begin(); it < end; ++it)
{
   if ((has_stl) && (it == stl))
      cout << "at second to last";
}

【讨论】:

    【解决方案3】:

    你可以用一些容器做到这一点:

    #include <iostream>
    #include <vector>
    
    int main() {
        std::vector<int> vec {1, 2, 3, 4, 5}; 
        for (auto it = vec.begin(); it != vec.end(); it++) {
            if (vec.end() - it == 3) {
                std::cout << *it << std::endl;
            }
        }   
        return 0;
    }
    

    【讨论】:

      【解决方案4】:

      以下解决方案:

      auto pos = std::next(std::begin(v), std::distance(std::begin(v), std::end(v))-2);
      for (auto it = std::begin(v); it != std::end(v); ++it)
      {
         if (it == pos)
            cout << "at second to last: " << *pos;
      }
      

      pos 现在是一个指向倒数第二个位置的迭代器,而函数std::nextstd::distance 使用可能的最佳实现(即随机迭代器的恒定复杂度,双向/前向迭代器的线性复杂度)。

      【讨论】:

      • end() 在最后一个元素之后返回一个迭代器,因此end-1 将是最后一个元素,end-2 将是发送到最后一个元素。
      • @RemyLebeau,绝对正确,我修改了它,感谢您的关注。
      • 这不是正向或双向迭代器最有效的解决方案。想象一下将它与列表一起使用:首先您遍历整个列表以查找distance,然后再次遍历next,然后再进行实际工作。双向的最优是 O(1) 而不是 O(n),对于前向迭代器来说最优的是单遍(具有恒定空间),而不是两遍。
      • @JohnZwinck,嗯,你是对的,忘记了距离的复杂性。我猜以前的解决方案(我设法删除)更好。 O(1) 用于随机迭代器(不是双向的),这就是你的意思,对吧?
      • @vsoftco: 不,O(1) 用于双向,因为你从最后开始并向后退两个,如我的回答中所见(它不支持仅向前的迭代器——那些是当然仍然是 O(n)。
      猜你喜欢
      • 2016-10-31
      • 2011-09-19
      • 1970-01-01
      • 1970-01-01
      • 2018-12-15
      • 2011-12-18
      • 2021-02-20
      • 2011-01-04
      • 2019-04-26
      相关资源
      最近更新 更多