折半查找算法(C语言)
在计算机科学中,折半搜索(英语:half-interval search),也称二分搜索(英语:binary search)、对数搜索(英语:logarithmic search),是一种在有序数组中查找某一特定元素的搜索算法。
搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半 。(百度百科)
如果说折半查找有什么缺陷的话,那就是它要求的数据必须是已经排好序的(升序降序均可以,下面的程序是以升序为例的)。其时间复杂度为O(log n),下面的程序可以明显感受到其优越性。
/*头文件*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void creatRand(int x,int y,int n,int *a) //创建范围在x~y的n个随机数并放到a数组中
{
srand((unsigned)time(NULL)); //初始化随机函数的种子
int i;
for(i=0;i<n;i++)
{
a[i]=x+rand()%(y-x);
}
return;
}
/*排序算法也有好几种,这里的重点是折半查找算法,所以暂时用比较好理解的选择排序算法,
顺便提一下,后面会专门对比一下几种排序算法*/
void order0to1(int *a,int n)
{
int i,j,t; //t用于中转要转换的两个数
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++) // 这里j=i+1,就是选择排序算法的典型特征(跟冒泡排序有区别)
{
if(a[j]<a[i])
{
t=a[j];
a[j]=a[i];
a[i]=t;
}
}
}
return;
}
/*函数指针a表示数组,n为数组长度,x为要查找的数*/
void find(int *a,int n,int x) //折半查找子函数
{
int rear,head,times=0; //定义头尾,并初始化查找的次数
rear=n-1; //rear指向最后一个数据
head=0; //head指向第一个数据
while(head<=rear) //循环查找的条件
{
if(x>a[(rear+head)/2]) //如果中间值小于要查找的数据值,则说明要查找的数在后面部分
{
printf("The location is %d ,and the value is %d\n",(rear+head)/2,a[(rear+head)/2]);
head=(rear+head)/2+1;
times++; //累计一次
}
else if(x<a[(rear+head)/2])
{
printf("The location is %d ,and the value is %d\n",(rear+head)/2,a[(rear+head)/2]);
rear=(rear+head)/2-1;
times++;
}
else //这时就查找成功了
{
times++;
printf("Find it!\n");
printf("The location is %d ,and the value is %d,times:%d\n",(rear+head)/2,x,times);
break;
}
}
if(rear<head) //x不在a数组里面
{
printf("No such a number!\n");
}
}
/*为了便于调试,我把总的逻辑算法放到自己定义的子函数里面*/
void my_main(void)
{
int n,num[2000],x; //注意,输入n时不能超过默认的2000个数据,可修改
printf("Input the number of data(<=2000):\n");
scanf("%d",&n);
creatRand(0,n*5,n,num); //创建随机数组
order0to1(num,n); //从小到大排序
printf("List:\n"); //输出已经排序好的数据,便于验证
for(x=0;x<n;x++)
{
printf("%d ",num[x]);
}
printf("\nwhat do you want to find(0~%d):\n",n*5);
scanf("%d",&x);
find(num,n,x); //折半查找
return;
}
int main()
{
int f=1;
while(f) //可控循环
{
system("cls");//清屏
fflush(stdin);//清空缓存
my_main(); //自定义主函数
printf("\nContinue?(1--yes,0--no)\n");
scanf("%d",&f);
}
return 0;
}
附上程序运行情况:
查找成功的情况:
查找失败情况:
PS:如有不妥之处,欢迎评论指出!