Java实现二分查找算法

什么是二分查找算法?

二分查找也称为折半查找,顾名思义,也就是将查找范围缩小一半的查找算法。
那么具体是怎么实现呢?
首先我们要明确一点,二分查找针对的是有序序列的查找。可以是从小到大排序也可以是从大到小排序,本文就以从小到大排序的数组为例子。

我们先确定几个关键的量:

  1. 首尾元素的下标,既然要将范围缩小,那么首尾下标肯定要知道啊,这样才能求出中间元素的下标。
  2. 需要查找的变量,当然这和定义的数组必须是相同类型。
  3. 数组,自定义一个有序数组或者无序数组然后手动将其排序,在其中进行查找。

二分查找的过程是这样的:
假设首元素下标为begin,尾元素下标为end,中间元素下标为mid,查找的元素为num,有序数组为arr。
在满足begin<=end的条件下:
①将num与arr[mid]进行比较,如果num=arr[mid],那么找到该元素,返回下标mid,否则将查找范围缩小一半。
②如果num<arr[mid],进行左半查找,begin不变,end=mid-1,继续从①开始。
③如果num>arr[mid],进行右半查找,end不变,begin=mid+1,继续从①开始。
总结:满足首元素下标小于等于尾元素下标时,一直循环减半查询范围直到找到元素为止;反之,元素不在该数组中。


图解二分查找过程

多说无益,还是看图说话。
定义一个有序数组[11,22,33,44,55,66,77]。
这里将首尾元素下标分别为begin和end,中间元素的下标为(begin+end)/2。
假设我们要查找的元素是11。

初始情况:
在这里插入图片描述

进行第一次查找:
在这里插入图片描述
此时判断11小于中间元素mid,所以新的查找范围缩小,此时尾部元素的下标变为mid-1。此时新的查找数组即为[11,22,33]。
在这里插入图片描述
继续~

进行第二次查找:
在这里插入图片描述
此时判断11小于中间元素,查找范围继续缩小,end变为mid-1。
新的查找数组为[11,22]。
在这里插入图片描述
继续~

进行第三次查找:
在这里插入图片描述
此时begin=0,end=1,mid=(0+1)/2=0,11=mid,所以查找到了11。

如果我们查找的元素为10,那么继续查找~
此时end=mid-1<begin,结束查询,10不在该数组中。

如果我们查找的元素是15,那么继续查找~
此时begin=mid+1=end,查找的数组中只剩22。新的arr[mid]=22,15<arr[mid] 。所以end=mid-1<begin,结束查询,15不在该数组中。

代码实现

说了这么多不如代码说的清楚,上代码!

public class BinarySearch {

    public static void main(String[] args) {
        System.out.println("请输入需要查找的正整数:");
        Scanner scanner = new Scanner(System.in);
        int num = scanner.nextInt();
        int[] arr = {11,22,33,,44,55,66,77};
        binarySearch(0, arr.length-1, num, arr);
    }

	//定义一个标签判断是否找到元素
    public static boolean flag = false;

    /**
     * 二分查找
     * @param num 需要查找的数字
     * @param arr 在该数组中查询
     * @param begin 开始下标
     * @param end  结束下标
     */
    public static void binarySearch(int begin,int end,int num,int[] arr){
        if (begin <= end){
            int mid = (end + begin)/2;
            if(num == arr[mid]){
                System.out.println("找到了!该数字在数组中的下标为:" + mid);
                flag = true;
            } else if(num < arr[mid]){
                end = mid-1;
                binarySearch(begin, end, num, arr);
            }else {
                begin = mid + 1;
                binarySearch(begin, end, num, arr);
            }
        }
        if (!flag){
            System.out.println("没有找到该数字!");
        }
    }

此时虽然已经实现了原来需要的二分查找,但是这里存在一个特殊情况,就是当数组中有多个相同的元素时,会存在查找不全!
那么该如何去处理呢?
很简单,当查找到第一个元素的下标之后,向左右遍历查找即可,直到遍历的元素与需要查找的元素不相等或者下标越界停止。(因为数组有序,所以相同的元素都是相邻的)

改进版代码如下

/**
     * 当有多个数字相同时的情况,那么查询的结果就会有多个,必须全部查出来
     * @param begin
     * @param end
     * @param num
     * @param arr
     */
    public static void binarySearchPlus(int begin,int end,int num,int[] arr){
        if (begin <= end){
            int mid = (end + begin)/2;
            if(num == arr[mid]){
                String desc = "找到了!该数字在数组中的下标为:";
                int temp = mid - 1;
                //向左遍历
                while (true){
                    if (temp < 0 || arr[temp] != num){
                        break;
                    }
                    desc += (" " + temp);
                    temp--;
                }
                //将第一个查到的元素加进去
                desc += " " + mid;
                int temp1 = mid + 1;
                //向右遍历
                while (true){
                    if (temp > end || arr[temp1] != num){
                        break;
                    }
                    desc += (" " + temp1);
                    temp1++;
                }
                System.out.println(desc);
                flag = true;
            } else if(num < arr[mid]){
                end = mid-1;
                binarySearch(begin, end, num, arr);
            }else {
                begin = mid + 1;
                binarySearch(begin, end, num, arr);
            }
        }
        if (!flag){
            System.out.println("没有找到该数字!");
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值