1.实践题目:输入n值(1<=n<=1000)、n个非降序排列的整数以及要查找的数x,使用二分查找算法查找x,输出x所在的下标(0~n-1)及比较次数。若x不存在,输出-1和比较次数。
2.问题描述:即对含n个整数的序列进行二分查找,找到所要查找的数时则返回其下标,找不到则返回-1,同时返回查找次数。
3.算法描述:
1 int BinarySearch (int *a, int size, int key) 2 { 3 if(key < 0 || key > a[size-1]) return -1; 4 int left = 0; 5 int right = size - 1; 6 int t = 0; 7 8 while (left <= right ) 9 { 10 t++; 11 int mid = (left + right) / 2; 12 if (a[mid] == key ) 13 { 14 cout << mid << endl; 15 cout << t ; 16 return mid ; 17 } 18 if (key < a[mid] ) 19 right = mid - 1; 20 else left = mid + 1; 21 } 22 cout << "-1" <<endl; 23 cout << t << endl; 24 return -1; 25 }
首先对序列设置左边界和右边界,并且由左右边界定义中值,进入循环,若左边界小于右边界则正常运行,当左边界大于右边界时不符合逻辑则推出。
每次对比所要查找的值与中间下标对应的值,若所要查找的值大于中间值,则左边界下标移至中值右侧,即mid+1.否则右下标移至中间值左侧,即mid-1.
直到所要找的值与中间值相同,返回中间值,即查找成功。
若未找到,即左边界大于等于右边界,则查找无果,退出循环返回-1。
4.算法时间及空间复杂度:
时间复杂度:每次查找折半,即执行一次while循环,设共有n个数,每次查找的区间大小就是n,n/2,n/4,…,n/2^k(接下来操作元素的剩余个数),其中k就是循环的次数。
由于n/2^k取整后>=1,即令n/2^k=1,
可得k=log2n,(是以2为底,n的对数),所以时间复杂度可以表示O()=O(logn)
空间复杂度:该算法使用的辅助空间仅有一个数组,所以为O(1)
5.心得体会:
起初输出总有问题,后来查找问题的时候才发现把输出语句写在了条件之外,非常粗心。
对于二分查找的边界问题起初不清晰,没有理解左右边界互换时产生的问题。