折半查找算法(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:如有不妥之处,欢迎评论指出!

发布了25 篇原创文章 · 获赞 9 · 访问量 6205

猜你喜欢

转载自blog.csdn.net/qq_42144047/article/details/89856437