数据结构与算法之二分查找

二分查找是一种常用的查找算法,也叫折半查找,它是针对有序数组进行的查找操作。其基本思想是:将有序数组一分为二,通过比较查找值与中间元素的大小,缩小查找范围,直到找到查找值或查找范围缩小为0为止。

具体的实现步骤如下:

  1. 定义左右指针,分别指向数组的第一个元素和最后一个元素
  2. 计算中间位置 mid,即 mid = (left + right) / 2
  3. 比较查找值和中间位置元素的大小,如果相等则直接返回中间位置元素下标,如果查找值小于中间元素,则在左半部分继续查找,否则在右半部分继续查找
  4. 重复执行步骤2和3,直到找到查找值或查找范围缩小为0

二分查找的时间复杂度是 O(logn),比线性查找的时间复杂度 O(n) 要快得多。但是,要使用二分查找,必须保证数组是有序的,否则无法正常执行查找操作。
在这里插入图片描述



一、C 二分查找 源码实现及详解

二分查找算法也称折半查找,它是一种在有序数组中查找特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;否则如果中间元素大于(小于)要查找的元素,依据大小关系,将数组的左半部分(右半部分)作为新的查找数组,然后继续执行查找算法,直到查找到要查找的元素或者数组为空为止。

下面是 C 语言实现二分查找的源码及详解:

#include <stdio.h>

int binarySearch(int arr[], int left, int right, int target) {
    while (left <= right) {
        int mid = left + (right - left) / 2;
        
        if (arr[mid] == target) {
            return mid;
        }
        else if (arr[mid] < target) {
            left = mid + 1;
        }
        else {
            right = mid - 1;
        }
    }
    
    return -1;
}

int main(void) {
    int arr[] = {1, 3, 5, 7, 9, 11, 13};
    int n = sizeof(arr) / sizeof(arr[0]);
    int target = 9;
    int result = binarySearch(arr, 0, n-1, target);
    
    if (result == -1) {
        printf("Element is not present in array\n");
    }
    else {
        printf("Element is present at index %d\n", result);
    }
    
    return 0;
}

该代码实现了一个基本的二分查找算法。函数 binarySearch 的参数包括 arr 数组,查找范围的左右端点下标 leftright,以及要查找的目标值 target 。函数通过一个 while 循环进行查找,循环条件为左端点下标小于等于右端点下标。在每次循环中,函数通过计算中点下标(左下标加上右下标除以二)判断目标值在左半区间还是右半区间,如果中点的值正好等于目标值,直接返回中点的下标,否则不断更新左右端点,直到找到目标值或者没有剩余元素返回 -1。

在主函数中,定义了一个有序数组 arr ,并通过调用 binarySearch 函数在数组中查找目标值 9 。如果返回值为 -1,则说明目标值不存在于数组中,否则打印目标值在数组中的下标。

需要注意的是,使用二分查找算法查找的数组必须是有序的,否则无法正确找到目标元素。

在这里插入图片描述



二、C++ 二分查找 源码实现及详解

二分查找也叫折半查找,是一种在有序数组中查找特定元素的算法。它的工作原理是通过不断地将查找区间划分为两个子区间,直到找到目标元素为止。

C++ 二分查找的源码实现如下:

// 在有序序列中查找目标值,找到则返回其下标,否则返回 -1
int binarySearch(int arr[], int left, int right, int target) {
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (arr[mid] == target) {
            return mid;
        } else if (arr[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return -1;
}

该函数的参数解释如下:

  • arr:有序数组
  • left:查找区间的左边界
  • right:查找区间的右边界
  • target:目标值

函数的返回值为目标值在数组中的下标,如果找不到则返回 -1。

接下来我们对该算法进行详细解释:

  1. 初始化查找区间为整个数组,即 left = 0right = n-1,其中 n 是数组的长度。
  2. 通过计算中间位置 mid,将查找区间划分为两个子区间:[left, mid-1][mid+1, right]
  3. 如果目标值等于 arr[mid],则直接返回 mid
  4. 如果目标值小于 arr[mid],说明目标值位于左子区间,将查找区间缩小为 [left, mid-1]
  5. 如果目标值大于 arr[mid],说明目标值位于右子区间,将查找区间缩小为 [mid+1, right]
  6. 重复步骤 2~5,直到找到目标值或者查找区间为空。

二分查找的时间复杂度为 O ( log ⁡ n ) O(\log n) O(logn),因为每次查找都将查找区间缩小一半,所以最坏情况下需要进行 log ⁡ 2 n \log_2 n log2n 次查找。

在这里插入图片描述



三、java 二分查找 源码实现及详解

Java 的二分查找算法是一种高效的查找算法,可以快速地从有序数组中查找指定的元素。下面是 Java 二分查找的源码实现及详解:

public static int binarySearch(int[] a, int key) {
    int low = 0;
    int high = a.length - 1;

    while (low <= high) {
        int mid = (low + high) >>> 1;
        int midVal = a[mid];

        if (midVal < key)
            low = mid + 1;
        else if (midVal > key)
            high = mid - 1;
        else
            return mid; // key found
    }
    return -(low + 1);  // key not found
}

在上述代码中,binarySearch() 方法采用了迭代的方式实现二分查找算法。它接收两个参数:一个有序的数组 a 和要查找的元素 key,并返回查找结果的下标。

首先,算法会初始化两个指针 lowhigh,分别指向数组的第一个和最后一个元素。接着,算法在一个循环中对数组进行二分查找,直到找到指定的元素或者数组被完全遍历。

在每次迭代中,算法首先计算当前查找区间的中间位置 mid。这里采用了无符号右移运算符 >>> 来代替普通的右移运算符,可以避免因为符号位的扩展而导致的问题。

计算出中间位置后,算法将中间位置对应的数组元素的值保存在 midVal 中。如果 midVal 小于要查找的元素 key,则说明 key 在数组的右半部分,此时将 low 指针向右移动到 mid + 1 的位置;如果 midVal 大于要查找的元素 key,则说明 key 在数组的左半部分,此时将 high 指针向左移动到 mid - 1 的位置;如果 midVal 等于要查找的元素 key,则说明已经找到了,直接返回它的下标 mid

如果循环结束后仍然没有找到指定的元素,那么说明该元素不存在于数组中。根据二分查找算法的规定,此时应该返回一个负数,代表元素未找到。具体返回值的计算方式为 -(low + 1),其中 low 是指向数组第一个大于 key 的元素的指针,如果 key 所在的位置是 i,则 low 的值就是 i + 1

以上就是 Java 二分查找算法的源码实现及详解。

在这里插入图片描述






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值