Java基础篇---------数组二分查找法

首先通过两个例子了解二分查找法是什么,以及为什么要使用二分查找法。

假设有一万个连续的整数0~9999,这些数字混乱排列,现在需要在这一万个数字中找到6666这个数字。

最为直接的方法是从左到右一个一个找或者从右到左一个一个找(线性查找法),直到找到6666这个数字,那么最坏的情况是找到第10000个数字才找到6666。当然,这对于一个人来说是非常坏的情况,可计算机的处理速度很快,就算是最坏的情况在目前各种强大的CPU面前也丝毫不会影响程序的运行速度。可是,在实际情况中数据量可能会很大,上千万甚至上亿,还有可能查找数字的方法会持续性的被调用。这种情况下,纵然CPU有强大处理能力也扛不住如此折腾。

假设有连续的整数0~9999,这些数字顺序排列,现在需要在这些数字中找到6666这个数字。

当我们以人类的思维看这个问题的时候会觉得非常的简单。第一点,数字顺序排列,最多只要找6667次就能找到6666这个数字。第二点,已经知道了需要找的是6666这个数字,所以这个数字在5000~9999之间,这时候0~4999折5000个数字不许要去考虑。当我们知道了6666这个数字的时候为什么却确定这个数字在5000~9999之间呢?因为我们知道5000是10000的一半,而5000比6666小,6666比9999小,所以自然的得出这个数字在5000~9999之间。这种思维方式就是我今天要将的主要内容--二分查找法,至于为什么要使用二分查找法的原因也很明显,二分查找法的效率明显要高于线性查找法。

PS:使用二分查找法的前提是数据必须是顺序排列,当没有其它影响的情况下可以考虑将混乱的数据先进行排序,Arrays类中的sort()提供了对数组数据进行排序的方法。比如在一个混乱的数组中判断是否有某个值,可以考虑将数组先进行排序,再用二分法进行查找,当然前提条件是这个方法可能会被调用比较多的次数,如果该方法只可能会被调用一次,那么将数组先进行排序再进行二分查找是不必要的,从时间上来讲可能还是直接使用线性查找法来的更快

Java基础篇---------数组二分查找法_第1张图片 如果关键字小于中间元素,只需要在数组的前一半元素中继续査找关键字。
如果关键字和中间元素相等,则匹配成功,査找结束。
 如果关键字大于中间元素,只需要在数组的后一半元素中继续査找关键字。

 

上图为在13个数字中通过二分查找法查找11的实例,通过具体的例子相信能帮助大家更好的理解二分查找法的原理。

了解完了何为二分查找法,以及为什么要使用二分查找法,下面来讲讲二分查找法的最大比较次数。

假设数组有n个元素。为方便起见,假设 n 是 2 的幂。经过第1 次比较,只剩下 n / 2 个元素需要进一步査找;经过第 2 次比较,剩下( n / 2 ) / 2 个元素需要进下—步査找。经过 k 次比较之后,需要査找的元素就剩下  n / 2k个 。 当 k=\log_{2}n 时,数组中只剩下1个元素,就只需要再比较1次。因此,在一个已经排序的数组中用二分査找法査找一个元素,即使是最坏的情况,也只需要 \log_{2}n+1 次比较。对于一个有 1024 ( 2^10 ) 个元素的数组,在最坏情况下,二分査找法只需要比较 11 次,而在最坏的情况下线性査找要比较1023次。

下一步我们引用一下百度百科里关于二分查找的流程图,在写程序之间理清开发思路。

Java基础篇---------数组二分查找法_第2张图片

二分查找法查找数组中某个数字下标的具体代码如下: 

public static int binarySearch(Integer[] srcArray, int des)
    {
        // 定义初始最小、最大索引
        int low = 0;
        int high = srcArray.length - 1;
        // 确保不会出现重复查找,越界
        while (low <= high)
        {
            // 计算出中间索引值
            // (high + low) >>> 1 等同于 (high+low)/2,但是要求high和low的合要大于等于0
            //>>>是位运算符,只对整型有效(不能用于浮点型)。
            //这里计算平均值使用>>>取代>>,是因为可能出现很大的数字,这些数字单独用不会超过Integer.MAX_VALUE,
            //但求和之后可能超过,这时如果使用>>或者/来计算,会因为溢出而算出负数结果。
            int middle = (high + low) >>> 1;
            if (des == srcArray[middle])
            {
                return middle;
                // 判断下限
            }
            else if (des < srcArray[middle])
            {
                high = middle - 1;
                // 判断上限
            }
            else
            {
                low = middle + 1;
            }
        }
        // 若没有,则返回-1
        return -1;
    }

 Arrays.binarySearch(int[] a, int key)提供了二分查找法。上面的代码就是其源码,所以当我们需要使用二分查找法查找数据下标的时候只需要调用Arrays.binarySearch()方法即可。

 

 

你可能感兴趣的:(JAVA基础)