二分查找算法

刚才看到五大常用算法之一的分治法,分治法有分而治之的思想,把规模不断的缩小,这样就会用到递归。二分查找也是分治法的一种实现。


在二分查找算法的两种实现方式中,就有一个是递归的实现方式,另一种就是循环的实现方式。


二分查找算法实现的前提:已排序的数组。


二分查找(折半查找)算法原理:将已排好序的数组,取出最小值的下标(即第一个值)和最大值的下标(即数组中的最后一个值)。根据这两个值得到数组的中间值的下标已经所对应的中间值,并根据这个中间值与需要查找的数进行判断大小。如果相等,就直接输出该值。如果中间值小于需要查找的数,让循环实现或者递归实现的最小值范围变为中间值+1,。如果中间值大于需要查找的数,让实现的最大值变为中间值-1。依次缩小范围,如果这个需要查找的元素在数组中就会输出那个值所对应的下标;如果这个值不在数组中,就会返回-1。


时间复杂度:最好的情况肯定是O(1)

                       平均时间复杂度:O(lgn)

       推理过程:   查找第1次能找到,会定位1个位置,查到的概率是1/n;

                              查找第2次能找到,会定位2个位置,查到的概率是2/n;

                              查找第3次能找到,会定位4个位置,查到的概率是4/n;

                              ......

                              查找第n次能找到,会定位2^m-1个位置,查到的概率是(2^m-1)/n;

                     由于有n个元素,最多会查m次,根据求和公式

                       

以下是我借鉴别人的代码,但是也是自己手动敲上去,明白其中的原委。

为了图省事,测试和实现的内容都写在一个类里面了。

public class BinarySearch {
    private int rCount = 0;
    private int lCount = 0;

    //计算递归的次数
    public int showRecursionCount() {
        return rCount;
    }

    //计算循环的次数
    public int showLoopCount() {
        return lCount;
    }

    /**
     * 利用递归实现二分查找
     * @param orderArray  已经排好序的数组
     * @param left  数组最左边的值
     * @param right  数组最右边的值
     * @param findValue  查找的元素
     * @return
     */
    public int recursionBinarySearch(int[] orderArray, int left, int right, int findValue) {
        rCount++;

        if(left <= right) {
            int middle = (left + right) / 2;
            int middleValue = orderArray[middle];
            if(findValue == middleValue) {
                return middle;
            } else if(findValue > middleValue) {
                return recursionBinarySearch(orderArray, middle + 1, right, findValue);
            } else {
                return recursionBinarySearch(orderArray, left, middle - 1, findValue);
            }
        } else {
            return -1; //需要查找的数不在数组范围内
        }
    }

    /**
     * 利用循环实现二分查找
     * @param orderArray 已经排好序的数组
     * @param findValue 查找的元素
     * @return
     */
    public int loopBinarySearch(int[] orderArray, int findValue) {
        int start = 0;
        int end = orderArray.length - 1;

        while(start <= end) {
            lCount++;
            //中间值
            int middle = start + (end - start) / 2;
            int middleValue = orderArray[middle];
            if(findValue == middleValue) {
                return middle;
            } else if(findValue < middleValue) {
                end = middle - 1;
            } else {
                start = middle + 1;
            }
        }
        return -1; //找不到的时候
    }

    public static void main(String[] args) {
        int[] orderArray = {1,3,5,6,7,8,9,11,14,21,35};
        int findValue = 9;
        int length = orderArray.length;

        BinarySearch binarySearch = new BinarySearch();
        int index = binarySearch.recursionBinarySearch(orderArray, 0, length - 1, findValue);
        int reTimes = binarySearch.showRecursionCount();
        System.out.println("利用递归的二分查找,得到该值在数组中的位置" + index + ",循环次数为" + reTimes);

        index = binarySearch.loopBinarySearch(orderArray, findValue);
        int loopTimes = binarySearch.showLoopCount();
        System.out.println("利用循环实现的二分查找,得到该值在数组中的位置" + index + ",循环次数为" + loopTimes);
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值