C语言----二分查找

1.了解认识二分查找

二分查找是一种在有序数组中查找特定元素的算法。它的工作原理是将数组分成两半,然后确定目标值可能在哪一半,最终缩小搜索范围直到找到目标值或确定目标值不存在为止。

具体步骤如下:

a.初始化两个指针,一个指向数组的起始位置(通常称为左指针),一个指向数组的结束位置(通常称为右指针)。
b.计算中间位置的索引:mid = (left + right) / 2。
c.比较中间元素与目标值:
如果中间元素等于目标值,则找到了目标,返回中间元素的索引。
如果中间元素大于目标值,则目标值可能在左半部分,更新右指针:right = mid - 1。
如果中间元素小于目标值,则目标值可能在右半部分,更新左指针:left = mid + 1。
4.重复步骤 2 和 3,直到找到目标值或左指针大于右指针为止。

这种算法的时间复杂度是 O(log n),其中 n 是数组的长度。二分查找通常在有序数组中效率很高,但前提是数组必须是有序的。

2.二分查找的三种方法

a.递归法
-----------递归法是一种直观且简洁的实现方式。
在每一步中,递归函数会计算中间位置 mid,并比较中间元素与目标值。
----如果中间元素等于目标值,返回中间元素的索引。
----如果中间元素大于目标值,在左半部分递归查找。
----如果中间元素小于目标值,在右半部分递归查找。
递归的结束条件是找到目标值或左指针大于右指针。

#include <stdio.h>
// 递归实现的二分查找函数
// 参数说明:arr为有序数组,target为要查找的目标值,left和right分别为查找范围的左右边界
int binarySearchRecursive(int arr[], int target, int left, int right) {
    if (left <= right) {
        int mid = left + (right - left) / 2;

        if (arr[mid] == target) {
            return mid;  // 如果中间元素等于目标值,则返回中间元素的下标
        }
        else if (arr[mid] > target) {
            // 如果中间元素大于目标值,在左半部分递归查找
            return binarySearchRecursive(arr, target, left, mid - 1);
        }
        else {
            // 如果中间元素小于目标值,在右半部分递归查找
            return binarySearchRecursive(arr, target, mid + 1, right);
        }
    }
    else {
        return -1;  // 如果左指针大于右指针,说明目标值不存在,返回 -1
    }
}

int main() {
    int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    int target = 0;
    scanf_s("%d",&target);
    int result = binarySearchRecursive(arr, target, 0, sizeof(arr) / sizeof(arr[0]) - 1);

    if (result != -1) {
        printf("找到了,下标是%d\n", result);
    }
    else {
        printf("找不到\n");
    }

    return 0;
}

b.迭代法:
----- 迭代法是使用循环来实现的,通过更新左右指针来不断缩小搜索范围。
-----循环的条件是左指针小于等于右指针。
-----在每一步中,计算中间位置 mid,并比较中间元素与目标值。
-----根据比较结果更新左右指针。

#include <stdio.h>

int main()
{
    int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    int left = 0;
    int right = sizeof(arr) / sizeof(arr[0]) - 1;
    int key = 0;  // 要查找的数字,从用户输入获取
    scanf_s("%d", &key);
    int mid = 0;  // 记录中间元素的下标
    int find = 0;  // 记录是否找到目标值

    // 使用迭代法进行二分查找
    while (left <= right)
    {
        mid = (left + right) / 2;

        if (arr[mid] > key)
        {
            right = mid - 1;  // 如果中间元素大于目标值,在左半部分继续查找
        }
        else if (arr[mid] < key)
        {
            left = mid + 1;  // 如果中间元素小于目标值,在右半部分继续查找
        }
        else
        {
            find = 1;  // 如果中间元素等于目标值,标记为找到
            break;
        }
    }

    // 输出结果
    if (1 == find)
        printf("找到了,下标是%d\n", mid);
    else
        printf("找不到\n");

    return 0;
}

左侧边界查找:
----有时候,二分查找并不仅仅是为了找到目标值是否存在,而是找到目标值的左侧边界(最左边的相同值的位置)。
----在比较中间元素时,如果中间元素大于等于目标值,在左半部分继续查找。
----如果中间元素小于目标值,在右半部分继续查找,但要更新左指针为 mid + 1,因为要找的是左侧边界。
左侧边界查找法的步骤如下:

1.初始化左右指针,左指针初始化为 0,右指针初始化为数组长度。
2.在每一步中,计算中间位置的索引:mid = (left + right) / 2。
3.比较中间元素与目标值:
----如果中间元素小于目标值,说明目标值可能在右半部分,更新左指针:left = mid + 1。
----如果中间元素大于等于目标值,说明目标值可能在左半部分,更新右指针:right = mid。
4.重复步骤 2 和 3,直到找到目标值的最左边位置。

#include <stdio.h>

// 左侧边界查找的函数
// 参数说明:arr为有序数组,target为要查找的目标值,size为数组的大小
int leftBoundBinarySearch(int arr[], int target, int size) {
    int left = 0;
    int right = size;

    while (left < right) {
        int mid = (left + right) / 2;

        if (arr[mid] < target) {
            left = mid + 1;  // 如果中间元素小于目标值,在右半部分继续查找左侧边界
        }
        else {
            right = mid;  // 如果中间元素大于等于目标值,在左半部分继续查找左侧边界
        }
    }

    return left;  // 返回左侧边界的下标
}

int main() {
    int arr[] = { 1, 2, 2, 2, 4, 5, 6, 7, 8, 9 };
    int target = 0;
    scanf_s("%d", &target);
    int result = leftBoundBinarySearch(arr, target, sizeof(arr) / sizeof(arr[0]));

    printf("左侧边界的下标是 %d\n", result);

    return 0;
}
  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值