赞
踩
二分查找也称折半查找,它是一种效率较高的查找方法
例:在一个有序数组中查找具体的某个数字n,
如,在一个一维数组中存储了一组有序元素1 2 3 4 5 6 7 8 9 10,现在我们要查找数字7,有人会想从前往后遍历去查找,这样固然可行,但是如果数据元素不是10个,而是一千甚至一万,则这样的查找效率显得很低
这里我们忽略了这组元素是有序的,我们可以从这组数据的中间开始查找,取中间的元素与要查找的元素比较大小,这样一次比较可以排除一半的元素,显然效率比遍历更高,这就是我们要说的二分查找,又称为折半查找
如在1 2 3 4 5 6 7 8 9 10查找7
我们查找的思路如下:
首先找到这组元素的中间元素:最左边元素的下标和最右边元素的下标之和除以2,作为中间元素的下标,如本例,(9+0)/ 2 = 4,4作为中间元素的下标,对应的数字是5
5比要找的数字7小,被查找的范围变为6 7 8 9 10;
新的被查找的范围的中间元素的下标(5+9)/ 2 = 7,对应的数字是8
8比要找的数字8大,被查找的范围6 7;
新的被查找的范围的中间元素的下标(5+6)/ 2 = 5,对应的数字是6
6比要找的数字7小,被查找的范围7;
新的被查找的范围的中间元素的下标(6+6)/ 2 = 6,对应的数字是7,找到了
我们发现上面算法只找了4次就找到了所要找的元素,如果是遍历的话,最坏的情况要找10次,所以二分查找其效率较高,其时间复杂度为
用代码实现:
- #include <stdio.h>
- int main()
- {
- int arr[] = {1,2,3,4,5,6,7,8,9,10};
- int k = 7; //要查找的数字
- //在数组中查找k
- int sz = sizeof(arr) / sizeof(arr[0]); //数组元素个数
- int left = 0;
- int right = sz -1;
- while(left <= right)
- {
- int mid = (left + right) / 2;
- if(arr[mid] < k)
- {
- left = mid + 1;
- }
- else if(arr[mid] > k)
- {
- right = mid - 1;
- }
- else
- {
- printf("找到了:%d,其下标是:%d\n",arr[mid],mid);
- break;
- }
- }
- if(left > right)
- {
- printf("找不到\n");
- }
- return 0;
- }
我们运行可以得到:
当把k改为11 ,我们发现找不到
如果上述代码要用函数实现,我们需要注意
如果函数内部需要参数部分传递某个数组元素的个数,数组元素个数要在函数外部求
如果在函数内部求数组元素个数,因为数组名传参传递的是数组名的首元素地址,此时sizeof(arr)算出的结果为4,sizeof(arr) / sizeof(arr[0])算出的结果为1,而不是元素个数,这点需要注意
用函数实现一个整型有序数组的二分查找:
- #include <stdio.h>
- int binary_search(int a[], int k, int s)
- {
- int left = 0;
- int right = s - 1;
- while(left <= right)
- {
- int mid = (left + right) / 2;
- if(k < a[mid])
- {
- right = mid - 1;
- }
- else if(k > a[mid])
- {
- left =mid + 1;
- }
- else
- {
- return mid;
- break;
- }
- }
- return -1;
- }
- int main()
- {
- int arr[] = {1,2,3,4,5,6,7,8,9,10};
- int k = 0;
- printf("输入要查找的数:");
- scanf("%d",&k);
- int sz = sizeof(arr) / sizeof(arr[0]);
- //找到就返回找到的位置的下标
- //找不到就返回-1
- int ret = binary_search(arr, k, sz);
- if (ret == -1)
- {
- printf("找不到\n");
- }
- else
- {
- printf("找到了:%d,下标是:%d\n",arr[ret],ret);
- }
- return 0;
- }
运行结果如下:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。