假设有一个人要我们猜0-99之间的一个数,那么最好的方法就是从0-99的中间数49开始猜。
如果要猜的数小于49,就猜24(0-48的中间数);如果要猜的数大于49,就猜74(50-99的中间数)。
重复这个过程来缩小猜测的范围,直到猜出正确的数字。二分查找的工作方法就是如此。
基本概念:
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。
首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,
如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,
如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。
重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
算法要求:
1.必须采用顺序存储结构。
2.必须按关键字大小有序排列。
二分查找法查找的数列,是一个有序集合。首先找到这个有序集合的最中间的元素。然后判断,
这个元素比需要找的元素大,接下来会在左边区域继续查找;反之,这个元素比要找的元素小,
则在右边区域进行查找。重复以上查找,直到找到这个查找的元素或者对数据集无法再分割为止。
二分查找法可以应用于任何类型的数据,只要将这些数据按照规律进行排序即可。
二分查找的接口定义:
int binary_search(int key, int arr[], int n);
返回值:若查找成功,返回目标的索引值;查找失败,返回-1。
描述:二分查找法,key是传递的要查找的元素,arr[]为已经输入的元素数组,n为数组元素的个数。
复杂度:O(lgN),N为要查找的元素个数。
二分查找法的实现:
二分查找法本质上就是不停的对有序数列进行分割,并检查区域中的中间元素。
有序数列放在arr[]中,需要查找的元素为key,n为数组的元素个数。
实现二分查找法,可以通过定义数列的左右边界值为变量left和right,用这两个变量来控制一个循环进行查找。
1.先将left设置为0,right设置为n-1,每次循环,设置left和right之间的中间值为mid。
2.如果位于mid的元素大小比key要小,将左边索引值left移动至mid后的一个元素位置上,即下一次循环要搜索的区域是当前区域的下半区。
3.如果位于mid的元素大小比key要大,将右边索引值left移动至mid前的一个元素位置上,即下一次循环要搜索的区域是当前区域的上半区。
4.随着不断循环搜索,左索引left从左向右移,右索引right从右向左移。
5.只要在mid这个位置找到了我们要找的数key,查找立即停止,并返回我们要的值;如果没有找到,left和right将重合。
注:图来源于博客园的IDreamo
C代码:
#include <stdlib.h>
/*二分查找函数binary_search*/
/*传参需要查找的元素key,输入的数组arr,输入的数组长度n*/
int binary_search(int key, int arr[], int n) {
/*声明变量,左边界值left,右边界值right,
中间值mid,用于记录查找次数count,用于记录查找成功次数count1*/
int left, right, mid, count=0, count1=0;
/*左边界值从最左边下标为0的位置开始*/
left = 0;
/*右边界值从数组长度减1的位置开始,也就是最右边*/
right = n - 1;
/*在查找范围不为0的情况下,执行循环语句*/
while(left < right) {
count++; //记录查找的次数
mid = (left + right) / 2; //计算中间值的下标
if (key < arr[mid]) { //如果要查找的元素小于中间值
right = mid - 1; //确定左子表的范围
}
else if (key > arr[mid]) { //如果要查找的元素大于中间值
left = mid + 1; //确定右子表的范围
}
/*如果要查找的元素等于中间值元素*/
else if (key = arr[mid]) {
printf("查找成功!\n 查找了%d次,arr[%d]=%d", count, mid, key);
count1++; //记录查找成功的次数
break;
}
}
/*如果一次都没有查找成功*/
if (count1 = 0)
printf("查找失败!");
return 0;
}
/*主函数*/
int main() {
/*声明用于键盘输入的变量i,用于查找
的元素key,数组arr,数组长度n*/
int i, key, arr[100], n;
printf("请输入数组的长度:\n");
scanf("%d", &n);
printf("请输入数组的元素:\n");
for (i=0;i<n;i++) {
scanf("%d", &arr[i]);
}
printf("请输入你要查找的元素:\n");
scanf("%d", &key);
/*调用二分查找函数*/
binary_search(key, arr, n);
printf("查找完毕!\n");
return 0;
}
运行结果:
请输入数组的长度:
8
请输入数组的元素:
1 2 3 4 5 6 7 8
请输入你要查找的元素:
2
查找成功!
查找了2次,arr[1]=2查找完毕!