二分搜索算法(C语言实现)

二分查找的递归与非递归程序,跟踪分析执行时间,分析两种算法的复杂性。

二分查找算法思想:

二分又叫折半查找,要求待查找的序列有序。每次取中间位置的值与待查关键字比较,如果中间位置的值比待查关键字大,则在前半部分循环这个查找的过程,如果中间位置的值比待查关键字小,则在后半部分循环这个查找的过程。直到查找到了为止,否则序列中没有待查的关键字。

快速排序算法思想:

定义变量low、high分别标识数组的第一个元素下标和最后一个元素下标,变量key先存储第一个数组arr[0],以后key的值都为划分后的第一个元素,先从数组的后面看起,high–直到发现有一个数小于key,arr[low]=arr[high],因为此时已经确定arr[low]比key小,所以low++,直到low=high;利用递归来实现对已经划分的数组再次划分,直到划分的左右两边都只有一个数。

我以前的博客有写过快排的Java实现代码,想学习的同学可以参考。

递归和非递归思想:

将数列按有序化(递增或递减)排列,查找过程中采用跳跃式方式查找,即先以有序数列的中点位置为比较对象,如果要找的元素值小 于该中点元素,则将待查序列缩小为左半部分,否则为右半部分。通过一次比较,将查找区间缩小一半。

算法步骤描述:

① 首先确定整个查找区间的中间位置 mid = ( left + right ) / 2;

② 用待查关键字值与中间位置的关键字值进行比较,只要相等,就查找成功

如果大于,则在后(右)半个区域继续进行折半查找

如果小于,则在前(左)半个区域继续进行折半查找

③ 对确定的缩小区域再按折半公式,重复上述步骤。

最后,得到结果:要么查找成功, 要么查找失败。

流程图如下:

    

递归流程图

非递归流程图

算法代码调试过程及输入输出结果:

例如输入数组大小为500时:  

对实验数据进行图表分析:(Excels和ppt生成)

源代码附上:

#include <bits/stdc++.h>//C++万能库

//排序算法设计(快速排序)
void QuickSort(int *arr,int low,int high){
		if(low<high){
		int i=low;
		int j=high;
		int key=arr[low];
		while(i<j){
			while(i<j&&arr[j]>=key) j--;
			if(i<j)
				arr[i++]=arr[j];//先赋值在自增
			while(i<j&&arr[i]<key) i++;
			if(i<j)
				arr[j--]=arr[i];//先赋值再自增
		}
		arr[i]=key;
		QuickSort(arr,low,i-1);//左边排序
		QuickSort(arr,i+1,high);//右边排序
	   }
}
//二分查找递归算法设计
int recursion_BinarySearch(int *a, const int& x, int left, int right){
    int middle = (left + right) / 2;
    if (x == a[middle]){
        return middle;//查找成功,直接返回下标
    }
    if (left >= right){
        return 0;
    } else if (x > a[middle]){
        return recursion_BinarySearch(a, x, middle + 1, right);//x>a[n/2]时,只要在数组a的右半部继续搜索x
    } else if (x < a[middle]){
        return recursion_BinarySearch(a, x, left, middle - 1);//如果x<a[n/2],则我们只要在数组a的左半部继续搜索x
    }
    return 0;
}
//二分查找非递归算法设计
int not_recursion_BinarySearch(int *a, const int &x, int n){
    int left = 0;
    int right = n - 1;
    while (left <= right){
        int middle = (left + right) / 2;
        if (x == a[middle]){
            return middle;//查找成功,返回下标
        } else if (x > a[middle]){
            left = middle + 1;//x>a[n/2]时,只要在数组a的右半部分继续搜索x
        } else{
            right = middle - 1;//如果x<a[n/2],则我们只要在数组a的左半部继续搜索x
        }
    }
    return 0;
}
int main(){
    int n;
    printf("请输入随机有序数组的大小n(1~n):");
    scanf("%d",&n);
    putchar('\n');//换行
    int *arr = new int[n];
    time_t time_;//生成时间种子
    srand((unsigned)time(&time_));//随机数发生器的初始化
    int i=0;
    while(i < n){
        arr[i] = rand() % 10000 + 1;//生成随机数
        ++i;
    }
    //快速排序
    QuickSort(arr,0,n);
    //输出框的格式设置(一行十个数)
    printf("自动生成的随机有序数组如下:\n");
    for (int i = 0; i < n; i++){
        if (i % 30== 0){
            putchar('\n');
        } else{
            printf("%d ",*(arr+i));
        }
    }
    putchar('\n');
    int x;
    for (int i = 0; i < 10; i++){
        printf("请输入需查找数值:");
        scanf("%d",&x);
        clock_t start1, end1, start2, end2;
        int  recursion_loc, not_recursion_loc;
        //计算递归二分查找时间
        start1 = clock();
        for (int i = 0; i < 10000000; i++)//一次搜索速度太快,所以循环多次
        {
            recursion_loc = recursion_BinarySearch(arr, x, 0, n - 1);
        }
        end1 = clock();

        //计算非递归二分查找时间
        start2 = clock();
        for (int i = 0; i < 10000000; i++)
        {
            not_recursion_loc = not_recursion_BinarySearch(arr, x, n);
        }
        end2 = clock();
        double time1 = ((double)(end1 - start1) / 1000);
        double time2 = ((double)(end2 - start2) / 1000);



        if (recursion_loc == 0) puts("递归方法未找到");
        else{
            printf("递归方法: ");
            printf("%d",x);
            printf(" 的位置是第 ");
            printf("%d",recursion_loc);
            printf(" 位 所用时间: ");
            printf("%.5lf",time1);
            puts("s");
        }

        if (not_recursion_loc == 0) puts("非递归方法未找到");
        else{
            printf("非递归方法: ");
            printf("%d",x);
            printf(" 的位置是第 ");
            printf("%d",not_recursion_loc);
            printf(" 位 所用时间: ");
            printf("%.5lf",time2);
            puts("s");
        }
    }
    return 0;
}




 

  • 4
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瓦特的代码小屋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值