简而言之就是一分为二的去查找,一种常用的查找方式。
```CPP
/* 对一个队列进行二分,这里考虑的总是有解的情况的整数二分 */
int find(int x){
int l = 0, r = q.size() - 1;
/* 一定有解的情况,在r=l时循环结束 */
while(r > l){
/* 这里的情况下,由于在计算二分时向下取整的性质,所以等号的所处的位置对r和l的复制是有影响的!!! */
int mid = l + (r - l >> 1);
/**
* 这里的写法本质上就是 mid = l + r >> 1;
* 这种写法可以有效的避免变量在l + r时发生溢出
* 同时可以改善运行效率(4倍以上,原因未知)
* */
if(q[mid] >= x){
/* 这里的条件是带等号的,说明mid是有可能是解的,所以移动边界时一定要到mid */
r = mid;
} else{
/**
* else里面自然就是不含等号的情况,这种情况看起来直接移动边界到mid好像也没有什么影响
* 但实际上在确定了mid一定不为解之后,就应该把mid筛掉
* 不妨假设这样的情形,在else中仍然“l=mid”只剩最后2个选项进行二分
* 由于向下取整的性质,总是有mid=l,倘若q[r]=x,q[mid]<x,就会令l=mid=l这样的死循环
* 这个二分算法就会永远都持续下去
* 当然也可以写成对称的形式,如下
*/
l = mid + 1;
}
}
return r;
}
/* 对中间的特殊部分有另一种形式的写法 */
if(q[mid] > x){
r = mid - 1;
}else{
l = mid;
}
/* 同理也有小于号的写法 */
if(q[mid] < x)
l = mid + 1;
else
r = mid;
/* 这两种写法本质是一样的,只是要注意等号带来的影响 */
```