Java data structure and algorithm (four common search algorithms, linear search, binary search, interpolation search, Fibonacci search)

linear search

Basic idea: compare one by one in order, find the value you want to find, then return its subscript or its value to the
code implementation:

 public static int  seqSearch(int[] arr ,int value) {
    
    
        //arr为目标数组,value为目标查找数据
        for(int i = 0;i < arr.length;i++) {
    
    
            if(arr[i] == value) {
    
    
                return i;
            }
        }
        return -1;
    }

binary search

A prerequisite for using binary search is that the given data sequence must be ordered

Analysis of binary search ideas:
1. First determine the subscript [int mid = (left + right)/2] in the middle of the data sequence.
2. Then compare the target value (value) with the middle value
. 3. If the target value (value ) is greater than the middle value (mid), then perform a recursive search on the right side of the middle value.
4. If the target value (value) is less than the middle value (mid), then perform a recursive search on the left side of the middle value.
5. If the target value ( value) is equal to the middle value (mid), then it means that the target value has been found, and returns the subscript
code as required to achieve:

   public static int binarySearch(int[] arr,int left,int right,int value) {
    
    
        //确定此次查找时的中间值是多少
        int mid = (left + right) /2;
        //如果左指针大于右指针那么就说明没有找到
        if(left > right) {
    
    
            return -1;
        }
        //如果要找的值比中间值小,那么就在左半边继续找
        if(value < arr[mid]) {
    
    
            return binarySearch(arr,left,mid-1,value);
        }
        //如果要找的值比中间值大,那么就在右半边继续找
        else if(value > arr[mid]) {
    
    
            return binarySearch(arr,mid+1,right,value);
        }
        //如果中间值就等于要找得值,那么就把目标值所在得下标返回
        else if(value == arr[mid]){
    
    
            return mid;
        }
        //如果走到了这一步那么就说明没有找到目标值
        return -1;
    }

Variant, if there are multiple values ​​that need to be searched in the sequence to be searched, how to implement
1, after finding the target value, scan to the left and right of the target value respectively, until the value is not equal to the target value and end Scan, store the scanned value equal to the subscript of the target value into the collection, and finally return the collection.

Code:

public static ArrayList<Integer> binarySearch(int[] arr, int left, int right, int value) {
    
    
        //确定此次查找时的中间值是多少
        int mid = (left + right) /2;
        //如果左指针大于右指针那么就说明没有找到,则返回一个空集合
        if(left > right) {
    
    
            return new ArrayList<>();
        }
        //如果要找的值比中间值小,那么就在左半边继续找
        if(value < arr[mid]) {
    
    
            return binarySearch(arr,left,mid-1,value);
        }
        //如果要找的值比中间值大,那么就在右半边继续找
        else if(value > arr[mid]) {
    
    
            return binarySearch(arr,mid+1,right,value);
        }
        //如果中间值就等于要找得值,那么就把目标值所在得下标返回
        else if(value == arr[mid]){
    
    
            int flag = mid;
            //创建一个集合
            ArrayList<Integer> arr1 = new ArrayList<Integer>();
            //往mid的左边进行扫描
            while(true) {
    
    
                if(flag < 0 || arr[flag] != value) {
    
    
                    break;
                }
                arr1.add(flag);
                flag--;
            }
            //因为上面已经扫描过mid所以现在mid不能再被扫描,否则会重复
            flag = mid+1;
            //往mid的右边进行扫描
            while(true) {
    
    
                if(flag > arr.length-1 || arr[flag] != value) {
    
    
                    break;
                }
                arr1.add(flag);
                flag++;
            }
            return arr1;
        }
        //如果走到了这一步那么就说明没有找到目标值,返回一个空集合
        return new ArrayList<>();
    }

interpolation lookup

Precautions for interpolation search:
(1) For a lookup table with a large amount of data and relatively uniform distribution of keywords
, interpolation search is used, which is faster (2) In the case of uneven distribution of keywords, this method is not necessarily faster than half Find better.
The basic idea of ​​interpolation search: the interpolation search algorithm is similar to binary search, the difference is that the interpolation search starts from the self-adaptive mid each time, and the mid index formula in the half search is used, low indicates the left index left, hight indicates the right index right, The key is the target value (value) formula we mentioned earlier
: int mid = low +(hight - low)*(key - arr[low])/(arr[hight] - arr[low])
insert image description here

Algorithm implementation:

 public static int insertValueSort(int[] arr,int left,int right,int value) {
    
    
        if(left > right || value > arr[right] || value < arr[left]) {
    
    
            return -1;
        }
        int mid = left + (right - left)*(value-arr[left])/(arr[right] - arr[left]);
        if(value < mid) {
    
    
            return insertValueSort(arr,left,mid-1,value);
        }
        else if(value > mid) {
    
    
            return insertValueSort(arr,mid + 1,right,value);
        }
        else {
    
    
            return mid;
        }
    }

Fibonacci search (golden section method)

Fibonacci (golden section method) principle:
The Fibonacci search principle is similar to the first two, only changing the position of the middle node (mid), and mid is no longer obtained by interpolation or interpolation, but is located at the golden section point Nearby,
that is, mid = low + F[k - 1] - 1 (F represents the Fibonacci sequence)

Understanding of F(k - 1) - 1:
insert image description here

(1): From the properties of the Fibonacci sequence F[k] = F[k-1] + F[k-2], we can get (F[k] - 1) = (F[k-1] - 1) + (F[k-2] - 1) + 1. This formula shows that as long as the length of the sequence table is F[k] - 1, the table can be divided into two sections with lengths of F[k-1] - 1 and F[k-2] - 1. That is, as shown in the above figure, the middle position is mid = low + F[k-1] - 1
(2): similarly, each subsection can be divided in the same way
(3): but the length of the sequence table is not necessarily n It is exactly equal to F[k] - 1, so it is necessary to increase the length of the original sequence table to F[k] - 1. The k value here only needs to make F[k] - 1 just greater than or equal to n. The following code It is obtained that after the length of the sequence table increases, the newly added position (from n+1 to F[k] - 1 position) can be assigned the value of n position

while(n > fib(k) - 1) {
    
    
	k++;
	}

Code:

 //用非递归的方式得到斐波那契数列
    public static int[] fi(int MaxSize) {
    
    
        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;
    }
    public static int fiSearch(int[] a,int key) {
    
    
        int low = 0;
        int high = a.length-1;
        int k = 0;//表示斐波那契分割数值的下标
        int mid = 0;//存放mid
        int[] f = fi(20);//表示斐波那契数列
        //获取到斐波那契分割数值的下标
        while(high > f[k]-1) {
    
    
            k++;
        }
        //因为f[k]值可能大于a的长度,因此我们需要使用Arrays类,一个新的数组,并指向a[]
        int[] temp = Arrays.copyOf(a,f[k]);
        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--;
            }else if(key > temp[mid]) {
    
    //我们应该继续向数组的后面查找(右边)
                low = mid + 1;
                k -= 2;
            }else {
    
    //需要确定返回的是哪个下标
                if(mid <= high) {
    
    
                    return mid;
                } else {
    
    
                    return high;
                }
            }
        }
        return -1;
    }

Guess you like

Origin blog.csdn.net/qq_48627750/article/details/121304159