#include <stdio.h>#include <math.h>//线性查找:时间复杂度是O(n)int linearSearch(int arr[],int target){int i=0;for(i=0;arr[i];i++){if(arr[i]==target)return i;}return -1;}//迭代折半查找:时间复杂度:T(n) = T(n/2) + c//要访问一半的数字int binarySearch(int arr[],int iLen, int target){int first = 0;int last = iLen - 1;int mid;while(first<=last){//=号必须//mid = (first+last)/2;mid = first-(last-first)/2;if(arr[mid]==target) return mid;else if(arr[mid]<target){first = mid + 1;}else if(arr[mid]>target){last = mid - 1;}}if(first>=last){return -1;}}//递归折半查找:时间复杂度:T(n)=O(Logn) Log以2为底//int binarySearchRecursive(int arr[],int start,int end, int target){//int mid = (start+end)/2;mid = start -(end-start)/2;if(start<=end){//=号必须if(arr[mid]==target) return mid;if(arr[mid]>target) return binarySearchRecursive(arr,start,mid-1,target);return binarySearchRecursive(arr,mid+1,end,target);}return -1;}void main(){//int arr[] = [3,4,9,8,12];int arr[] = {3,8,9,10,12};int iLen = sizeof(arr)/sizeof(arr[0]);printf("%ld\n", binarySearch(arr,iLen,8));return;}
up为折半查找的代码。你会发现有这个代码:mid=(first+last)/2。
如果(first+last)的和大于int类型所能表示的最大值(231-1),这会有一个小问题:结果为一个负数。在C语言中会报索引超出边界的错误或进入无限循环?
解决方案:
1、int mid = low + ((high - low)/2);
并不总是有效的。为什么呢?
在C语言中,有符号的整数溢出是未定义的,这个说明有可能还是会溢出。
2、Java:
int mid = (low + high) >>> 1(总是高位补零)
3、C/C++:
int mid = ((unsigned int)low + (unsigned int)high)>>1(无符号的数右移,高位补零)
虽然在C语言中,无符号的整数溢出不是未定义的。但是这个计算出来还是有可能有问题:比如(UINT_MAX+1)/2结果是0
4、x+y=(x&y)*2+x^y; 用位运算肯定不会发生溢出了。
但是以上方法都脱离了一个事实,因为是对数组排序,数组是有大小限制的。
对于64位机来说最大的寻址空间是264
字节,整型如果是8字节,261字节是数组所能容纳的最大值,也就是说start和end只和最大为262,没有超出
int能表示的最大值范围,也就肯定不会溢出了。
32位机也能用类似方法分析。
int arr[1<<30];//VC6.0编译报错:E:\MYWORKSPACE\cpluspluscode\binarySearch\binary.cpp(56) : error C2133: 'arr' : unknown size
参考:
http://locklessinc.com/articles/binary_search/
总结:
32位机还是64位机上,都用兼容的site_t替代int。优化可以用也可以不用。
本文探讨了折半查找算法的时间复杂度及其优化方法,包括解决数组索引溢出问题的策略,并提供了实例代码分析。
1万+

被折叠的 条评论
为什么被折叠?



