二分查找小结
参考资料:
1、程序员编程艺术第二十五章
2、勇幸的博客
二分查找除了参考以下代码外,参考lower_bound()
upper_bound()
两个函数的实现代码
- 资料一的代码
//二分查找V0.1实现版
//copyright@2011 July
//随时欢迎读者找bug,email:zhoulei0907@yahoo.cn。
//首先要把握下面几个要点:
//right=n-1 => while(left <= right) => right=middle-1;
//right=n => while(left < right) => right=middle;
//middle的计算不能写在while循环外,否则无法得到更新。
int binary_search(int array[],int n,int value)
{
int left=0;
int right=n-1;
//如果这里是int right = n 的话,那么下面有两处地方需要修改,以保证一一对应:
//1、下面循环的条件则是while(left < right)
//2、循环内当array[middle]>value 的时候,right = mid
while (left<=right) //循环条件,适时而变
{
int middle=left + ((right-left)>>1); //防止溢出,移位也更高效。同时,每次循环都需要更新。
if (array[middle]>value)
{
right =middle-1; //right赋值,适时而变
}
else if(array[middle]<value)
{
left=middle+1;
}
else
return middle;
//可能会有读者认为刚开始时就要判断相等,但毕竟数组中不相等的情况更多
//如果每次循环都判断一下是否相等,将耗费时间
}
return -1;
}
- 资料二的代码
/* binsearch 寻找key下标,不存在 return -1 */
/* binsearch 注意点【找不到 vs 死循环】
* 1. left <= right 如改为 left < right 可能找不到key
* 例如 1 2 3 4 5;key=5; left==right时候才搜到key
* 2. left = mid + 1;
* 如上left改为=mid,可能死循环,例如上面例子,
* 当left指向4时候,right指向5,此时,死循环;
* 死循环的根本原因在于left,当两个指针left与right相邻
* left可能永远等于mid,而right不会因为等于mid死循环
*/
int binsearch(int * arr, int lef, int rig, int key)
{
if(!arr) return -1;
int left = lef, right = rig;
while(left <= right)
{
int mid = left + ((right-left)>>1);
if(arr[mid] < key)
{
left = mid + 1;
}else if(arr[mid] > key)
{
right = mid - 1;
}else
return mid;
}
return -1;
}
/* binsearch_min 返回key(可能有重复)第一次出现的下标,如无return -1
*
* binsearch_min 注意点【死循环】
* 1. 如果while(left < right)改为(left <= right)可能死循环;
* 2. 循环结束条件,left == right
*
* 该代码我测试了很多用例,没发现反例,我认为是对的
* 但网上都是用的left<right-1的条件并分别对arr[left]和arr[right]
* 进行检查;我认为我写的更简练,希望有兴趣的读者帮忙review这段代码
* 如发现反例指出错误,感激不尽,嘿
*/
int binsearch_min(int * arr, int lef, int rig, int key)
{
if(!arr) return -1;
int left = lef, right = rig;
while(left < right)
{
int mid = left + ((right-left)>>1);
if(arr[mid] < key)
{
left = mid+1;
}
else
{
right = mid;
}
}
if(arr[left] == key) return left;
return -1;
}
/* binsearch_max 返回key(可能有重复)最后一次出现的下标,如无return -1
*
* binsearch_max 注意点【死循环 vs 越过目标位置】
* 1. 如果改为while(left < right)可能死循环;
* 2. 如果left=mid改为left=mid+1;则有可能越过目标位置
* 3. 循环结束条件,left == right || left == right -1
*
* 如非要死记:找最大的等号放<=key的位置,找最小的等号放>=key位置
*/
int binsearch_max(int * arr, int lef, int rig, int key)
{
if(!arr) return -1;
int left = lef, right = rig;
while(left < right -1)
{
int mid = left + ((right-left)>>1);
if(arr[mid] <= key)
{
left = mid;
}
else
{
right = mid;
}
}
if(arr[right] == key) // 找max,先判断right
{
return right;
}
else if(arr[left] == key)
{
return left;
}else
return -1;
}
/* binsearch_justsmall 返回刚好小于key的元素下标,如无return -1
*
* binsearch_justsmall 注意点【死循环 vs 越过目标位置】
* 1. 如果改为while(left < right)可能死循环;因为left=mid的缘故
* 2. 如果left=mid改为left=mid+1;则有可能越过目标位置
* 3. 循环结束条件,left == right || left == right -1
*/
int binsearch_justsmall(int * arr, int lef, int rig, int key)
{
if(!arr) return -1;
int left = lef, right = rig;
while(left < right - 1)
{
int mid = left + ((right-left)>>1);
if(arr[mid] < key)
{
left = mid;
}else
{
right = mid - 1;
}
}
if(arr[right] < key) // 找刚好小于,先判断right
{
return right;
}else if(arr[left] < key)
{
return left;
}else
return -1;
}
/* binsearch_justgreat 返回刚好大于key的元素下标,如无return -1
*
* binsearch_justgreat 注意点【死循环 vs 检查元素是否大于key】
* 1. 如果改为while(left <= right)可能死循环;因为right = mid;
* 2. 最后注意检查arr[right]是否大于key
* 3. 循环结束条件,left == right
*/
int binsearch_justgreat(int * arr, int lef, int rig, int key)
{
if(!arr) return -1;
int left = lef, right = rig;
while(left < right)
{
int mid = left + ((right-left)>>1);
if(arr[mid] <= key)
{
left = mid + 1;
}else
{
right = mid;
}
}
if(arr[right] > key) return right;
return -1;
}
┆ 凉 ┆ 暖 ┆ 降 ┆ 等 ┆ 幸 ┆ 我 ┆ 我 ┆ 里 ┆ 将 ┆ ┆ 可 ┆ 有 ┆ 谦 ┆ 戮 ┆ 那 ┆ ┆ 大 ┆ ┆ 始 ┆ 然 ┆
┆ 薄 ┆ 一 ┆ 临 ┆ 你 ┆ 的 ┆ 还 ┆ 没 ┆ ┆ 来 ┆ ┆ 是 ┆ 来 ┆ 逊 ┆ 没 ┆ 些 ┆ ┆ 雁 ┆ ┆ 终 ┆ 而 ┆
┆ ┆ 暖 ┆ ┆ 如 ┆ 地 ┆ 站 ┆ 有 ┆ ┆ 也 ┆ ┆ 我 ┆ ┆ 的 ┆ 有 ┆ 精 ┆ ┆ 也 ┆ ┆ 没 ┆ 你 ┆
┆ ┆ 这 ┆ ┆ 试 ┆ 方 ┆ 在 ┆ 逃 ┆ ┆ 会 ┆ ┆ 在 ┆ ┆ 清 ┆ 来 ┆ 准 ┆ ┆ 没 ┆ ┆ 有 ┆ 没 ┆
┆ ┆ 生 ┆ ┆ 探 ┆ ┆ 最 ┆ 避 ┆ ┆ 在 ┆ ┆ 这 ┆ ┆ 晨 ┆ ┆ 的 ┆ ┆ 有 ┆ ┆ 来 ┆ 有 ┆
┆ ┆ 之 ┆ ┆ 般 ┆ ┆ 不 ┆ ┆ ┆ 这 ┆ ┆ 里 ┆ ┆ 没 ┆ ┆ 杀 ┆ ┆ 来 ┆ ┆ ┆ 来 ┆
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)