【问题标题】:how to extend range with end() iterator如何使用 end() 迭代器扩展范围
【发布时间】:2015-06-05 03:35:52
【问题描述】:

(不确定这是正确的任务) 我正在编写与经典排序相关的 stl 风格的算法。 原型是:

  template<typename RAIter>
  void Algo(RAIter first, RAIter last) {
  ....
    size_t size = std::distance(first, last);
    RAIter midIter =first;
    std::advance(midIter, size / 2 - 1);

    Algo(first, midIter);
    Algo(midIter + 1, last);
    ....
 }

但它对我来说不能正常工作,因为, 最初它的范围如下: 向量 v; 算法(v.begin(),v.end()); 但是,在内部,在递归调用中,子范围不包含 end() 元素。

在这种情况下,典型的技术是什么?

【问题讨论】:

  • 您的算法不一致。您调用它时排除了结尾,但您递归地调用了结尾同时包含和排除了它。
  • 其实问题是 - 如何为内部调用添加 end() 元素
  • 如果内部调用的合约与用户调用的合约不同,则需要不同的函数。
  • 问题:为什么递归调用需要end() 元素?我想不出任何需要这些信息的经典排序算法。
  • 传递结束元素是 stl 中的常见做法,所有算法都使用范围 [first, last)

标签: c++ stl iterator stl-algorithm


【解决方案1】:

我会提出两个选择。

  1. (首选)使算法在内部不需要包含last。在您的情况下,可以这样做:

    template<typename RAIter>
    void Algo(RAIter first, RAIter last) {
        ....
        size_t size = std::distance(first, last);
        if (size <= 1) {
             // special processing of single-item or empty range
             return;
        }
    
        RAIter midIter =first;
    
        std::advance(midIter, size / 2);
    
        Algo(first, midIter); // midIter not included
        Algo(midIter, last);  // it's included here instead
    }
    
  2. 创建一个单独的函数,该函数期望包含last 的范围:

    template<typename RAIter>
    void AlgoImpl(RAIter first, RAIter last) {
        ....
        // looks like this is more correct:
        // size_t size = std::distance(first, last) + 1;
        size_t size = std::distance(first, last);
        RAIter midIter =first;
        std::advance(midIter, size / 2 - 1); // and here "- 1" seems wrong 
    
        AlgoImpl(first, midIter);
        AlgoImpl(midIter + 1, last);
        ....
    }
    
    template<typename RAIter>
    void Algo(RAIter first, RAIter last) {
        if (first == last) {
            return;
        }
        AlgoImpl(first, last - 1);
    }
    

【讨论】:

  • 例如容器有 6 个元素。使用 end() 进行初始调用,距离返回 6,但在下一步中,它返回 2 而不是预期的 3,这很清楚,因为初始调用包含 7 个元素和结束,但下一次调用仅获取 3 个元素并且没有结束。
  • @amigo421 注意std::advance(midIter, size / 2); 不是size / 2 - 1。 BTW size/2 - 1 在这两种情况下都是错误的,我只是没有编辑第二个。
  • @amigo421 但可能你不会将范围分成相等的部分,谁知道呢
  • 这是合并排序(用于内部排序)的学习示例,您的第二种方式对我来说看起来不错,但是,当然,我更喜欢在单个函数中实现这种方式
猜你喜欢
  • 2020-10-14
  • 1970-01-01
  • 2012-03-08
  • 1970-01-01
  • 2014-09-08
  • 1970-01-01
相关资源
最近更新 更多