初探C语言|如何在有序数列中查找一个数呢?二分查找的拿手活!

欢迎讨论:如有错误或不足,欢迎指正和建议,本人主打“听劝”。当然,如有疑问,也期待你在评论区留言互动。
点赞+关注:如果这篇文章对你有帮助,那就支持一下小编吧~~

前言

二分查找(Binary Search)是一种经典的查找算法又称折半查找法,主要用于在有序数组中高效地查找目标值。其时间复杂度为 O ( log ⁡ n ) O(\log n) O(logn),因此在大规模数据中非常实用。本文将结合一个 C 语言实现的代码,详细介绍二分查找的原理、代码实现。


简单的二分查找用例

1. 二分查找的基本原理

二分查找的核心思想是分而治之,通过不断缩小查找范围,快速定位目标值。假设我们有一个从小到大排序的数组,目标是查找一个特定的数字 k。算法的步骤如下:

  1. 定义两个指针 leftright,分别指向数组的起始位置和末尾位置。
  2. 计算中间位置的下标 mid = (left + right) / 2
  3. 比较 arr[mid]k 的关系:
    • 如果 arr[mid] == k,找到了目标值;
    • 如果 arr[mid] < k,目标值在右半部分,将 left 更新为 mid + 1
    • 如果 arr[mid] > k,目标值在左半部分,将 right 更新为 mid - 1
  4. 重复上述步骤,直到找到目标值,或 left > right 时停止查找,表示目标值不存在。

2. 实现代码

以下是实现二分查找的完整代码:


#include<stdio.h>

int main() {
    int arr[10] = { 0,1,2,3,4,5,6,7,8,9 }; // 有序数组
    int k; // 被查找的数

    printf("请输入你要查找的数 (0-9):\n");
    if (scanf("%d", &k) != 1 || k < 0 || k > 9) { // 检查输入合法性
        printf("输入非法,请输入范围内的整数!\n");
        return 1;
    }

    int left = 0;
    int right = 9;
    int mark = 0;

    while (left <= right) {
        int mid = left + (right - left) / 2; // 防止溢出的中间下标计算方式
        if (arr[mid] < k) {
            left = mid + 1;
        } else if (arr[mid] > k) {
            right = mid - 1;
        } else {
            printf("找到了,下标为 %d\n", mid);
            mark = 1;
            break;
        }
    }

    if (!mark) {
        printf("找不到\n");
    }

    return 0;
}

3. 代码详解

  1. 数组和目标值的定义

    int arr[10] = { 0,1,2,3,4,5,6,7,8,9 }; // 有序数组
    int k; // 被查找的数
    
    • arr 是一个有序数组,包含 10 个从 0 到 9 的整数。
    • k 是用户需要查找的目标值。
  2. 输入检查

    if (scanf("%d", &k) != 1 || k < 0 || k > 9) {
        printf("输入非法,请输入范围内的整数!\n");
        return 1;
    }
    
    • 确保用户输入的值是整数,并且在数组范围内。如果不符合要求,直接返回错误提示。
  3. 查找逻辑

    int left = 0;
    int right = 9;
    int mark = 0;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (arr[mid] < k) {
            left = mid + 1;
        } else if (arr[mid] > k) {
            right = mid - 1;
        } else {
            printf("找到了,下标为 %d\n", mid);
            mark = 1;
            break;
        }
    }
    
    • 定义 leftright 表示查找的范围。
    • mid 是当前中间元素的下标,比较其值与目标值 k
    • 根据比较结果调整范围:
      • 如果 arr[mid] < k,目标值在右半部分;
      • 如果 arr[mid] > k,目标值在左半部分;
      • 如果相等,则查找成功,打印结果。
  4. 查找结果

    if (!mark) {
        printf("找不到\n");
    }
    
    • 如果循环结束后 mark == 0,表示未找到目标值。

4. 测试用例

输入测试

  • 输入 5

    请输入你要查找的数 (0-9):
    5
    找到了,下标为 5
    
  • 输入 10(超出范围):

    请输入你要查找的数 (0-9):
    10
    输入非法,请输入范围内的整数!
    
  • 输入 -1(非法输入):

    请输入你要查找的数 (0-9):
    -1
    输入非法,请输入范围内的整数!
    
  • 输入不存在的值 8(如在 6 个数组中模拟)

    请输入你要查找的数 
    ...
    printf log runtime
    ---- Check Trace Root
    
    
    
    
    

例题讲解

例子场景

你买了一双鞋,告诉我价格不超过 300 元,我想知道具体价格。我们假设价格是整数,范围在 0 到 300 之间(闭区间)。我每次猜一个数,你会告诉我是不是猜对了,或者价格更高还是更低。

解决方法

折半查找的核心思想是每次猜 中间数,这样可以最大限度地减少可能的范围。

分析过程

  1. 初始化范围:设 low = 0high = 300
  2. 每次取中点:计算 mid = (low + high) // 2
  3. 比较结果
    • 如果我猜的 mid 恰好是价格,则结束查找;
    • 如果 mid 小于真实价格,你会告诉我价格更高,于是更新范围:low = mid + 1
    • 如果 mid 大于真实价格,你会告诉我价格更低,于是更新范围:high = mid - 1
  4. 循环继续:直到找到确切的价格。

实际操作

假设实际价格是 240 元,以下是折半查找的步骤:

  1. 初始范围:low = 0, high = 300mid = (0 + 300) // 2 = 150。你说价格更高。
  2. 更新范围:low = 151, high = 300mid = (151 + 300) // 2 = 225。你说价格更高。
  3. 更新范围:low = 226, high = 300mid = (226 + 300) // 2 = 263。你说价格更低。
  4. 更新范围:low = 226, high = 262mid = (226 + 262) // 2 = 244。你说价格更低。
  5. 更新范围:low = 226, high = 243mid = (226 + 243) // 2 = 234。你说价格更高。
  6. 更新范围:low = 235, high = 243mid = (235 + 243) // 2 = 239。你说价格更高。
  7. 更新范围:low = 240, high = 243mid = (240 + 243) // 2 = 241。你说价格更低。
  8. 更新范围:low = 240, high = 240mid = (240 + 240) // 2 = 240。猜中!

代码实现


#include <stdio.h>

int binarySearch(int low, int high, int target) {
    int mid;
    while (low <= high) {
        mid = (low + high) / 2; // 计算中间值
        printf("猜测的价格: %d\n", mid); // 显示猜测的价格
        if (mid == target) {
            printf("恭喜!找到价格: %d\n", mid);
            return mid; // 找到目标价格
        } else if (mid < target) {
            printf("实际价格更高。\n");
            low = mid + 1; // 调整范围到更高的一半
        } else {
            printf("实际价格更低。\n");
            high = mid - 1; // 调整范围到更低的一半
        }
    }
    printf("未找到价格。\n");
    return -1; // 没有找到目标值
}

int main() {
    int low = 0;            // 最低价格
    int high = 300;         // 最高价格
    int target = 240;       // 实际价格(用于模拟)

    printf("开始折半查找...\n");
    binarySearch(low, high, target);

    return 0;
}

优点分析

  1. 时间复杂度为 O ( log ⁡ n ) O(\log n) O(logn),非常高效。
  2. 简单且容易实现。

结语

二分法的思想也常用于其他问题,如查找有序数组中的特定值或优化搜索空间问题。建议大家去深度学习。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值