C语言实现二分查找
核心思路(前提数组是有序数组)
- 把数组看成一个区间, start初始化为0, end 初始化为长度 - 1, mid = (end - start) / 2
- 进行判断 需要查询的值 大于或者小于mid位置的值。
如果大于的话 需要改变start的值 此时由图可知 mid需要前进一位, 随后start = mid,mid 再次更新位置 跟1中一致。
如果小于的话 需要改变end的值 此时由图可知 mid需要后退一位, 随后end= mid,mid 再次更新位置 跟1中一致。
如图所示,实现了折半查找。 - 重复以上操作后,最后会出现 start = end 和 (end - start)- 1 的情况 就可以直接进行判断了
二分查找核心就是折半,解决了如何切换区间就好办了。
代码如下:
/* 二分查找初步思路: 设mid变量保存区间中间值 用来判断查找值
1. 中间值和查找的比较:
大于: mid自减1后(mid也需要往前推一位) 赋值给end start 不变
mid -= (end - start) / 2 为下一波判断大小做准备 继续位于区间中间
小于: mid自加1后(mid也需要往后推一位) 赋值给end end 不变
mid += (end - start) / 2 为下一波判断大小做准备 继续位于区间中间
2. 如果start == end:
直接判断start或者end位置的值跟查询是否相等
相等: 赋值 break
3. 如果(end - start) == 1:
判断查询的值跟start或者end的位置的值是否有匹配 如果有匹配则保存索引到index break
*/
int two_search(int *arr,int value)
{
int start, end, mid,index = -1;
start = 0;
end = N - 1;
/* mid 初始化为中间索引 */
mid = (end - start) / 2;
int i;
for (i = 0; i < sizeof(arr) / sizeof(int); i++)
{
printf("第%d次 查找\n", i + 1);
printf("当前索引区间为%d ==> %d ==> 中间索引值为%d\n", start, end,mid);
/* 大于: end 改变为 中间值 - 1 start 不变 */
if (arr[mid] > value)
{
end = --mid;
/* 如果是end改变 则mid需要往前减去结束除开始的二分之一 */
mid -= ((end - start) / 2);
}
else if (arr[mid] < value)
{
start = ++mid;
/* 如果是end改变 则mid需要往前加上结束除开始的二分之一 */
mid += ((int)(ceil((float)(end - start) / 2)));
}
else
{
/* 刚好中间值等于了查找值 */
printf("mid值的索引为%d", mid);
index = mid;
break;
}
/* 查询完毕 判断是否有相等的值 */
if (start == end)
{
mid = -1;
/* 判断最后是否为查找值 */
if (arr[start] == value)
{
/* 最后查找到了 */
printf("最后查找到值索引为%d \n", start);
index = start;
break;
}
}
// 最后区间剩两个值
else if ((end - start) == 1)
{
if (arr[start] == value)
{
/* 最后查找到了 */
printf("当前索引区间为%d ==> %d ==> 中间索引值为%d\n", start, end,mid);
printf("mid = 0 start = 最后查找到值索引为%d \n", start);
index = start;
break;
}
else if (arr[end] == value)
{
/* 最后查找到了 */
printf(" mid = 0 end =最后查找到值索引为%d \n", end);
index = end;
break;
}
}
}
/* 没找到 */
if (index == -1)
{
printf("%s", "None");
}
return index;
}