Javaデータ構造とアルゴリズム-検索アルゴリズム-[day06]

検索アルゴリズム

線形探索分析と実装

番号シーケンス:{1、9、-1、34、89、11}があり、名前がシーケンスに含まれているかどうかを判断します[シーケンシャル検索]では、名前が見つかった場合、それを見つけて下付きの値を入力するよう求められます。

public class SeqSearch {
    
    
    public static void main(String[] args) {
    
    
        int arr[] = {
    
    1, 9, -1, 34, 89, 11};//无序数组
        int z = seqSearch(arr, 89);
        if (z == -1){
    
    
            System.out.println("没有找到");
        }else {
    
    
            System.out.println("找到值,下标为" + z);
        }


        int arz[] = {
    
    9,34,11};
        int[] ints = seqzSearch(arr, arz);
        for (int i = 0; i < ints.length; i++) {
    
    
            System.out.print("下标为" +"[" + ints[i] + "]");
        }
    }

    /**
     *  这里我们实现的线性查找是找到一个满足条件的值,就返回
     * @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;
    }

    public static int[] seqzSearch(int[] arr,int[] arz){
    
    
        int seqz[] = new int[arz.length];

        int index = 0;
        for (int i = 0; i < arr.length; i++) {
    
    
            for (int j = 0; j < arz.length; j++) {
    
    
                if (arr[i] == arz[j]){
    
    
                    seqz[index] = i;
                    index++;
                }
            }

        }
        return seqz;
    }

}


二分探索分析と実現

順序付けられた配列{1,8、10、89、1000、1234}でバイナリ検索を実行し、番号を入力してこの番号が配列に存在するかどうかを確認し、添え字を見つけてください。存在しない場合は、「そのような番号はありません」というプロンプトが表示されます。

バイナリ検索のアイデアの分析:

  1. まず、配列中央の添え字を決定しますmid =(左+右)/ 2

  2. 次に、
    findValをarr [mid]と比較して、検索する番号を見つけます2.1 findVal> arr [mid]。つまり、検索する番号がmidの右側にあるため、再帰的に右側を検索する必要があります。
    2.2 findVal <arr [mid]、つまり、検索する数値がmidの左側にあるため、左側に再帰的に検索する必要があります。
    2.3 findVal == arr [mid]見つかった場合は戻ります。

いつ再帰を終了する必要がありますか。

  • 見つかったら再帰を終了します。
  • 配列全体は再帰的ですが、findValはまだ見つからないため、左>右のときに再帰を終了する必要があります。

コード

//注意:使用二分查找的前提是 该数组是有序的。
public class BinarySearch {
    
    
    public static void main(String[] args) {
    
    
        int arr[] = {
    
    1, 8, 10, 88, 1000, 1234};

        int resIndex = binarySearch(arr, 0, arr.length, 88);
        System.out.println("resIndex=" + resIndex);


    }

    //二分查找算法

    /**
     *
     * @param arr   数组
     * @param left  查找时左边的索引
     * @param right 右边的索引
     * @param findVal   要查找的值
     * @return 如果找到就返回下标, 如果没有找到, 就返回-1
     */
    public static int binarySearch(int[] arr, int left, int right, int findVal) {
    
    

        //当left > right 时,说明递归整个数组,但是没有找到
        if (left > right){
    
    
            return -1;
        }
        int mid = (left + right) / 2;
        int midVal = arr[mid];

        if (findVal > midVal) {
    
     //向 右递归
            return binarySearch(arr, mid + 1, right, findVal);
        } else if (findVal < midVal) {
    
     //向 左递归
            return binarySearch(arr, left, mid - 1, findVal);
        }else {
    
    
            return mid;
        }
    }
}

アルゴリズムの最適化

//注意:使用二分查找的前提是 该数组是有序的。
public class BinarySearch {
    
    
    public static void main(String[] args) {
    
    
        int arr[] = {
    
    1, 8, 10, 88, 1000, 1000, 1000, 1000, 1234,1234,6666,6666};

        List<Integer> list = binarySearchz(arr, 0,arr.length - 1, 6666);
        System.out.println(list);


    }

    //二分查找算法

    /**
     *
     * @param arr   数组
     * @param left  查找时左边的索引
     * @param right 右边的索引
     * @param findVal   要查找的值
     * @return 如果找到就返回下标, 如果没有找到, 就返回-1
     */
    public static int binarySearch(int[] arr, int left, int right, int findVal) {
    
    

        //当left > right 时,说明递归整个数组,但是没有找到
        if (left > right){
    
    
            return -1;
        }
        int mid = (left + right) / 2;
        int midVal = arr[mid];

        if (findVal > midVal) {
    
     //向 右递归
            return binarySearch(arr, mid + 1, right, findVal);
        } else if (findVal < midVal) {
    
     //向 左递归
            return binarySearch(arr, left, mid - 1, findVal);
        } else {
    
    
            return mid;
        }
    }

    //思考题
    /*
    题:{1,8,10,89,1000,1000,1234}当一个有序数组中,有多个相同的数值时
    如何将所有的数值都查找到,比如这里的1000

    思路分析:
    1.在找到mid 索引值时,不要马上返回
    2.向mid 索引值得左边扫描,将所有满足 1000的元素下标,加入到集合ArrayList
    3.向mid 索引值的右边扫描,将所有满足 1000的元素下标,加入到集合ArrayList
    4.将ArrayList返回
     */

    public static List<Integer> binarySearchz(int[] arr, int left, int right, int findVal) {
    
    



        //当left > right 时,说明递归整个数组,但是没有找到
        if (left > right){
    
    
            return new ArrayList<Integer>();
        }
        int mid = (left + right) / 2;
        int midVal = arr[mid];

        if (findVal > midVal) {
    
     //向 右递归
            return   binarySearchz(arr, mid + 1, right, findVal);
        } else if (findVal < midVal) {
    
     //向 左递归
            return binarySearchz(arr, left, mid - 1, findVal);
        } else {
    
    

            /*思路分析:
            1.在找到mid 索引值时,不要马上返回
            2.向mid 索引值得左边扫描,将所有满足 1000的元素下标,加入到集合ArrayList
            3.向mid 索引值的右边扫描,将所有满足 1000的元素下标,加入到集合ArrayList
            4.将ArrayList返回*/
            List<Integer> resIndexlist = new ArrayList<Integer>();
            //2.向mid 索引值得左边扫描,将所有满足 1000的元素下标,加入到集合ArrayList
            int temp = mid - 1;
            while (true){
    
    
                if (temp < 0 || arr[temp] != findVal){
    
    //退出
                    break;
                }
                //否则,就把temp 放入到集合resIndexlist中
                resIndexlist.add(temp);
                temp -= 1;//temp左移
            }
            resIndexlist.add(mid);
            //3.向mid 索引值的右边扫描,将所有满足 1000的元素下标,加入到集合ArrayList
            temp = mid + 1;
            while (true){
    
    
                if (temp > arr.length -1 || arr[temp] != findVal){
    
    //退出
                    break;
                }
                //否则,就把temp 放入到集合resIndexlist中
                resIndexlist.add(temp);
                temp += 1;//temp左移

            }
        //    resIndexlist.add(mid);//别忘了把之前找到的放进去
            return resIndexlist;
        }
    }
}

補間検索の分析と実装

補間検索原理

  • 補間検索アルゴリズムはバイナリ検索に似ていますが、補間検索は毎回アダプティブミッドから開始される点が異なります。

  • ハーフサーチでミッドインデックスを検索する式、低は左のインデックス、左は高、右のインデックスは右、キー
    は先に説明したfindValです

ここに画像の説明を挿入

int mid =低+(高-低)*(キー-arr [低])/(arr [高]
-arr [低]); /挿入值索引/

前のコード式に対応:

int mid =左+(右–左)*(findVal – arr [左])/(arr [右]
– arr [左])


補間検索アルゴリズムを示します1-100

具体的なアイデア:

配列arr = [1、2、3、…、100]

  • 値を見つける必要がある場合1

  • バイナリサーチを使用して、私たちは見つけるために複数回再帰する必要があります1

  • 補間検索アルゴリズムを使用:int mid =左+(右–左)*(findVal – arr [左])/(arr [右] – arr [左])

  • int mid = 0 +(99-0)*(1-1)/(100-1)= 0 + 99 * 0/99 = 0

  • たとえば、探している値は100です。

  • int mid = 0 +(99-0)*(100-1)/(100-1)= 0 + 99 * 99/99 = 0

  • 99 = 99

要約すると、補間検索アルゴリズム->一連の数式計算

おすすめ

転載: blog.csdn.net/SwaeLeeUknow/article/details/108738029