搜索算法--Search Algorithm

    在java中,我们常用的查找有四种:   

                  1) 顺序(线性)查找  

                  2) 二分查找/折半查找  

                  3) 插值查找  

                  4) 斐波那契查找

一、线性查找

        在数组中进行查找,找到返回下标,找不到返回-1

   //线性查找
    public static int seq(int[] array, int data) {
        for (int i = 0; i < array.length; i++) {
            if (array[i] == data) {
                return i;
            }
        }
        return -1;
    }

 


二、二分查找【查找的数据必须是一个有序的数组】

        不断的将一个数组进行折半处理,判断中间值是否是要查找的数据。如果中间值比查找的值大,就往中间值的左边进行查找,如果中间值比查找的值小,就往中间值的右边进行查找

 代码实现:

    /**
     * @param array   在array数组中进行查找
     * @param start   开始下标
     * @param end     结束下标
     * @param findVal 查找的值
     * @return
     */
    public static int binarySearch(int[] array, int start, int end, int findVal) {
        if (start > end) {
            //递归结束条件
            return -1;
        }
        int mid = (start + end) / 2;
        int midVal = array[mid];
        if (findVal > midVal) {
            //右边递归
           return binarySearch(array, mid + 1, end, findVal);
        } else if (findVal < midVal) {
            //左边递归查找
            return  binarySearch(array, start, mid - 1, findVal);
        }
        return mid;
    }

当查找的值数组中有多个时,代码该怎么写:        

        思路:

                当找到相等的值时不要返回,继续向左递归如果还有相等的值就加到一个集合中

,继续向右递归如果有相等的值加到一个集合中,,最终返回一个集合

代码实现:

  /**
     * @param array   在array数组中进行查找
     * @param start   开始下标
     * @param end     结束下标
     * @param findVal 查找的值
     * @return
     */
    public static ArrayList<Integer> binarySearch(int[] array, int start, int end, int findVal) {
        if (start > end) {
            //结束条件
            throw new RuntimeException("没有找到");
        }
        int mid = (start + end) / 2;
        int midVal = array[mid];
        if (findVal > midVal) {
            //右边递归
            return binarySearch(array, mid + 1, end, findVal);
        } else if (findVal < midVal) {
            //左边递归查找
            return binarySearch(array, start, mid - 1, findVal);
        } else {
            //保存结果
            ArrayList<Integer> list = new ArrayList<>();
            //向左进行查找
            int temp = mid - 1;
            while (true) {
                //因为数组定是有序的,所以相等的值也是连续的
                if (temp < 0 || array[temp] != findVal) {
                    break;
                }
                list.add(temp);
                temp--;
            }
            //增加mid
            list.add(mid);
            //向右查找
            temp = mid + 1;
            while (true) {
                if (temp > end || array[temp] != findVal) {
                    break;
                }
                list.add(temp);
                temp++;
            }

            return list;
        }
    }

 三、插值查找

1、插值查找算法类似于二分查找,不同的是插值查找每次从自适应mid处开始查找。插值查找也需要一个有序的数组

2、将折半查找中的求mid 索引的公式 , low 表示左边索引left, high表示右边索引right. key 就是前面我们讲的  findVal, int mid = low + (high - low) * (key - arr[low]) / (arr[high] - arr[low])  ;/*插值索引*/

3、对应前面的代码公式: int mid = left + (right – left) * (findVal – arr[left]) / (arr[right] – arr[left])

4、通过上面的公式,mid直接定位到查找元素的位置上,只需要查找一次

  /*
        插值查找算法--也需要数组是有序的数组
     */
    public static int inertValSearch(int[] array ,int left ,int right ,int findVal){
        System.out.println("查找次数"); //1次
        //获取mid
        //!!!!!!直接定位到要超找元素的下标
        int mid =  left + (right - left) * (findVal - array[left]) / (array[right] - array[left]);
        //获取中间值
        int midVal = array[mid] ;

        //放置越界
        //当查找的比第一个数小,比最后一个大时,停止查询
        if(left>right || findVal < array[0] || findVal > array[array.length-1]){
            return -1;
        }

        if (findVal > midVal){
            //如果查找的值比中间值大,则右递归
            return inertValSearch(array,mid+1,right,findVal) ;
        }else if (findVal < midVal){
            //查找的值比中间值小,左递归
            return inertValSearch(array,left,mid,findVal);
        }else {
            return mid ;
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鲨瓜2号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值