std :: reverse是否有冗余操作?

时间:2015-10-29 20:52:05

标签: c++ algorithm optimization

通过挑战<algorithm>图书馆,我即将前往没有人去过的地方。

根据cplusplus.com,其实施等同于

template <class BidirectionalIterator>
  void reverse (BidirectionalIterator first, BidirectionalIterator last)
{
  while ((first!=last)&&(first!=--last)) {
    std::iter_swap (first,last);
    ++first;
  }
}

这是最佳解决方案吗?

(first!=last)&&(first!=--last)

对我来说是个红旗。如果可以将BidirectionalIterator<进行比较,那么

while ( first < last ) iter::swap(first++,--last);

将减少操作。例如,假设我们有

int arr [] = { 1, 2, 3, 4, 5 };
std::reverse(arr, arr+sizeof(arr)/sizeof(int));

两个程序涉及的比较和增量是

  1. --last
  2. ++first
  3. first!=last
  4. first!=X其中X是第1步的结果
  5. A&&B(结果隐式检查是否为非零)其中A是步骤3的结果而B是步骤4的结果
    1. --last
    2. first < A其中A是第1步的结果
    3. ++first
    4. 在我的解决方案中。

      所以,请向我解释为什么C ++ reverse算法的实现方式。

      此致 Mike Rowe Optimeiser

2 个答案:

答案 0 :(得分:1)

首先,请不要在此引用cplusplus.com。这是一个糟糕的网站。不要相信那里的一句话。

如果您对特定库中特定算法的实现感到好奇,那么请自行检查。例如,这是来自gcc 4.8.3(逐字复制,除了删除空行):

  template<typename _BidirectionalIterator>
    inline void
    reverse(_BidirectionalIterator __first, _BidirectionalIterator __last)
    {
      ;
      std::__reverse(__first, __last, std::__iterator_category(__first));
    }

这是随机访问迭代器的实现:

  template<typename _RandomAccessIterator>
    void
    __reverse(_RandomAccessIterator __first, _RandomAccessIterator __last,
       random_access_iterator_tag)
    {
      if (__first == __last)
 return;
      --__last;
      while (__first < __last)
 {
   std::iter_swap(__first, __last);
   ++__first;
   --__last;
 }

如您所见,它使用<

这是双向迭代器的一个:

  template<typename _BidirectionalIterator>
    void
    __reverse(_BidirectionalIterator __first, _BidirectionalIterator __last,
       bidirectional_iterator_tag)
    {
      while (true)
 if (__first == __last || __first == --__last)
   return;
 else
   {
     std::iter_swap(__first, __last);
     ++__first;
   }
    }

这个经过仔细检查。

答案 1 :(得分:0)

双向迭代器接口不提供小于/大于关系的运算符。它只满足前向迭代器的等式/不等式运算符要求,因此严格针对双向迭代器接口编写的代码不能使用operator<

您可以理解为什么双向迭代器无法通过想象双链表来提供这样的关系运算符。如果迭代器只存储诸如指向列表节点的指针之类的状态,那么它就能够前进和后退,但是不能有一个有意义的概念,而不是&#34;小于&#34;或者&#34;大于&#34;只给予那个州。有足够的信息来提供一个有意义的概念&#34;小于&#34;或者&#34;大于&#34;通常意味着我们已经可以实现一个随机访问迭代器,它是双向接口的超集。

鉴于双向迭代器要求,您展示的代码似乎完全合理。这将是将其概括为用于双向链接列表所需的代码类型,例如,而不仅仅是vectordeque之类的随机访问序列。但是,它只是一种可能的实现方式,没有什么可以阻止供应商进一步扩展它。

当然,这也不排除供应商提供针对随机访问迭代器优化的版本,除了使用迭代器标记或类型特征的等式/不等式之外,它实际上提供了关系运算符运算符。然而,严格的双向迭代器版本(最通用的版本)需要避免关系运算符。