天天看点

二分查找的非递归、递归实现及其优化

/**
 * 二分查找的非递归、递归实现及其优化
 * 算法要求序列有序
 * 1、折半查找是进行加法与除法运算的(mid=(low+high)/2)
 * 2、插值查找则进行更复杂的四则运算(mid = low + (high - low) * ((key - a[low]) / (a[high] - a[low])))
 * 3、而斐波那契查找只进行最简单的加减法运算(mid = low + F[k-1] - 1),在海量数据的查找过程中,这种细微的差别可能会影响最终的效率。
 * 因此就执行效率来说3>1>2
 * @author fwk
 */
public class BinaryChop {
    public static void main(String[] args) {
        int [] n = {,,,,,};
        System.out.println(chop(n, ));
        System.out.println(chop2(n, ,,n.length-));
        System.out.println(chop3(n, ));
        System.out.println(chop4(n, ));
    }

    /**
     * 非递归实现
     * 找到时返回下标,找不到时返回-1
     * @param array 目标数组(递增数组)
     * @param point 需要查找的数字
     * @return
     */
    public static int chop(int[] array,int point){
        if(array.length==||array==null) return -;  //处理空数组和空指针
        else{
            int low = ,high = array.length-,num = -;
            while(low<=high){
                int mid = (low+high)/;              //取中点
                if(array[mid]==point){
                    num = mid;
                    break;
                }else if(array[mid]<point) low=mid+;   //中点右移
                else high=mid-;                        //中点左移
            }
            return num;
        }
    }

    /**
     * 递归实现二分查找
     * @param array
     * @param point
     * @param low
     * @param high
     * @return
     */
    public static int chop2(int[] array,int point,int low,int high){
        //注:此处也应做数组非空检查 
        int mid = (low+high)/;
        if(low>high||point<array[low]||point>array[high]) return -;
        if(array[mid]==point) return mid;
        else if(array[mid]>point) return chop2(array, point, low, high-);
        else return chop2(array, point, low+, high);
    }

    /**
     * 优化1:插值查找
     * 插值查找算法对二分查找算法的改进主要体现在mid的计算上
     * 计算公式为:mid = ((point-array[low])/(array[high]-array[low]))*(high-low)+low
     * @param array
     * @param point
     * @return
     */
    public static int chop3(int[] array,int point){
        if(array.length==||array==null) return -;  //处理空数组和空指针
        else{
            int low = ,high = array.length-,num = -;
            while(low<high){
                int mid = ((point-array[low])/(array[high]-array[low]))*(high-low)+low;
                if(array[mid]==point){
                    num = mid;
                    break;
                }else if(array[mid]<point) low=mid+;   //中点右移
                else high=mid-;                        //中点左移
            }
            return num;
        }
    }

    /**
     * 优化2:斐波那契查找
     * @param array
     * @param point
     * @return
     */
    public static int chop4(int[] array,int point){
        int [] F = {,,,,,,,,,};     //构造斐波那契数列
        int low, high, mid, k,n=array.length-;  //n为待查找数组的长度
        low = ;
        high = n;
        k = ;
        while (n > F[k]-) /* 计算n位于斐波那契数列的位置 */
            k++;
        while (low <= high) {
            mid = low + F[k-] -;
            if (point < array[mid]){
                high = mid - ;
                k = k - ;
            }
            else if (point > array[mid]){
                low = mid + ;
                k = k - ;
            }
            else {
                if (mid <= n)
                    return mid;
                else
                    return n;
            }
        }
        return ;
    }
}
           

继续阅读