一、前言
二分查找算法是一个很常见到的一种找到指定数字的方式,希望看完这篇文章后可以带你理解二分查找如何实现和原理。
二、原理
二分查找二分查找(Binary Search)算法,也叫折半查找算法。二分查找的原理很简单,比如
说:有一件衣服的价格的范围是1~500,让我们去猜他的价格,我们总是会去找中间的那个值去
猜,而是从1开始一直往后猜,这样的效率就太低了,在这种情况下我们就引入了二分查找,二分
查找是针对有序的数据集合(这里是使用二分查找的前提条件),每次通过跟区间的中间元素去比
较,将要查找的区间每次都缩小到原来的一半,直到找到这个元素为止,或者当这个区间为0的时
则意味着,找不到这个元素
为了方便我们理解,我们以图中的数组为例1,2,12,13,23,27,35,40,45,70,我们以查找35为例,画了了一张简易图(忽略图画的不好这个细节),其中left代表左下标,right代表右下标,mid表示中间值下标
二分查找就如图中所示,如果中间值大于要查找的值,则往数组的左边继续查找,改变左边的范围,如果中间值小于要查找的值,则往数组的右边继续查找,改变右边的范围,直到找到这个元素或者,区间为0为止
三、代码的实现
二分查找可以使用循环和递归来进行实现,我们来分别看一下循环和递归如何实现
1、循环
int bin_search(int arr[], int left, int right, int key)
{
while (left <= right)
{
int mid = left + (right - left) /2;//计算中间下标
if (arr[mid] < key)//大于给定值,向右边找
left = mid + 1;
else if (arr[mid] > key)//小于给定值向左边找
right = mid - 1;
else
return mid;//等于给定值返回下标
}
return -1;//找不到返回-1
}
int main()
{
int key = 0;
scanf("%d", &key);
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int left = 0;
int right = sizeof(arr) / sizeof(arr[0]) - 1;//计算right的下标位置
int num = bin_search(arr,left,right,key);
if (num == -1)
printf("找不到\n");
else
{
printf("找到了\n");
printf("下标为 %d", num);
}
return 0;
}
上述写法是采用[left, right] 区间的写法,左闭右闭的写法,两边都可以去得到,二分查找在循环中还存在一种[left, right)的写法,形式大同小异,只是right的位置取不到了,因此处理会做出些许的改变
int main()
{
int key = 0;
scanf("%d", &key);
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int left = 0;
int right = sizeof(arr) / sizeof(arr[0]);//计算right的下标位置但是取不到right
int flag = 0;
while (left < right)//因为right取不到所以不能带等号
{
int mid = left + (right - left) / 2;
if (arr[mid] < key)
left = mid + 1;
else if (arr[mid] > key)
right = mid;//因为right取不到因此right=mid 这里可以用数学里的方式去理解 比较好理解
else
{
printf("找到了\n");
printf("下标为 %d", mid);
flag = 1;
break;
}
}
if (flag == 0)
{
printf("找不到\n");
}
}
二分查找的实现是比较的简单的,需要注意但是中间值的计算,一种是(right+left)/ 2这种计算方式会出现超出所定义数据类型的范围,即是除以2之后的值是在范围内,也会出错,因此方法一会出现溢出的风险,方法二是 left+(right-left)/2这种计算方式与第一种计算的结果相同,但是就没有溢出的问题,它总是保证了生成的mid大于left小于right
2、递归
int bin_search(int arr[],int left,int right,int key)
{
if (left <= right)
{
int mid = left + (right - left) / 2;//找出中间下标
if (arr[mid] > key)
return bin_search(arr, left, mid - 1, key);
else if (arr[mid] < key)
return bin_search(arr, mid + 1, right, key);
else
return mid;
}
else
return -1;
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int left = 0;
int right = sizeof(arr) / sizeof(arr[0]) - 1;
int key = 0;
scanf("%d", &key);
int num = bin_search(arr,left,right,key);
if (num == -1)
{
printf("找不到\n");
}
else
{
printf("找到了\n");
printf("下标为 %d", num);
}
return 0;
}
四、总结
以上就是本人目前对于二分查找的全部理解了,认为二分查找还是有诸多的局限性的,使用的条件比较的苛刻,但是使用起来比较的方便。
感谢大家可以看到这里,本人小白一个,如果有错误,欢迎各位大佬前来指正