【C语言】二分查找

题目

编写代码在一个整形有序数组中查找具体的某个数

要求:找到了就打印数字所在的下标,找不到则输出:找不到

方法

对于在整形有序数组中查找我们可以使用二分查找法,下面具体介绍一下该方法

例如,现在有一个有序数组arr[10]={1,2,3,4,5,6,7,8,9,10};我们想要查找该数组中的7这个数,应该怎么办呢?我们可以用循环遍历,让他一个一个的查找,直到找到对应的元素,但是这种方法显然过于粗暴和繁杂,不符合我们编译代码时要求简洁高效的原则,于是我们可以使用二分查找,二分查找其实就是让左右元素判断出中间元素,在通过中间元素向我们要查找的元素进行推进,当中间元素等于要找的元素时结束查找。与遍历不同的是,对于我们设定的左右元素,不在他们包括中的元素是不需要判断的,这样便节省了代码和时间。

首先,我们可以设置下标0为left,下标9为right,令(left+right)/2可以得到middle=4,也就是说中间元素为5,可是我们要找的元素7在5的右边,于是我们可以缩小范围——即将这里算出来的middle

后一位变成left,这样我们要查找的范围就变成了6-9,而6前面的元素便省去了查找的过程直接甩掉。

接着,我们继续将left和right进行运算,找到下一个middle元素8,我们可以看到8比我们要找的元素7更大,因此我们可以将right=middle-1也就是元素7,那么查找范围变成了6-7,我们继续查找,将这两个的中间值算出来后发现middle=6,我们要查找的元素在右边,那么left=middle+1,得到元素7,这下左右元素都等于7,运算后中间值也就等于7,找到了我们要找的元素。

明白了大概原理后,我们可以进行编译代码

代码

我们可以给定一个自定义函数,让解析过程都在自定义函数进行

int search(int arr[], int k,int sz)
{
    int left = 0;
    int right = sz - 1;
    while (left<=right)//如果left>right根据left前面和right后面元素舍掉不计的原理,将没有元素可以查找
    {
        int mid = left + (right - left) / 2;
        if (arr[mid] < k)
        {
            left = mid - 1;
        }
        else if (arr[mid] > k)
        {
            right = mid - 1;
        }
        else//如果中间值就是要查找的值,那么直接返回
        {
            return mid;
        }
    }
    return -1;//如果没有找到返回一个不属于数组中的值
}
//二分查找是一个循环,这里面的代码只做到了一次查找,需要多次
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int k = 0;
    scanf_s("%d", &k);//输入想要查找的元素
    int sz = sizeof(arr) / sizeo(arr[0]);//计算数组的长度
    int ret = search(arr, k,sz);//将查找元素,数组长度,和数组传入函数中进行运算
    if (ret == -1)
        printf("找不到\n");
    else
        printf("找到了,下标是:%d\n", ret);
    return 0;
}

同理,不用自定义函数也可以完成代码,只不过在判断是否能查找到元素时需要引入一个变量,如果查找到了值便设定变量为1,没有便为0,这样在判断时可以直接用变量判断。

注:怎么理解mid = left + (right - left) / 2?

为什么不用(left+right)/2呢?因为如果两个值足够大,加起来的值会造成数据溢出,形成错误,因此我们可以换个方法计算平均值

我们假如right的值比left大,那么我们将right比left大的值去掉一半,加到left上,就可以等于现在right的值,而现在两个元素的值,就是他们的平均值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值