算法——查找

99 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,[点击查看活动详情]

查找算法,排序算法,除了要讨论算法本身的好坏之外,还要讨论数据本身的分布情况。有些数据是随机分布的,方差大。

根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素。
1,顺序查找
2,二分查找
3,插值查找
4,斐波那契查找
5,数表查找
6,分块查找
7,哈希查找

顺序查找

线性查找,属于无序查找算法
开始端——>顺序扫描——>与定值相比较——>相等,成功。不相等,失败。
适合于存储结构为顺序存储或链接存储的线性表。
时间复杂度为O(n);

顺序查找代码

public class LinearSearch{
    public static void main(String[] args){
        int[] arr={3,9,1,4,5,2,6,8,7};
        int key=8;
        int index = linearSearch(arr,key);
        System.out.println("index = "+index);
    }
    private static int linearSearch(int[] arr,int key){
        for(int i=0;i<arr.length;i++){
            if(arr[i]==key){
                return i;
            }
        }
        return -1;
    }
}

二分查找

折半查找,属于有序查找算法。
定植与中间结点关键字比较——>相等,则成功,不等——>定植与子表比较,递归进行——>结束。
前提:元素是有序的。
时间复杂度为O(log2n).
适用于静态查找表。不适用频繁执行插入或删除操作的数据集。\

代码

迭代法

public class BinarySearch{
    public static void main(String[] args){
        int[] arr={1,2,3,4,5,6,7,8,9};
        int key=8;
        int index=binarySearch(arr,key);//角标
        System.out.println("index = "+index);
    }
   private static int binarySearch(int[] arr,int key){
       int low = 0;
       int high=arr.length-1;
       int mid=(low+hige)/2;
       while(arr[mid]!=key){
           if(arr[mid]>key){
               high=mid-1;
           }else if(arr[mid]<key){
               low=mid+1;
           }
           if(low>high){
               return -1;
           }
           mid=(low+high)/2;
       }
       return mid;
   }
}

这里类似于循环

递归法

int index=binarySearch(arr,key,0,arr.length-1);
System.out.println("index = "+index);
private static int binarySearch(int[] arr,int key,int low,int high){
    if(low>high){
        return -1;
    }
    int mid=(low+high)/2;
    if(arr[mid]==key){
        return mid;
    }
    if(key<arr[mid]){
        return binarySearch(arr,key,low,mid-1);
    }else{
        return binarySearch(arr,key,mid-1,high);
    }
}

类似于分治(大问题化为小问题)。
计算式:mid=low+1/2*(high-low),避免相加导致整型溢出。

插值查找

类似于二分查找。适用于分布均匀(方差)的查找表。
计算式:mid=low+(key-a[low])/(a[high]-a[low])*(high-low)
时间复杂度:O(log2(log2n)).log2(log2n)<log2n\

代码

public class InterpolationSearch{
    public static void main(String[] args){
        int[] arr={1,5,12,21,30,32,55,68,80,89,90,99};
        int key = 30;
        int index = interpolationSearch(arr,key,0,arr.length-1);
        System.out.println("index = "+index);
    }
    private static int interpolationSearch(int[] arr,int key,int low,int high){
        if(low>high){
            return -1;
        }
        int mid=low+(int)(1.0*(key-arr[low])/(arr[high]-arr[low])*(high-low));
        System.out.println("mid = "+mid);
        if(mid<low||mid>high){
            return -1;
        }
        if(arr[mid]==key){
            return mid;
        }else if(arr[mid]>key){
            return interpolationSearch(arr,key,low,mid-1);
        }else{
            return interpolationSearch(arr,key,mid+1,high);
        }
    }
} 

斐波那契查找

是在二分查找的基础上根据斐波那契数列进行分割的。
是区间中单峰函数的搜索技术。
黄金比例:1:0.618,1.618:1。随着斐波那契的递增,前后两数的比值接近0.618.

代码

public class FibonacciSearch{
    public static void main(String[] args){
        int[] arr={1,2,3,4,5,6,7,8,9};
        int key=8;
        int index = fibonacciSearch(arr,key);
        System.out.println("index = "+index);
    }
    private static int fibonacciSearch(int[] arr,int key){
        int[] f=getFibonacci();
        int low = 0;
        int high = arr.length-1;
        int mid=0;
        int k=0;
        while(high>f[k]-1){
            k++;
        }
        int[] temp = Arrays.copyOf(arr,f[k]);
        for(int i=high+1;i<temp.length;i++){
            temp[i]=arr[high];
        }
        
        while(low<=high){
            mid=low+f[k-1]-1;
            if(key<tem[mid]){
                high=mid-1;
                k-=1;
            }else if(key>temp[mid]){
                low=mid+1;
                k-=2;
            }else{
                if(mid<=high){
                    return mid;
                }else{
                    return high;
                }
            }
        }
        return -1;
    }
    
    private static int[] getFibonacci(){
        int f = new int[20];
        f[0]=1;
        f[1]=1; 
        for(int i =2;i<f.length.length;i++){
            f[i]=f[i-1]+f[i-2];
        }
        return f;
    }
}