在std :: lower_bound中没有小问题?

时间:2015-04-02 15:53:34

标签: c++ algorithm std time-complexity lower-bound

为什么std::lower_bound( )中的第一步没有重要的比较?

初始步骤std::lower_bound将迭代器it从列表中的first更改为中心位置:

step = std::distance(first,last) / 2;
it = std::advance(first, step);

之后,算法开始将该中心 - it与给定的value进行比较:

if (*it < value) { ... } else { ... }

但是重要的案例是在重新定位it之前将一个比较作为初始步骤:

if (value < *first) return last;
// else start original algorithm ...

想象一下,有一个非常长的列表,您仍然需要等到当前形式的std::lower_bound实现,value < *first为真。当然它是 O(log_2(最后 - 第一个)),但在这种情况下它可能是 O(1),只有一个额外的行。

1 个答案:

答案 0 :(得分:2)

这种实现lower_bound的方式允许你做这个简单的检查,否则你总是被迫做这个检查。在&#34;意义上,你不会为你不能使用的东西买单&#34;这对我来说很有意义。

因为lower_bound仅适用于排序结构,所以如果您认为值得,可以始终与第一个元素进行比较。

尽管如此,实际的实现看起来不同,因此一些STL实现可能实际上进行了此检查。

SGI的实施,例如看起来像这样(检查未完成!):

template <class _ForwardIter, class _Tp, class _Distance>
_ForwardIter __lower_bound(_ForwardIter __first, _ForwardIter __last,
                           const _Tp& __val, _Distance*) 
{
  _Distance __len = 0;
  distance(__first, __last, __len);
  _Distance __half;
  _ForwardIter __middle;

  while (__len > 0) {
    __half = __len >> 1;
    __middle = __first;
    advance(__middle, __half);
    if (*__middle < __val) {
      __first = __middle;
      ++__first;
      __len = __len - __half - 1;
    }
    else
      __len = __half;
  }
  return __first;
}

template <class _ForwardIter, class _Tp>
inline _ForwardIter lower_bound(_ForwardIter __first, _ForwardIter __last,
                const _Tp& __val) {
  __STL_REQUIRES(_ForwardIter, _ForwardIterator);
  __STL_REQUIRES_SAME_TYPE(_Tp,
      typename iterator_traits<_ForwardIter>::value_type);
  __STL_REQUIRES(_Tp, _LessThanComparable);
  return __lower_bound(__first, __last, __val,
                       __DISTANCE_TYPE(__first));
}