算法第二章上机实践报告
1.实践题目:7-2 改写二分搜索算法(此题与张雯静同学一起完成)
2.问题描述
3.算法描述
1 int BinarySearch(int a[],int x,int n){ 2 //找到x的下标并返回,否则输出-1 3 int left = 0; int right = n-1; 4 while(left<=right){ 5 int middle = (left+right)/2; 6 if(x==a[middle]) { 7 cout<<middle<<" "<<middle; 8 return 0; 9 } 10 if(x>a[middle]) left=middle+1; 11 if(x<a[middle]) right=middle-1; 12 } 13 if(right<0) { 14 cout<<-1<<" "<<0; 15 return 0; 16 } 17 18 if(left>n-1) { 19 cout<<n-1<<" "<<n; 20 return 0; 21 } 22 23 if((left>0)&&(left<=n-1)) { 24 cout << right << " " <<left; 25 return 0; 26 } 27 }
该题的BinarySearch算法与第一道题二分查找其实差不多,但是由于题目要求不同,做出了一些修改
1)根据题目要求当x存在于数组中时,i,j相同需要都输出,刚开始我们是cout << right << " " <<left;
但是后来通过例子发现right和left存在不相等的情况,这是因为 我们前面 int middle = (left+right)/2 此时可能出现由于int类型导致了本来有些是小数除不尽 但是int为整型
比如说 left=1,right= 2,middle本来等于1.5现在int后变为1
1 if(x==a[middle]) { 2 cout<<middle<<" "<<middle; 3 return 0; 4 }
而由于BinarySearch是int 类型的函数,所以最后有返回值,于是return 0,即结束整个函数
2)当x不存在于数组当中,又有三种情况进行讨论
①x小于数组中所有的数
1 if(right<0) { 2 cout<<-1<<" "<<0; 3 return 0; 4 }
举一个例子:
这是因为 当x小于数组中所有的数时,在二分搜索的过程中要不断的缩小缩小,因此right 在不断的减一减一,减到最后小于0了都没有找到x,而在这个过程中left没有改变一直都是0
②x大于数组中所有的数时
1 if(left>n-1) { 2 cout<<n-1<<" "<<n; 3 return 0; 4 }
举一个例子:
这是因为x大于数组中所有的数,在二分搜索的过程中要不断缩小范围,因此left要不断的加一加一,加到最后超出了数组边界了都没有找到x,而在这个过程中right没有改变一直是原来的数
③x在数组当中但是x的值在数组中两个数之间
举一个例子:
这是因为x在数组中间的时候,在二分搜索的过程中不断缩小范围,时而left减一,时而right加一,此时出现left不小于right的情况,但left的值仍在0-(n-1)之间
4.算法时间及空间复杂度分析
1 #include<iostream> 2 using namespace std; 3 4 int BinarySearch(int a[],int x,int n){ 5 //找到x的下标并返回,否则输出-1 6 int left = 0; int right = n-1; 7 while(left<=right){ 8 int middle = (left+right)/2; 9 if(x==a[middle]) { 10 cout<<middle<<" "<<middle; 11 return 0; 12 } 13 if(x>a[middle]) left=middle+1; 14 if(x<a[middle]) right=middle-1; 15 } 16 if(right<0) { 17 cout<<-1<<" "<<0; 18 return 0; 19 } 20 21 if(left>n-1) { 22 cout<<n-1<<" "<<n; 23 return 0; 24 } 25 26 if((left>0)&&(left<=n-1)) { 27 cout << right << " " <<left; 28 return 0; 29 } 30 } 31 32 int main(){ 33 int n,x;//n为n个数字,x为目标数 34 cin >> n >> x; 35 int a[n]; 36 for(int i=0;i<n;i++){ 37 cin >> a[i]; 38 } 39 BinarySearch(a,x,n); 40 return 0; 41 }
1)时间复杂度
通过代码分析,①发现在main函数里面有一个构建数组的for循环,共经过了n次循环,因此时间复杂度为O(n);
②在BinarySearch函数当中由于比较次数sum是一个常数,因此时间复杂度为O(1)
因此整个函数的时间复杂度为O(n)
2)空间复杂度
由于main函数里面定义了一个a[n]因此需要一个长度为n的空间,而常数则忽略不计,因此空间复杂度为O(n)
5.实践收获
1)第一次上机的体会
这次本学期算法课第一次上机实验,并且第一次以组队的形式敲代码,刚开始以为我们会有点不适应,但是后来发现还可以
2)遇到的问题
①第一道题中遇到的return两个值的问题
这次实验中 我们打第一道题的时候,基本上是按照书上的给的二分搜索法打的,遇到的问题不多,但是由于第一道题要输出比较次数和x的下标,我们疑惑了,因为刚开始我们是用return x的下标的,然后在main函数里面cout出这个值,但函数只能返回一个值,因此我们最后采用的方法是
1 int BinarySearch(int a[],int x,int n){ 2 //找到x的下标并返回,否则输出-1 3 int left = 0; int right = n-1; 4 int sum = 0; 5 while(left<=right){ 6 sum++; 7 int middle = (left+right)/2; 8 if(x==a[middle]) { 9 cout << middle<<endl; 10 return sum; 11 } 12 if(x>a[middle]) left=middle+1; 13 if(x<a[middle]) right=middle-1; 14 15 } 16 cout<<-1<<endl; 17 return sum; 18 19 }
在BinarySearch里面先cout x的下标再return sum 然后在main函数里面在cout的时候 就可以输出x的下标和sum
②第二道题中遇到的分情况讨论问题
第二道题刚开始我们在打的时候,考虑的是先按第一道题的打法,BinarySearch算法不变,在后面当BinarySearch等于-1的时候,即x不在数组中时再分3种情况讨论
但是后来我们觉得这样太麻烦,也不好实现,后来我的队友张雯静想到一个方法,就是通过left和right来进行判断,我们通过举例子还有一步步分析,最后实现了
③第一二道题都遇到的问题是,BinarySearch函数是int 函数,需要有返回值,因此每个情况讨论完之后,都需要有return 0,来结束整个函数
如下图所示