无法理解 C++ STL 中的 1 行代码 来源:Lower_Bound/Upper_Bound
Can't Understand 1 Line of Code in C++ STL Source: Lower_Bound/Upper_Bound
我正在编写一些代码来查找最后一个键,其值不超过 PHP 的给定整数。
例如,array(0=>1,1=>2,2=>3,3=>3,4=>4)。给定整数 3,我将找到键 3。(二叉搜索)
我在互联网上寻找了一些关于二进制搜索的参考资料。
我找到这个,即找到第一个键,其值不小于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
附注:我最初问题的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 或其他东西作为结果?
二叉搜索的算法非常简单。
/**
* 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;
}
只是为了回答"为什么不......?"问题:这个算法的工作方式略有不同。如果下限实际上是第一个元素,我们会遇到问题。
__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。
相关文章:
- 如何确定包含路径的来源?
- OpenGL 调试上下文警告 -"将使用视频内存作为缓冲区异议的来源
- CMakeLists.txt:(add_executable):没有给目标提供来源:教程
- 空集"Out of bound iterator"
- 如何找出 Kernel32 依赖项的来源
- Rcpp - 来源Cpp - 未定义的符号
- 找不到小内存泄漏的来源
- 从模板实例化/类型推断中查找错误消息的实际来源
- 安装了要来源的特征cmake目标点包括但不安装
- 如何使用 Valgrind 确定内存泄漏"still-available"来源?
- 跟踪非管理C#代码中违反访问的来源
- 从Visual Studio中的来源构建外部库
- 从来源建立咖啡馆的麻烦
- 如何从 VisualStudio 获取更多详细信息以跟踪警告的来源
- 从多个来源检查NULL:共享_ptr vs double指针
- 我的3D OpenGL对象围绕世界来源,而不是本地空间来源.我在做什么错或误会
- 将COUT从C 中的各种来源重定向到同一文件
- 来自多个来源的关于BFS的TLE
- 标题中存在未申报的标识符 - 亮度,但在班级来源中未知
- 我在哪里可以找到dynamic_cast来源