算法第二章上机实践报告

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

该题的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

在BinarySearch里面先cout x的下标再return sum 然后在main函数里面在cout的时候 就可以输出x的下标和sum

②第二道题中遇到的分情况讨论问题

第二道题刚开始我们在打的时候,考虑的是先按第一道题的打法,BinarySearch算法不变,在后面当BinarySearch等于-1的时候,即x不在数组中时再分3种情况讨论

但是后来我们觉得这样太麻烦,也不好实现,后来我的队友张雯静想到一个方法,就是通过left和right来进行判断,我们通过举例子还有一步步分析,最后实现了

③第一二道题都遇到的问题是,BinarySearch函数是int 函数,需要有返回值,因此每个情况讨论完之后,都需要有return 0,来结束整个函数

如下图所示

 

posted on 2019-09-18 00:27  流星雨lxy  阅读(167)  评论(0编辑  收藏  举报

导航