查询算法学习

 1.二分查找:

                算法描述:

        二分查找法主要利用折半的思想,每次查询的时候都可以排除一半的数字,从而提高查询的速度
        二分查找法只能针对有序的数组进行查询。
    算法过程描述
        先取出已排序的数组的中间值,和目标值进行比较。
        如果目标值比中间值大,则再从将中间值开始到尾部的数组的中间值拿出来再次比较。
        如果目标值比中间值小,则从中间值开始到头部的数组的中间值拿出来再次比较。
可以递归实现左右数组的再次查询,直到找到目标,或者左右数组无法在分割

package advanced;

/**
* 二分查找
 * */
public class BinarySearchs {
    public static void main(String[] args) {
        int[] arr={3,5,6,9,9,15,46,65};
        int target=9;
        int result=binarySearchs(arr,target,0,arr.length-1);
        if (result==-1){
            System.out.println("没有找到该目标数据");
        }else {
            System.out.println("找到的索引为:"+result);
        }
    }

    public static int binarySearchs(int[] arr,int target,int left,int right){
        int result=-1;

        if (left>right){

            return result;
        }
            int mid=(left+right)/2;
            if (target>arr[mid]){
                return binarySearchs(arr,target,mid+1,right);
            }else if(target<arr[mid]){
                return binarySearchs(arr,target,left,mid-1);
            }else {
                return mid;
            }
    }
}

2.插值查找:

                  算法描述:

二分查找法查找点的算法:
            mid = = first + (last-first)/2
        通过类比,我们可以将查找的点改进为如下:
            first+ (target-a[first])/(a[last]-a[first])*(last-first)
也就是将上述的比例参数1/2改进为自适应的,根据关键字在整个有序表中所处的位置,
让mid值的变化更靠近关键字key,这样也就间接地减少了比较次数。
        基本思想:基于二分查找算法,将查找点的选择改进为自适应选择,可以提高查找效率。
当然,差值查找也属于有序查找。
        对于表长较大,而关键字分布又比较均匀的查找表来说,插值查找算法的平均性能比折半查找要好的多。反之,数组中如果分布非常不均匀,那么插值查找未必是很合适的选择。
        另外由于target也参与了mid值的计算,那么就可以出现负数或者超过数组长度的值,所
以也需要提前进行判断

package advanced;

/**
* 插值查找
* */
public class InterpolationSearch {
    public static void main(String[] args) {
        int[] arr={1,2,5,6,8,9,13,15,18,26,27,90};
        int target=90;
        int result=interpolationSearch(arr,target,0,arr.length-1);
        if (result==-1){
            System.out.println("没有找到");
        }else {
            System.out.println("该目标索引为:"+result);
        }
    }

    public static int interpolationSearch(int[] arr,int target,int left,int right){
        int result=-1;
        if (left>right||target<arr[0]||target>arr[arr.length-1]){
            return result;
        }

        int mid=left+((target-arr[left])/(arr[right]-arr[left]))*(right-left);
        if (target==arr[mid]){
            return mid;
        }else if(target>arr[mid]){
            return interpolationSearch(arr,target,mid+1,right);
        }else {
            return interpolationSearch(arr,target,left,mid-1);
        }
    }
}

3.斐波那契查找:

                          算法描述:

1.先构造用于查询中间值的斐波那契数列f,通过查询数组的last下标并且计算出数列的
长度k;
    2.如果查询数组arrs不够斐波拉契数组最大值的长度f(k)的值,则需要将查询数组
扩容到f(k)一样的长度的临时数组temp,并且将多余的值使用查询数组最大值arrs[last]
进行补全
    3.将中间值mid设置成 first + f(k-1)-1
    4.然后进行非递归二分查找法
判断目标值target如果比temp[mid]大,那么则从右边再次查询,设置first =
mid +1,k值需要减2
如果目标值target比temp[mid]小,则从左边再次查询,设置last=mid-1,k值需
要减1
查询到目标之后
如果mid小于last,则直接返回mid
如果mid大于last,那么则直接返回last

 

 

 

 

package advanced;

import java.util.Arrays;

public class FibonacciSearchs {
    public static void main(String[] args) {
        int[] arrs={1,2,7,18,19,21,77,99,666};
        int[] f=getFibList(arrs.length);
        //        斐波那契数组需要的个数。
        int k=0;
        for (int i = 0; i < f.length; i++) {
            while (f[i]>=arrs.length){
                k=i;
                break;
            }
        }

        //创建一个临时数组,补全数组长度和斐波那契数组对应k的值的大小
        int[] temp=new int[f[k]];
        for (int i = 0; i < f[k]; i++) {
            if (i>=arrs.length-1){
                temp[i]=arrs[arrs.length-1];
                continue;
            }
            temp[i]=arrs[i];
        }

        System.out.println("斐波那契数列:"+Arrays.toString(f));
        System.out.println("临时数组:"+Arrays.toString(temp));

        //使用二分查找法实现查询
        int first=0;
        int last=arrs.length-1;
        int target=7154;
        int i=1;
        while (first<=last){
            int mid=first+f[k-i]-1;
            if (temp[mid]==target){
                if (mid>=arrs.length-1){
                    mid=arrs.length-1;
                }
                System.out.println("找到了该目标的索引为"+mid);
                return;
            }else if(temp[mid]>target){
                last=mid-1;
                i+=2;
            }else {
                first=mid+1;

                i+=1;
            }
        }
        System.out.println("没有找到该目标值");
    }

    //构造斐波那契数列
    public static int[] getFibList(int maxSize){
        //创建数列:
        int[] f=new int[maxSize];
        //0和1的值都是1
        f[0]=1;
        f[1]=1;
        for (int i = 2; i < f.length-1; i++) {
            f[i]=f[i-1]+f[i-2];
            if (f[i]>=maxSize){
                return f;
            }
        }
        return null;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值