查找算法介绍

查找算法介绍

在java中常用的查找算法一共有四种
1、顺序(线性)查找
2、二分查找(折半查找)
3、插值查找
4、斐波那契查找

一、顺序查找
基本原理:对于任意一个序列以及一个给定的元素,将给定元素与序列中元素依次比较,直到找出与给定关键字相同的元素,或者将序列中的元素与其都比较完为止。
代码如下:

public class queSearch {
    public static void main(String[] args) {
        int[] arr = {5,11,3,64,95,11,2,35,4};
       List list = search(arr,11);
        if (list.size() == 0){
            System.out.println("没有找到您要搜索的数据索引位置");
        }else{
            System.out.println("您要搜索数据的位置为:" + list.toString());
        }
    }

    public static List search(int[] arr,int value){
        List list = new ArrayList();
        for (int i=0;i<arr.length;i++){
            if (value == arr[i]){
                list.add(i);
            }
        }
        return list;
    }
}

结果如下:
在这里插入图片描述
二、二分查找
思路分析:
所需要查找的序列必须是有序的
1、首先确定该数组的中间的下标,mid = (left + right) / 2;
2、然后让需要查找的数findVal与arr[mid]比较
  2.1如果findVal < arr[mid],说明需要查找的数在mid左边,因此需要继续递归向左查找
  2.2如果findVal > arr[mid],说明需要查找的数在mid右边,因此需要继续递归向右查找
  2.3如果findVal = arr[mid],说明需要查找的数位置就是mid,直接返回结果
结束递归的条件:
1.找到就结束递归
2.递归完整个数组,仍然没有找到,就需要结束,此时left>right递归结束

代码如下:

public class BinarySearch {
    public static void main(String[] args) {
        int[] arr = {153,654,987,1000,1000,1023,1254,2148};
        List<Integer> list = search(arr,0,arr.length-1,1000);
        System.out.println(list);
    }

    public static List<Integer> search(int[] arr,int left,int right,int findVal){
        if (left > right){
            return new ArrayList();
        }
        int mid = (left + right) / 2;
        int midVal = arr[mid];
        List<Integer> indexVal = new ArrayList<>();
        if (findVal < midVal){
            return search(arr,left,mid - 1,findVal);
        }else if (findVal > midVal){
           return search(arr,mid + 1,right,findVal);
        }else{
            int index = mid;
            while (true){
                if ((index-1)<0 || arr[index-1] != findVal){
                    break;
                }
                index = index - 1;
                indexVal.add(index);
            }
            indexVal.add(mid);
            index = mid;
            while (true){
                if ((index+1)>(arr.length-1) || arr[index+1] != findVal){
                    break;
                }
                index = index + 1;
                indexVal.add(index);
            }
        }
        return indexVal;
    }
}

结果如下:
在这里插入图片描述
三、插值查找
插值查找原理介绍:
(1)插值查找算法类似于二分查找,不同的是插值查找每次从自适应mid处开始查找。
(2)将折半查找中的求mid索引的公式,left表示左边索引,right表示右边索引,key就是要寻找的数据值,则mid取值如下:mid = (left + right)/2 = left + 1/2(right - left)
将上述折半查找的公式改写为:mid = left + {(key - arr[left])/(arr[right]-arr[left])}*(right - left)

代码如下:

public class InsertSearch {
    public static void main(String[] args) {
        int[] arr = new int[100];
        for (int i=0;i<100;i++){
            arr[i] = i;
        }
        int index = insertSearch(arr,0,arr.length -1,90);
        System.out.println(index);
    }

    public static int insertSearch(int[] arr,int left,int right,int key){
        System.out.println("进行插值查找");
        if (left > right || key < arr[0] || key > arr[arr.length -1]){
            return -1;
        }
        int mid = left + (right - left) * (key - arr[left])/(arr[right] - arr[left]);
        int midVal = arr[mid];
        if (key > midVal){
            return insertSearch(arr,mid + 1,right,key);
        }else if(key < midVal){
            return insertSearch(arr,0,mid -1,key);
        }else {
            return mid;
        }
    }
}

结果如下:
在这里插入图片描述
可以看出如果有序序列的波动不大,分布比较均匀的话使用插值查找的速度十分快。

四、斐波那契查找(黄金分割法)
基本介绍:
(1)黄金分割点是指把一条线段分割为两部分,使其中一部分与全长之比等于另一部分与这部分之比。取其前三位数字的近似值是0.618.由于按此比例设计的造型十分美丽,因此称为黄金分割,也称为中外比。这是一个神奇的数字,会带来意想不到的效果。
(2)斐波那契数列{1, 1,2, 3,5, 8,13, 21, 34, 55}发现斐波那契数列的两个相邻数的比例无限接近黄金分割值0.618

基本原理介绍:
斐波那契查找的原理与前两种相似,仅仅改变中间节点(mid)的位置,mid不再是中间或者插值得到,而是位于黄金分割点的附近,即mid = left + F(k-1)-1,如下图所示:
在这里插入图片描述
对F(k-1)-1的理解:
(1)由斐波那契数列F[k] = F[k-1] + F[k-2]的性质,可以得到F[k]-1 = F[k-1]-1 + F[k-2]-1 +1,该式说明,只要序列的长度为F[k]-1,则可以将该表分成长度为F[k-1]-1和F[k-2]-1的两段,从而中间值
mid = left + F(k-1)-1
(2)类似的,每一子段也可以用相同的方式分割
(3)但顺序表长度n不一定刚好等于F[k]-1,所以需要将原来的顺序表长度n增加至F[k]-1。这里的k值只要能使F[k]-1恰好大于或等于n即可。

代码如下:

public class FibonacciSearch {
    public static int maxSize = 20;
    public static void main(String[] args) {
        int[] arr = {1,8,13,45,69,78,123};
        int index = fibSearch(arr,69);
        System.out.println("index:" + index);
    }

    public static int[] fib(){
        int[] f = new int[maxSize];
        f[0] = 1;
        f[1] = 1;
        for (int i=2;i<f.length;i++){
            f[i] = f[i-1] + f[i-2];
        }
        return f;
    }

    public static int fibSearch(int[] arr,int key){
        int left = 0;
        int right = arr.length - 1;
        int[] f = fib();
        int k = 0;
        int mid = 0;
        while (right > f[k] - 1){
            k++;
        }
        int[] temp = Arrays.copyOf(arr,f[k]);
        for(int i=right+1;i<f[k];i++){
            temp[i] = arr[right];
        }

        while (left <= right){
            mid = left + f[k-1]-1;
            if (temp[mid] > key){
                right = mid -1;
                k--;
            }else if(temp[mid] < key){
                left = mid + 1;
                k -=2;
            }else{
                if (mid <= right){
                    return mid;
                }else{
                    return right;
                }
            }
        }
        return -1;
    }
}

结果如下:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值