【问题标题】:Can't Understand 1 Line of Code in C++ STL Source: Lower_Bound/Upper_Bound无法理解 C++ STL 中的 1 行代码 来源:Lower_Bound/Upper_Bound
【发布时间】:2014-12-06 02:48:27
【问题描述】:

我正在编写一些代码来查找值不超过 PHP 给定整数的最后一个键。
例如,数组(0=>1,1=>2,2=>3,3=>3,4=>4)。给定整数 3,我会找到键 3。(二分查找)

我在 Internet 上查找了一些关于二进制搜索的参考资料。
我找到了这个,即找到值不小于 C++ 给定整数的第一个键。
它说:

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;        //    <======this line
  }
  return __first;
}

好吧,为什么要使用“__len = __half;”而不是“__len = __half + 1;”?
“_middle”在每个循环中引用的键/值不会在这个二进制搜索过程中被遗忘并丢失吗?
我的意思是,这两个“__len”似乎不会加起来完整的“__len”,似乎__middle已被跳过

PS: 我的原始问题的 PHP 代码是:

$cid_start  = $count - 1;
$len        = $count;
while($len > 0){
    $half   = $len >> 1;
    $middle = $cid_start - $half;
    if($c_index[$middle][1] > $time_start){
        $cid_start = $middle - 1;
        $len       = len       - $half - 1;
    }else{
        $len       = $half + 1;
    }
}

它会起作用吗?还是会出错?
当我在数组中找不到任何内容时,如何获得 -1 或其他结果?

【问题讨论】:

  • 它会工作吗?还是会出错?”你试过运行它吗?
  • 任何标准库源都不应真正用作参考,除非专门为此目的而制作。您应该能够找到更好的源代码示例来学习。
  • “在每个循环中“_middle”所指的键/值不会在这个二进制搜索过程中被遗忘并丢失吗?”if 块中...
  • @Celeo ,我试着用笔和纸一步一步地运行它,结果让我很困惑。
  • @lightness-races-in-orbit , emm...怎么样?

标签: php c++ stl binary-search lower-bound


【解决方案1】:

二分查找的算法非常简单。

/**
 * Search $value in $array
 * Return the position in $array when found, -1 when not found
 * $array has numeric consecutive keys (0..count($array)-1)
 * $array is sorted ascending; this condition is mandatory for binary search
 * if $array is not sorted => the output is rubbish
 */
function search($value, array $array)
{
    // At each step search between positions $start and $end (including both)
    $start = 0;
    $end   = count($array) - 1;

    // End when the search interval shrunk to nothing
    while ($start <= $end) {
        // Get the middle of the interval
        // This is shorter and faster than intval(($start + $end) / 2)
        $middle = ($start + $end) >> 1;

        // Check the value in the middle of the current search interval
        if ($value == $array[$middle]) {
            // Found
            return $middle;
        }

        // Not found yet; the binary step: choose a direction
        if ($value < $array[$middle]) {
            // Search in the left half
            $end = $middle - 1;
        } else {
            // Search in the right half
            $start = $middle + 1;
        }
    }

    // Not found
    return -1;
}

【讨论】:

    【解决方案2】:

    只是为了回答“为什么不……?”问题:这个算法的工作方式略有不同。如果下界实际上是第一个元素,我们就会遇到问题。

    __len 将减半直到 2:

    while (__len > 0)
    {
        __half = __len >> 1; // __half is __len/2 floored
    
        __middle = __first + __half; // Assuming random access iterators, simplified
    
        if (*__middle < __val) // Lower bound is __first, so *__middle >= __val
        {
          // […]
        }
        else
          __len = __half + 1; // .. self-explanatory
    }
    

    ,然后我们得到一个无限循环。即,当__len == 2:

    while (__len > 0) // Okay, 2 > 0
    {
        __half = __len >> 1; // __half is now 2 >> 1, which is 1
    
        __middle = __first + __half; // Rewritten for clarity. __middle == __first.
    
        if (*__middle < __val) // lower bound is at __first, so *__middle >= __val
        {
          // […]
        }
        else
          __len = __half + 1; // __len is 1 + 1 == 2
    } // Endless loop
    

    如果分配的长度本身是 __half,则不会发生这种情况 - 那么对于 __len == 2,我们得到 1,对于 __len == 1,我们得到 0。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-26
      • 2021-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-19
      相关资源
      最近更新 更多