赞
踩
二分查找是针对有序序列来说的,在有序序列中使用二分查找能大大提高查找效率。
前提:有序数组中查找关键词所在的位置
① 首先确定整个查找区间的中间位置 mid
② 用待查关键字key值与中间位置的关键字值进行比较;
若相等,则查找成功
若大于,则在后(右)半个区域继续进行折半查找
若小于,则在前(左)半个区域继续进行折半查找
③ 对确定的缩小区域再按折半公式,重复上述步骤。
(1)简单的写法
mid = (start + end) / 2
但这种写法有个缺点:mid可能会溢出。
我们可以举一个简单的例子来证明这一事实。
比如,当start = 1000 ,
end = INT_MAX。
INT_MAX
是int
数据类型可以存储的上限。这时start + end的和就溢出了。
(2)保险的写法
mid = start + (end - start) / 2
这样的写的好处大概有两个:
第一 :不会产生溢出
第二 :从通用性考虑,适用于对指针或者迭代器的操作。如果start和end同时是指针或者同时是迭代器时无法编译通过,因为俩指针或者俩迭代器运算不支持相加运算,只支持相减运算。
为什么指针和迭代器运算不支持相加运算,只支持相减运算?
我发现网上很少提及这个问题的原因。本人认为原因是这样的:两个迭代器相加,或者两个指针相加后所表示的位置对于vector容器就越界了,失去的意义。但是相减就可以,位置还在容器之中。
(3)(2)的另一种写法
mid = start + ((end - start) >> 1)
这种写法和(2)一样。
“>>”:表示向右移。value >> num:即value的二进制数整体向右移num位,表示在十进制上就是value除以2的num次方,value >> 1就是value 除以2。
“<<”:表示左移。value << num,就是指value的二进制形式整体向左移动num位,表示在十进制上就是value乘以2的num次方,value << 1就是value乘以2。
故(end - start) >> 1,即为(end - start) / 2。
非递归写法:
- /**
- *Copyright (c) 2019 Young Fan.All Right Reserved.
- *Author: Young Fan
- *Date: 2019.04.26
- *IDE: Visual Studio 2017
- *Description:
- */
-
- #include <iostream>
-
- using namespace std;
-
- int binarySearch(int numbers[], int length, int target) {
-
- int length_ptr = sizeof(numbers) / sizeof(int);
- cout << length_ptr << endl;//输出为1,sizeof会把从主函数中传进来的字符数组当作是指针来处理。
- //指针的大小又是由机器来决定,32位编译器指针变量的大小为4字节,64位编译器指针变量的大小为4字节
- if (length == 0)
- return -1;
- int start = 0, end = length - 1;
- while (start <= end) {
- int mid = start + (end - start) / 2;
- if (numbers[mid] == target)
- return mid; //查找到了则返回数据数组的下标
- else if (numbers[mid] > target)
- end = mid - 1;
- else
- start = mid + 1;
- }
- return -1;
- }
-
- int main()
- {
-
- int numbers[] = { 1, 2, 3, 4, 5, 6, 7}; //有序的
- int length = sizeof(numbers) / sizeof(int); //n得7
- cout << "length = " << length << endl;
- int a = binarySearch(numbers, length, 7); //返回数据数组的下标
-
- cout << a << endl;
-
- return 0;
- }

递归写法:
- int binarySearch(int[] a, int start, int end, int target) {
- if(start > end)
- return -1;
- int mid = start + (end - start) / 2;
- if(a[mid] == target)
- return mid;
- else if(a[mid] > target)
- return binarySearch(a, start, mid-1, target);
- else
- return binarySearch(a, mid+1, end, target);
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。