前言
二分查找又叫拆半查找,C语言二分查找是一种高效的查找算法,但是只适用于有序的情况,不管是递增的数列,还是递减的数列,前提一定要是有序的数组。
目录
二分查找算法的基本原理:
(1):前提一定为有序数组。
(2):首先定义出数组的最左边元素的下标,最右边元素的下标和数组下标的中间值。
(3):找出该数组中的中间元素(通过下标来寻找),然后与所找元素进行比较,若中间元素小于所寻找元素,那么中间值加1(此时充当左边的范围下标),右边范围的边界仍是最右边元素的下标,若中间元素小于所寻找元素,那么中间值减1(此时充当右边的范围下标),左边范围的边界仍是最左边元素的下标。
(4):重复此过程,直到找到目标值或搜索区间为空(表示未找到)。
时间复杂度
-
时间复杂度:O(log n)
- 空间复杂度:O(1)(迭代版本)
- 最优情况:O (1)(目标元素恰在中间位置)
- 最坏情况:O (log n)(n 为数组长度)
接下来将用C语言实例来验证
例子:给出一串数字1~10,来让我们寻找这一串中的数字7,以及找到数字7对应的下标。
首先根据二分查找的基本原理,确定下标,如下:
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 0; //想要从数组arr1中寻找的数字
printf("请输入你想找从数组中寻找的数字:");
scanf("%d", &k);
int sz = sizeof(arr1) / sizeof(arr1[0]);
int left = 0; //左下标
int right = sz - 1; //右下标
int flag = 0; //标志
其中 sz 为数组 arr1 中的元素个数,数组的下标是从0开始,最大下标为元素个数减1,刚开始 left 为最左边元素的下标也就是此时 arr1[1] 的下标,right 为最右边元素的下标也就是 arr1[10] 的下标。
然后根据例子,找到合适的循环条件:
不难发现,每当进行一次二分查找,左边范围下标或者右边范围下标会有一个发生变化,通过中间下标所对应的元素与所寻找元素相比较,从而确定哪边范围下标变化。
但从循环开始 左边范围下标 left 就小于 右边范围下标 right ,当随着二分查找的一次次进行,二者 left 和 right 会逐渐的逼近知道相等,达到循环的终止条件。
int flag = 0; //标志
while (left <= right)
{
int mid = left + (right - left) / 2; //数组的中间下标
if (arr1[mid] < k)
{
left = mid + 1;
}
else if (arr1[mid] > k)
{
right = mid - 1;
}
else
{
flag = 1;
printf("找到了,下标为%d\n", mid);
break;
}
}
if (0 == flag)
{
printf("找不到\n");
}
当我们寻找的数字为 7 时,数组中 10 个元素,最左边范围的下标为 0 ,最右边范围的下标为 9,中间下标为 4 ,通过数组中下标为 4 的元素与数字 7 比较,很明显 arr1[4] 为 5 比数字 7 要小,那么最左边范围的下标变成中间下标加 1,最右边范围的下标不变,此时的 left 小于 right 符合循环条件,在进行第二次二分查找,此时的最左边范围的下标为 5 ,中间下标变成了 7 ,通过数组中下标为 7 的元素与数字 7 比较,结果 arr1[7] 要大于数字 7,此时中间下标加1变成右边范围的下标,在进行第三次二分查找,左边范围的下标为5,右边范围的小标为6,中间下标为5,让arr1[5]与数字7进行比较,结果小于数字7。
那么左边下标变成6,右边下标仍为6,在进行一次二分查找,此时找到数字7对应的下标。
完整代码如下:
#include<stdio.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 0; //想要从数组arr1中寻找的数字
printf("请输入你想找从数组中寻找的数字:");
scanf("%d", &k);
int sz = sizeof(arr1) / sizeof(arr1[0]);
int left = 0; //左下标
int right = sz - 1; //右下标
int flag = 0; //标志
while (left <= right)
{
int mid = left + (right - left) / 2; //数组的中间下标
if (arr1[mid] < k)
{
left = mid + 1;
}
else if (arr1[mid] > k)
{
right = mid - 1;
}
else
{
flag = 1;
printf("找到了,下标为%d\n", mid);
break;
}
}
if (0 == flag)
{
printf("找不到\n");
}
return 0;
}
总结:
二分查找的效率极高,可以用于处理大量的数据,但是必须为有序的序列,上述情况为单调递增的数组,那么单调递减的数组相应的判断条件相反即可。






