Java——查找算法

这篇博客详细介绍了Java中三种主要的查找算法:线性查找、二分查找和插值查找。通过实例代码展示了每种查找方法的递归和非递归实现,并探讨了它们的适用场景。线性查找适用于小规模或无序数据,而二分查找和插值查找则适合有序数据,其中插值查找在数据分布均匀时效率更高。
摘要由CSDN通过智能技术生成


在Java中常用的查找有四种:
(1)顺序(线性)查找
(2)二分查找(折半查找)
(3)插值查找
(4)斐波那契查找(黄金分割点查找)

一、线性查找:


public class SeqSearch {

    public static void main(String[] args) {
        int[] arr = {1,9,11,-1,43,89};
        int index = seqSearch(arr, 11);
        if (index==-1){
            System.out.println("没有找到!");
        }else{
            System.out.println("找到,下标为" + index);
        }

        int[] arr = {1,9,11,-1,43,89,11};
//        List<Integer> indexList = seqSearch2(arr, 11);
//        if (indexList.size() > 0){
//            System.out.println("符合条件的值的索引为:" + indexList);
//        }else{
//            System.out.println("没有符合条件的值!");
//        }

    /**
     * 查找到一个满足条件的值就返回
     * @param arr 待查找的数组
     * @param value 要查找的值
     * @return  返回元素在数组中的下标
     */
    public static int seqSearch(int[] arr, int value){
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == value){
                return i;
            }
        }
     return -1;
    }

/**
     * 找到数组中所有满足条件的数字下标,然后返回
     * @param arr
     * @param value
     * @return
     */
    public static List<Integer> seqSearch2(int[] arr, int value){
        //用于存储符合的值的索引
        ArrayList<Integer> list = new ArrayList<Integer>();

        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == value){
                list.add(i);
            }
        }
        return list;
    }
}

二、二分查找:

(1)递归实现:

/*
二分查找:前提,数组必须是有序的
 */

public class BinarySearch {

    public static void main(String[] args) {
        int[] arr = {1,9,11,-1,43,89};
        int index = binarySearch(arr, 0,5,11);
        if (index==-1){
            System.out.println("没有找到!");
        }else{
            System.out.println("找到,下标为" + index);
        }
    }

    /**
     * 递归实现二分查找
     * @param arr 待查找数组
     * @param left 左边索引
     * @param right 右边索引
     * @param findVal  需查找的值
     * @return 找到就返回索引,没找到就返回-1
     */
    public static int binarySearch(int[] arr,int left, int right, int findVal){

        if (left > right){
            return -1;
        }
        int mid = (left + right) / 2;//中间索引
        int midVal = arr[mid];

        if (midVal > findVal){//中间值大,需要向左递归
            return  binarySearch(arr,left,mid - 1, findVal);
        }else if (midVal < findVal){//中间值小,需要向右递归
            return  binarySearch(arr,mid + 1,right,findVal);
        }else {
            return mid;
        }
    }
}

 /**
     * 返回数组中所有符合条件的值得索引
     * @param arr
     * @param left
     * @param right
     * @param findVal
     * @return
     */
    public static List binarySearch2(int[] arr, int left, int right, int findVal){

        if (left > right){
            return new ArrayList();
        }
        int mid = (left + right) / 2;//中间索引
        int midVal = arr[mid];

        if (midVal > findVal){//中间值大,需要向左递归
            return  binarySearch2(arr,left,mid - 1, findVal);
        }else if (midVal < findVal){//中间值小,需要向右递归
            return  binarySearch2(arr,mid + 1,right,findVal);
        }else {

            ArrayList<Integer> list = new ArrayList<>();

            int temp = mid - 1;//向左查找重复的
            while (true){
                if (temp < 0 || arr[temp] != findVal){
                    break;
                }
                list.add(temp);
                temp--;
            }

            list.add(mid); //添加当前的

            temp = mid + 1; //向右查找重复的
            while (true){
                if (temp > arr.length || arr[temp] != findVal){
                    break;
                }
                list.add(temp);
                temp++;
            }
            return list;
        }
    }
  /**
     * 返回数组中所有符合条件的值得索引,方法2 的另一种实现
     * @param arr
     * @param left
     * @param right
     * @param findVal
     * @return
     */
    public static List binarySearch3(int[] arr, int left, int right, int findVal){

        if (left > right){
            return new ArrayList();
        }
        int mid = (left + right) / 2;//中间索引
        int midVal = arr[mid];

        if (midVal > findVal){//中间值大,需要向左递归
            return  binarySearch3(arr,left,mid - 1, findVal);
        }else if (midVal < findVal){//中间值小,需要向右递归
            return  binarySearch3(arr,mid + 1,right,findVal);
        }else {

            ArrayList<Integer> list = new ArrayList<>();

            for (int i = mid - 1; i >= 0 ; i--) {//向左找
                if (arr[i] == findVal){
                    list.add(i);
                }else{
                    break;
                }
            }

            list.add(mid);

            for (int j = mid + 1; j < arr.length; j++) {
                if (arr[j] == findVal){
                    list.add(j);
                }else{
                    break;
                }
            }
            return list;
        }
    }

(2)非递归实现:

   //非递归实现二分查找
    public static int binarySearchNoRecur(int[] arr, int findVal){
        int left = 0;
        int right = arr.length-1;

        while (left <= right){
            int mid = (left + right) / 2;
            if (arr[mid] == findVal){
                return mid;
            } else if (arr[mid] < findVal){ //向右找,改变的是left
                left = mid +1;
            }else {
                right = mid-1;
            }
        }
        return -1;
    }

三、插值查找:

重要的是中间索引的优化:int mid = left + (right - left)*(findVal - arr[left]) / (arr[right] - arr[left]);
注意:(1)对于数据量较大,关键字分布比较均匀的查找表来说,采用差值查找,速度较快(2)关键字分布不均匀的情况下,该方法不一定比折半查找要好。

package search;

/**
 * 插值查找
 */
public class InsertValueSearch {
    public static void main(String[] args) {

        int[] arr = new int [100];
        for (int i = 0; i < 100; i++) {
            arr[i] = i + 1;
        }

        int index = insertValueSreach(arr, 0, 99, 50);
        if (index==-1){
            System.out.println("没有找到!");
        }else{
            System.out.println("找到,下标为" + index);
        }
    }


    public static int insertValueSreach(int[] arr, int left, int right, int findVal){

        if (left > right || findVal < arr[0] || findVal > arr[arr.length-1]){
            //这个条件必须有,为了防止数组越界
            return -1;
        }
        //自适应 mid
        int mid = left + (right - left)*(findVal - arr[left]) / (arr[right] - arr[left]);//中间索引
        int midVal = arr[mid];

        if (midVal > findVal){//中间值大,需要向左递归
            return  insertValueSreach(arr,left,mid - 1, findVal);
        }else if (midVal < findVal){//中间值小,需要向右递归
            return  insertValueSreach(arr,mid + 1,right,findVal);
        }else {
            return mid;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值