当前位置:文档之家› 二分搜索实验报告

二分搜索实验报告

南京邮电大学通达学院
实验报告
实验名称:二分查找原理
课程名称:微型计算机原理与接口技术
姓名班级学号:钱煜中
142501
14250120
实验时间:2016.11.25
二分查找原理
一、实验原理:
二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。

因此,折半查找方法适用于不经常变动而查找频繁的有序列表。

首先,假设表a中n个元素是按升序排列,将表中间位置记录的关键字与查找关键字x比较,如果x=a[n/2]两者相等,则x查找成功,算法终止;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字x<a[n/2],则进一步在前一子表中搜索x,否则若x>a[n/2],查找后一子表。

重复以上过程,直到找到满足条件的记录x,使查找成功,或直到子表不存在为止,此时查找不成功。

值得注意的是,如果查找值x是有序序列a中的重复元素,二分查找不确定找到的是重复元素中的哪一个,例如,对于序列{1,2,3, 3,4},如果查找值为3,那么最终查找记录位置为3号元素或者4号元素都是正确结果;另一方面,如果找不到与查找值x完全相等的数值,将以序列a中与x最为相近的值作为最终查找结果。

举例。

有序序列a = {1,2,3,4,5,7,9},查找数据x = 5,步骤如下:
序列a共有7个元素,因此查找数据5,
第一次比较,time = 1,index_mid = 4,mid = 4,x > mid,所以在后半部分中查找{4,5,7,9};
第二次比较,time = 2,index_mid = 6,mid = 7,x < mid,因此在前半部分中查找{4,5,7};
第三次比较,time = 3,index_mid = 5,mid = 5,x = mid,查找成功。

最终结果,查找次数time = 3,对应数值序号index = 5。

二、实验代码
#include <stdio.h>
#include<stdlib.h>
void shuchu(int *a,int c)
{
int i;
for(i=0;i<c;i++)
printf("%4d",a[i] );
printf("\n");
}
void half_search(int *a,int b,int c)//a是数组,b是待查找数,c是数的个数
{
int i=0,j=0,k=c-1,x,d=1;//i是查找次数,j是下界,k是上界,d是判断double e;
for(;d;)
{
if((k-j)==1)
{
i++;
if(a[j]==b)
{
printf("经过%d次查找后:%d在第%d位\n",i,b,j+1);
break;
}
if(a[k]==b)
{
printf("经过%d次查找后:%d在第%d位\n",i,b,k+1);
break;
}
i=(b-a[j]);
if(i<0)
i=-i;
d=(a[k]-b);
if(d<0)
d=-d;
if(i>d)
printf("没有找到%d找到了和他最相近的数%d在第%d位
\n",b,a[k],k+1);
if(i<d)
printf("没有找到%d找到了和他最相近的数%d在第%d位
\n",b,a[j],j+1);
break;
}
e=((j*1.0+k*1.0)/2+0.5);
//printf("%f\n",e);
x=(int)e;
//printf("x=%d,j=%d,k=%d\n",x,j,k);
if(a[x]>b)
{
k=x;
i++;
}
if(a[x]<b)
{
j=x;
i++;
}
if(a[x]==b)
{
d=0;
i++;
printf("经过%d次查找后:%d在第%d位\n",i,b,x+1 );
}
//printf("现在是第%d次搜索中间值x在第%d位 a[%d]
为%d\n",i,x+1,x,a[x]);
}
}
void paixu(int *a,int c)
{
int i,j,k;
for(i=0;i<c-1;i++)
{
for(j=0;j<c-1;j++)
{
if(a[j]>a[j+1])
{
k=a[j];
a[j]=a[j+1];
a[j+1]=k;
}
}
printf("第%2d次排序后:",i+1);
shuchu(a,c);
}
}
void zhuhanshu()
{
int a[12]={1,7,2,4,13,10,7,3,2,5,8,6},b,c=12;
/*int a[100],b,c,i;
printf("共有几个数要输入\n");
scanf("%d",&c);
for(i=0;i<c;i++)
{
printf("输入第%d个数\n",i+1);
scanf("%d",a+i);
}*/
printf("输入的数组为:");
shuchu(a,c);
paixu(a,c);
printf("需要查找的数\n");
scanf("%d",&b);
half_search(a,b,c);
}
void main()
{
int a=1;
zhuhanshu();
while(a)
{
printf("输入1继续输入0退出\n");
printf("\n");
scanf("%d",&a);
if(a==1)
zhuhanshu();
if(a==0)
break;
}
}
三、实验数据(给出实验结果)
查找的序列为 x = { 1 7 2 4 13 10 7 3 2 5 8 6},需要查找的数据为var1 = 2,var2 = 7。

1、按照实验一冒泡排序方法给出排序后的序列 x1(升序排列),
与实验一类似,给出每一趟排序的最终结果,共11个结果;2、在x1序列中,分别查找出var1和var2的位置序号index,并给
出两个数据分别的查找次数time。

四、实验总结(问题、解决方法、心得体会等)
这次实验是二分搜索,实验中遇到了好几个问题。

第一个问题来自于上次冒泡排序,为了让输入更加便捷,我是让用户去选择输入几个数然后一个个输入的,但是这次实验要经常调试,所以每次都要输入一遍很烦,在实验报告的代码中,原来的还在但是被注释掉了,为了让
调试方便,采用了直接定义的时候就把数放进去。

在这个问题后是二分搜索的实现,其实二分搜索不难,定义一个上界、下界和中值,要找的数比中值小就把上界变成中值,否则下界变成中值。

在这里首先有个问题,有同学和我讨论的时候下界变中值的时候他是下界等于中值加一,结果程序出了问题,我一开始觉得很有道理,但是因为他出错了,我们就寻找问题,那就是因为没考虑数组中如果没有要找的数那么就只能上界紧贴下界,这一句语句一下子就让上界等于下界了,虽然优化了算法但是引起了问题。

我是没有去优化这一步的,因为关于要找的数在数组不存在我已经给出了解决办法,那就是在不停的寻找中,首先就是上界减下界是不是等于1,如果出现这种情况就说明找不到要找的数,那么我就让上下界分别和要找的数相减然后取绝对值比较,最后输出比较近的值。

本以为我这样就很完美了,结果发现如果要找第一个数或者最后一个数也是找不到,问题就是如果找的数就是下界那个数,上界无限接近下界,但是下界没有和要找的数比较过,最后直接进入了寻找最接近的数这个功能,这不合理。

所以在上界减下界等于1里面的最开始我会把要找的数和上下界比较,如果有相等直接输出来并且结束,后面的就不计算了。

实验过程中还有问题就是整型数相除的结果直接就是整型数,不是全舍的,所以要想四舍五入还要引入一个double并且把整型数*1.0,这个影响查找次数,但是不影响是否能找得到,最后的算法是采用四舍五入的。

相关主题