chenlun127

一 总叙

相比排序,查找简单很多。

常用的查找算法有四种,分别是

  1)顺序(线性)查找    //也就是一个一个找过去

  2)二分查找/折半查找   //前提必须是有序数组,每次都从待查数组的中间找起

  3)插值查找    //与二分查找类似,前提同样得是有序数组,mid值更改

  4)斐波那契(黄金分割法)查找算法    //与二分法类似,前提得是有序数组,mid值选择黄金分割点

二 顺序查找

  就是通过遍历数组,逐个得与数值相比较,当相同时返回下标,若没有找到则返回-1.

  代码如下

  

public class Sequential_Search {
        public static void main(String[] args) {
                int[] arr = {15,4,3,2,8,1,6,74,8,1,20,4};
                System.out.println(Arrays.toString(arr));
                int j = Sequential_Search.SequentialSearch(arr,1);
                if(j ==-1){
                        System.out.println("没有找到该数值");
                }else{
                        System.out.println("找到该数值,在数组中的索引位置为"+j);
                }
        }
        public static int SequentialSearch(int[] arr,int value){
                for (int i = 0; i < arr.length; i++) {
                        if(arr[i]==value){
                                return i;
                        }
                }
                return -1;
        }
}

 

 

 

 三 二分查找

  mid = (left+right)/2  ,初始时left=0,right=arr.length-1,将待比较的数值与数组中间的数值相比较,并以此来判断区间在左边还是右边。循环往复。

//二分查找 前提是有序数组
public class Binary_Search {
        public static void main(String[] args) {
                int[] arr = {1,2,3,4,6,7,8,9,10,10,10,10,10,101,1011,12,13};
                List<Integer> integers = Binary_Search.binartSearch(arr, 10, arr.length - 1, 0);
                for (Integer integer : integers) {
                        System.out.print(integer);
                        System.out.print(" ");
                }
                /*int j = Binary_Search.binartSearch(arr,10,arr.length-1,0);
                if(j==-1){
                        System.out.println("没有这个数");
                }
                else{
                        System.out.println("这个数字的下标为"+j);
                }*/
                
        }
/*        public static int binartSearch(int[] arr,int value,int right,int left){
                if(left>right){
                        return -1;
                }
                int mid = (right+left)/2;
                int midValue = arr[mid];
                if(value>midValue){
                        return binartSearch(arr,value,right,mid+1);
                }else if(value<midValue){
                        return binartSearch(arr,value,mid-1,left);
                }
                return mid;
        }*/
        //将有序数组中所有满足条件的数值下标全都取出来
        public static List<Integer> binartSearch(int[] arr, int value, int right, int left){
                if(left>right){
                        return new ArrayList<Integer>();
                }
                int mid = (right+left)/2;
                int midValue = arr[mid];
                if(value>midValue){
                        return binartSearch(arr,value,right,mid+1);
                }
                else if(value<midValue){
                        return binartSearch(arr,value,mid-1,left);
                }
                else{
                        List<Integer> list = new ArrayList<Integer>();
                        list.add(mid);
                        int temp = mid-1;
                        while(temp>=0&&arr[temp]==value){
                                list.add(temp);
                                temp-=1;
                        }
                        temp=mid+1;
                        while(temp<=arr.length&&arr[temp]==value){
                                list.add(temp);
                                temp+=1;
                        }
                        return list;
                }
        }
        }

四 插值查找

  与二分查找类似,不过不是取得中间值进行比较,而是通过公式 mid = left+(right-left)*(value-arr[left])/(arr[right]-arr[left])来获取中间值。

public class Interpolation_Method {
        public static void main(String[] args) {
                int[] arr =new int[100];
                for (int i = 0; i < 100; i++) {
                        arr[i]=i;
                }
                int j = Interpolation_Method.insertSort(arr,99,0,arr.length-1);
                if(j==-1){
                        System.out.println("未找到该数值");
                }
                else{
                        System.out.println("该数值在数组中的位置是"+j);
                }
        }
        public static int insertSort(int[] arr,int value,int left,int right){
               if(left>right || value>arr[arr.length-1] || value<arr[0]){
                       return -1;
               }
               int mid = left+(right-left)*(value-arr[left])/(arr[right]-arr[left]);
               int midValue = arr[mid];
                if (value>midValue){
                        return insertSort(arr,value,mid+1,right);
                }
                if(value<midValue){
                        return insertSort(arr,value,left,mid-1);
                }
                else return mid;
        }
}

五 斐波那契(黄金分割法)查找算法

  这部分的代码来自 https://blog.csdn.net/interesting_code/article/details/104322118 

  同样是对二分法的改进,这次是通过比较有序数组中的特定点然后不断缩小寻找的范围。

package com.cl.Search_Slgorithm;

import java.util.Arrays;

public class Fibonacci_Searches {
        
        public static int maxSize = 20;
        public static void main(String[] args) {
                int [] arr = {1,8, 10, 89,189,1000, 1234};
                
                System.out.println("index=" + fibSearch(arr, 189));// 0
                
        }
        
        //因为后面我们mid=low+F(k-1)-1,需要使用到斐波那契数列,因此我们需要先获取到一个斐波那契数列
        //非递归方法得到一个斐波那契数列
        public static int[] fib() {
                int[] f = new int[maxSize];
                f[0] = 1;
                f[1] = 1;
                for (int i = 2; i < maxSize; i++) {
                        f[i] = f[i - 1] + f[i - 2];
                }
                return f;
        }
        
        //编写斐波那契查找算法
        //使用非递归的方式编写算法
        /**
         *
         * @param a  数组
         * @param key 我们需要查找的关键码(值)
         * @return 返回对应的下标,如果没有-1
         */
        public static int fibSearch(int[] a, int key) {
                int low = 0;
                int high = a.length - 1;
                int k = 0; //表示斐波那契分割数值的下标
                int mid = 0; //存放mid值
                int f[] = fib(); //获取到斐波那契数列
                //获取到斐波那契分割数值的下标
                while(high > f[k] - 1) {
                        k++;
                }
                //因为 f[k] 值 可能大于 a 的 长度,因此我们需要使用Arrays类,构造一个新的数组,并指向temp[]
                //不足的部分会使用0填充
                int[] temp = Arrays.copyOf(a, f[k]);
                //实际上需求使用a数组最后的数填充 temp
                //举例:
                //temp = {1,8, 10, 89, 1000, 1234, 0, 0}  => {1,8, 10, 89, 1000, 1234, 1234, 1234,}
                for(int i = high + 1; i < temp.length; i++) {
                        temp[i] = a[high];
                }
                
                // 使用while来循环处理,找到我们的数 key
                while (low <= high) { // 只要这个条件满足,就可以找
                        mid = low + f[k - 1] - 1;
                        if(key < temp[mid]) { //我们应该继续向数组的前面查找(左边)
                                high = mid - 1;
                                //为甚是 k--
                                //说明
                                //1. 全部元素 = 前面的元素 + 后边元素
                                //2. f[k] = f[k-1] + f[k-2]
                                //因为 前面有 f[k-1]个元素,所以可以继续拆分 f[k-1] = f[k-2] + f[k-3]
                                //即 在 f[k-1] 的前面继续查找 k--
                                //即下次循环 mid = f[k-1-1]-1
                                k--;
                        } else if ( key > temp[mid]) { // 我们应该继续向数组的后面查找(右边)
                                low = mid + 1;
                                //为什么是k -=2
                                //说明
                                //1. 全部元素 = 前面的元素 + 后边元素
                                //2. f[k] = f[k-1] + f[k-2]
                                //3. 因为后面我们有f[k-2] 所以可以继续拆分 f[k-1] = f[k-3] + f[k-4]
                                //4. 即在f[k-2] 的前面进行查找 k -=2
                                //5. 即下次循环 mid = f[k - 1 - 2] - 1
                                k -= 2;
                        } else { //找到
                                //需要确定,返回的是哪个下标
                                if(mid <= high) {
                                        return mid;
                                } else {
                                        return high;
                                }
                        }
                }
                return -1;
        }
}

 

分类:

技术点:

相关文章:

  • 2022-02-07
  • 2022-02-07
  • 2022-02-07
  • 2022-01-30
  • 2021-05-18
  • 2022-12-23
  • 2021-12-27
  • 2022-02-07
猜你喜欢
  • 2022-02-07
  • 2021-09-18
  • 2022-02-07
  • 2022-02-07
  • 2021-10-10
  • 2021-10-26
  • 2022-02-07
相关资源
相似解决方案