算法第二章上机实验报告
l 实践题目
设a[0:n-1]是已排好序的数组,请改写二分搜索算法,使得当x不在数组中时,返回小于x的最大元素位置i和大于x的最小元素位置j。当搜索元素在数组中时,i和j相同,均为x在数组中的位置。
输入格式:
输入有两行:
第一行是n值和x值; 第二行是n个不相同的整数组成的非降序序列,每个整数之间以空格分隔。
输出格式:
输出小于x的最大元素的最大下标i和大于x的最小元素的最小下标j。当搜索元素在数组中时,i和j相同。 提示:若x小于全部数值,则输出:-1 0 若x大于全部数值,则输出:n-1的值 n的值
输入样例:
在这里给出一组输入。例如:
6 5
2 4 6 8 10 12
输出样例:
在这里给出相应的输出。例如:
1 2
l 问题描述
传统的二分搜索算法旨在在一个有序数列中对数列中的一个数进行查找,而现在相对于之前所做的问题改动就是任意给出一个数字,锁定它在这个有序数列中的范围,而问题也由此主要分为以下三种情况:(1)如果给的这个数字恰好在这个有序数列的最小值和最大值之间,则要通过二分查找锁定这个数在数列中的哪两个数之间。(2)如果给定的这个数字刚好是这个有序数列中的某一个数字,则此时所需要输出的两个值均为该数字在相应存储数组中的元素下标。(3)给定的数字小于这个有序数列的最小值 或者给定的数字大于这个有序数列的最大值。所以对于相应算法的设计,也即是对这三种情况的分别考虑与处理。
l 算法描述
- 定义主函数main,定义关键字x,定义一列数组长度为n的数组a[n],定义int i,j,定义一个函数BinarySearch( );
- 调用函数BinarySearch(a,x,n,&i,&j),引用参数i.j,以便返回i,j的值,此处采用了传值调用的方法,取i,j两个变量的地址,然后直接打印输出i,j两个地址里的内容即可。
- 利用二分搜索的思想,在数组中查找关键字x。当left<=right,如果x==mid,则x在数组中,返回下标i,j,如果x>a[mid],则left=mid+1,如果x<a[mid],则 right=mid-1,不断一半一半地缩小范围查找,直到left>right,还是没有找到x,把right赋值给i,left赋值给就j,返回下标i,j,输出小于x的最大元素位置i和大于x的最小元素位置j。
- 同时在循环结束后,在BinarySearch()函数中采用if语句进行判断如果left>right,则证明是问题分析中的第二种情况,此时left即为j的值,left-1即为i的值,同样采用if-else语句对第三种情况进行分析处理,相应进行输出i,j的值。
l 算法空间复杂度及时间复杂度分析
- 算法时间复杂度:循环体内每循环一次时间复杂度减少一半且判断的时间复杂度为O(1),所以T(n)=1*T(N/2)+O(1)=O(logn)
- 空间复杂度:各个变量的空间复杂度都是O(1),所以算法空间复杂度为O(1)
l 心得体会
这也是学习算法设计与分析这门课程以来第一次结队编程,其实在这个过程中,我作为设计算法的一方,发现自己在分析问题,解决算法问题的方面还是有很多思维不严谨的地方,比如在这道算法题的解决过程中,因为自己把特殊情况的if-else语句设计进了循环中,导致无法跳出循环,运行超时的问题,但也是在跟队友的讨论中让我发现问题的所在,还有优化算法的方面,一开始的设计思路并没有想到采用传值调用,但初期算法设计发现,太多的条件判断语句与循环嵌套很容易出错,所以进行修改。在辅助队友进行代码调整时,我也发现自己在编程时并没有完全按照编程及命名规范,显得有些随意,这也是以后的编程中需要改进的地方。