Java教程

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

本文主要是介绍数据结构与算法--二分查找,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

简介

二分查找又称折半查找、二分搜索、折半搜索等,是在分治算法基础上演变的查找算法

二分查找算法仅适用于有序序列,它只能用在升序序列或者降序序列中查找目标元素


二分查找局限性

依赖数组结构

二分查找需要利用下标随机访问元素,如果使用链表等其他数据结构则无法实现二分查找

针对有序的数据

二分查找需要的数据必须是有序的。如果数据没有序,需要先排序,排序的时间复杂度最低是 O(nlogn)。所以,如果针对的是一组静态的数据,没有频繁地插入、删除,可以进行一次排序,多次二分查找

如果数据集合有频繁的插入和删除操作,要想用二分查找,要么每次插入、删除操作之后保证数据仍然有序,要么在每次二分查找之前都先进行排序。针对这种动态数据集合,无论哪种方法,维护有序的成本都是很高的

二分查找只能用在插入、删除操作不频繁,一次排序多次查找的场景中。针对动态变化的数据集合,二分查找将不再适用

数据量大小

  • 数据量太小不适合二分查找

    如果要处理的数据量很小,完全没有必要用二分查找,顺序遍历就足够了

  • 数据量太大不适合二分查找

    二分查找底层依赖的是数组,数组需要的是一段连续的存储空间,所以数据比较大时,比如1GB,这时候可能不太适合使用二分查找,因为内存都是离散的,可能电脑没有这么多的内存


算法图解

从图中可以看出,每次查找目标值时都需要将目标值跟中间值进行比较,以判断出目标值在中间值的左边还是右边亦或是目标值就是中间值

中间值得计算有两种方式:

right 表示搜索区域内最后一个元素所在位置,left 表示搜索区域内第一个元素所在的位置,mid 表示中间元素所在的位置

  • 方法一:mid = ( left + right) / 2
    • 该方法存在溢出的风险,当 left 和 right 比较大时,有可能会导致 mid 的值错误,从而使程序出错
  • 方法二:mid = left + (right - left) / 2
    • 该方法则可以保证生成的 mid 一定大于 left,小于 right


代码实现

循环方法

/**
 * 二分查找--循环方法
 * @param arr       原数组
 * @param left      左指针
 * @param right     右指针
 * @param target    目标值
 * @return          寻找目标值第一次出现的下标值,不存在则返回-1
 */
public int binarySearch(int[] arr,int left,int right,int target){

    int mid = left + (right - left) / 2;
    while (left < right) {
        if (target > arr[mid]) {
            //目标值位于中间值的右边
            left = mid + 1;
        } else if (target < arr[mid]){
            //目标值位于中间值的左边
            right = mid - 1;
        } else if (target == arr[mid]){
            //找到目标值下标
            return mid;
        }

        //找出中间值下标
        mid = left + (right - left) / 2;
    }

    //找不到
    return -1;
}

递归方式

/**
 * 二分查找--递归方式
 * @param arr       原数组
 * @param left      左指针
 * @param right     右指针
 * @param target    目标值
 * @return  寻找目标值第一次出现的下标值,不存在则返回-1
 */
public int binarySearch(int[] arr,int left,int right,int target){

    //没有在数组中找到目标值
    if (left > right) {
        return -1;
    }

    //获取该次查找目标值的数组中间值下标
    int mid = left + (right - left) / 2;

    if (target > arr[mid]){
        //目标值大于中间值,则目标值在中间值的右边
        return binarySearch(arr,mid + 1,right,target);
    } else if (target < arr[mid]){
        //目标值小于中间值,则目标值在中间值的左边
        return binarySearch(arr,left,mid - 1,target);
    } else {
        //查到目标值第一次出现的下标值
        return mid;
    }
}
这篇关于数据结构与算法--二分查找的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!