Data structure and algorithm (search algorithm: linear, bisection, interpolation, Fibonacci)

Keywords: Algorithm data structure

Introduction to search algorithm

In java, there are four common Searches:

1. Sequential (linear) search

2. Binary search / half search

3. Interpolation search

4. Fibonacci search

Linear search

There is a sequence: {1,8,10,8910001234}. Judge whether the sequence contains this name [sequential search]

Requirement: if it is found, it will prompt that it is found, and give the subscript value

Code implementation:

package search;

/**
 * Linear search
 */
public class SeqSearch {
    public static void main(String[] args) {
        int arr[] = {1,9,11,-1,34,89};//Array without order
        int index = seqSearch(arr,11);
        if (index == -1){
            System.out.println("Can't find");
        }else {
            System.out.println("find,Subscript is="+index);
        }
    }

    /**
     * Here, we implement linear search to find a value that meets the conditions and return it
     * @param arr
     * @param value
     * @return
     */
    public static int seqSearch(int[] arr ,int value){
        //Linear search is to compare one by one. If the same value is found, the subscript is returned
        for (int i = 0; i < arr.length; i++){
            if (arr[i] == value){
                return i;
            }
        }
        return -1;
    }
}

Binary search algorithm

Binary search:

Please perform a binary search {1,8,10,8910001234} on an ordered array, enter a number to see if this number exists in the array, and find the subscript. If not, you will be prompted "there is no such number"

Thinking: {1,8,10,8910001234} when there are multiple identical values in an ordered array, how to find all the values, such as 1000 here

Train of thought analysis

  Code implementation:

Note: the subscript of finding all elements that meet the conditions is added:

package search;

import com.sun.source.tree.NewArrayTree;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;

/**
 * Binary search
 * Note: arrays must be ordered
 */
public class BinarySearch {

    public static void main(String[] args) {
        int arr[] = {1, 8, 10, 1000,1000,1000, 1234};

//        int resIndex = binarySearch(arr,0,arr.length - 1,1);
//        System.out.println("resIndex="+resIndex);
        List<Integer> restIndexList =binarySearch2(arr,0,arr.length-1,1000);
        System.out.println(restIndexList);
    }

    //Binary search algorithm
    /**
     * @param arr     array
     * @param left    Index on the left
     * @param right   Index on the right
     * @param findVal Value to find
     * @return If it is found, it returns the subscript. If it is not found, it returns - 1
     */
    public static int binarySearch(int[] arr, int left, int right, int findVal) {

        //When left > right, it means that the whole array is recursive, but it is not found
        if (left > right){
            return -1;
        }
        int mid = (left + right) / 2;
        int midVal = arr[mid];

        if (findVal > midVal) { //Recursive right
            return binarySearch(arr, mid + 1, right, findVal);
        } else if (findVal < midVal) {// Left recursion
            return binarySearch(arr, left, mid - 1, findVal);
        } else {
            return mid;
        }
    }

    //Complete thinking
    /*
    {1,8,10,89,1000,1000,1234}When in an ordered array,
    How to find all the values when there are multiple identical values, such as 1000

    Train of thought analysis
    1:Do not return the mid index value immediately after it is found
    2:Scan to the left of the mid index value, and add all element subscripts that meet 1000 to the set ArrayList
    3:Scan to the right of the mid index value, and add all element subscripts that meet 1000 to the set ArrayList
    4:Return ArrayList to
     */
    public static ArrayList binarySearch2(int[] arr, int left, int right, int findVal) {

        //When left > right, it means that the whole array is recursive, but it is not found
        if (left > right){
            return new ArrayList<Integer>();
        }
        int mid = (left + right) / 2;
        int midVal = arr[mid];

        if (findVal > midVal) { //Recursive right
            return binarySearch2(arr, mid + 1, right, findVal);
        } else if (findVal < midVal) {// Left recursion
            return binarySearch2(arr, left, mid - 1, findVal);
        } else {
            /*
             1:Do not return the mid index value immediately after it is found
             2:Scan to the left of the mid index value, and add all element subscripts that meet 1000 to the set ArrayList
             3:Scan to the right of the mid index value, and add all element subscripts that meet 1000 to the set ArrayList
             4:Return ArrayList to
             */
            ArrayList<Integer> resIndexList = new ArrayList<Integer>();
            int temp = mid - 1;
            while (true){
                if (temp < 0 || arr[temp] != findVal){ //sign out
                    break;
                }
                //Otherwise, it is temp and put into reindexlist
                resIndexList.add(temp);
                temp -=1;
            }
            resIndexList.add(mid);

            //Scan to the right of the mid index value, and add all element subscripts that meet 1000 to the set ArrayList
            temp = mid + 1;
            while (true){
                if (temp > arr.length-1 || arr[temp] != findVal){ //sign out
                    break;
                }
                //Otherwise, you can use temp and put it into reindexlist
                resIndexList.add(temp);
                temp +=1;
            }
            return  resIndexList;
        }
    }

}

Interpolation lookup

Introduction to interpolation search principle:

(1) The interpolation search algorithm is similar to binary search, except that the interpolation search starts from the adaptive mid every time

(2) The formula for finding mid index in half search. low represents the left index and high represents the right index

key is our findVal

(3)int midindex = low +(high - low) *(key - arr[low]) / (arr[high] -arr[low]; / * interpolation index*/

Corresponding to the previous code formula:

int mid = left + (right - left) * (findVal -arr [left]) / (arr[right] - arr[left])

(4) An example is given to illustrate the array of interpolation search algorithm 1-100

 

Interpolation search application case:

Please find an ordered array, find {1,8,10,8910001234}, enter a number to see if the number exists, and write out the subscript. If not, you will be prompted with "no such number"

Code implementation:

package search;

/**
 * Interpolation lookup
 */
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 =insertValueSearch(arr,0,arr.length-1,100);
        System.out.println("index="+index);
    }

    //Write interpolation search algorithm
    //Interpolation search algorithm also requires an orderly array
    /**
     *
     * @param arr array
     * @param left Left index
     * @param right Right index
     * @param findVal Find value
     * @return
     */
    public static int insertValueSearch(int[] arr, int left, int right, int findVal){

        //Note: findval < arr [0] and arr[arr.length-1] must be required
        //Otherwise, the mid we get may cross the border
        if (left > right || findVal < arr[0] || findVal >arr[arr.length-1]){
            return  -1;
        }
        //Find the mid, adaptive
        int mid = left + (right -left) *(findVal -arr[left]) / (arr[right] - arr[left]);
        int midVal =arr[mid];
        if(findVal > midVal) {// Description should recurse to the right
            return insertValueSearch(arr, mid + 1, right, findVal);
        }else if (findVal < midVal) {//Description should look recursively to the left
            return insertValueSearch(arr, mid - 1, right, findVal);
        }else {
            return mid;
        }

    }
}

Precautions for interpolation search:

(1) For the lookup table with large amount of data and uniform keyword distribution, interpolation is faster

(2) The keyword distribution is uneven, and this method is not necessarily better than half search

Fibonacci (golden section) search algorithm

Fibonacci (golden section) search basic introduction:

(1) : the golden section point refers to dividing a line segment into two parts, so that the ratio of one part to the whole length is equal to the ratio of the other part to this part. The approximate value of the first three digits is 0.618. Therefore, the shape designed according to this ratio is very beautiful, so it is called the golden section, also known as the middle to outer ratio. This is a magical number, which will bring unexpected effects

(2) Fibonacci sequence {1,1,2,3,4,5,13,21,34,55} it is found that the ratio of two adjacent numbers of Fibonacci sequence is infinitely close to the golden section value of 0.618

  Fibonacci principle:

The Fibonacci search principle is similar to the first two, only changing the position of the intermediate node (mid). The mid is not only obtained by intermediate or interpolation, but is located near the golden section point, that is, mid=low+F(k-1)-1 (F represents Fibonacci sequence), as shown in the figure below

  Understanding of F(k-1)-1:

(1) Due to the property of Fibonacci sequence F[k]=F[k-1]+F[k-2], it can be obtained that (F[k-1]) = (F[k-1]-1) + (F[k-2]-1)+1

The formula shows that as long as the length bit F[k]-1 of the sequence table, the table can be divided into two segments of growth bit F[k-1]-1 and F[k-2]-1,

That is, as shown in the above figure, from the middle position bit mid=low+F(k-1)-1

(2) Similarly, each sub segment can be divided in the same way

(3) However, the length n of the sequence table is not necessarily equal to F[k-1], so it is necessary to increase the length n of the original sequence table to F[k]-1. The value of K here can be obtained from the following code as long as F[k-]1 is exactly equal to or greater than N. after the length of the sequence table increases, the new position (from n+1 to F[k]-1 position) can be assigned as the value of N position

 

Fibonacci find application case:

Please perform Fibonacci search {1,8,10,8910001234} on an ordered array, enter a number to see if the array exists at this time, and find the subscript. If not, you will be prompted "there is no such number"

Code implementation:

package search;

import java.util.Arrays;

/**
 * fibonacci search 
 * Note: ordered array
 */
public class FibonacciSearch {

    public static int maxSize = 20;
    public static void main(String[] args) {
        int [] arr ={1,8,10,89,1000,1234};

        System.out.println("index="+fibSearch(arr,1234));
    }
    //Since we need to use Fibonacci sequence for mid = low+f(k-1)-1, we need to obtain a Fibonacci sequence first
    //A Fibonacci sequence is obtained in a non recursive way
    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;
    }

    //Write Fibonacci search algorithm
    //Write the algorithm in a non recursive way
    /**
     *
     * @param a array
     * @param key Key (value) we need to find
     * @return Returns the subscript for, if not - 1
     */
    public static int fibSearch(int[]a,int key){
        int low = 0;
        int high = a.length-1;
        int k = 0; //Subscript representing the Fibonacci division value
        int mid = 0; //Store mid value
        int f[] =fib(); //Get Fibonacci sequence

        //Get the subscript of Fibonacci division value
        while (high > f[k] -1){
            k++;
        }

        //Because the f[k] value may be greater than the length of a, we need to use the Arrays class to construct a new array and point to temp []
        //The insufficient part is filled with 0
        int [] temp = Arrays.copyOf(a,f[k]);
        //In fact, you need to fill temp with the last number of the a array
        //give an example:
        //temp ={1,8,10,89,1000,1234,0,0,0} =>{1,8,10,89,1000,1234,1234,1234,1234}
        for (int i = high + 1; i <temp.length; i++){
            temp[i] = a[high];
        }

        //Use while to cycle and find our number key
        while(low <= high){ //As long as this condition is met, you can find it
            mid = low + f[k-1]-1;
            if (key < temp[mid]){ //We should continue to look in front of the array (left)
                high = mid -1;
                /*
                Why k--
                explain:
                1.All elements = front elements + rear elements
                2.f[k] = f[k-1] + f[k-2]
                Because there are f[k-1] elements in front, you can continue to split f[k-1] = f[k-1] + f[k-3]
                That is, continue to find K in front of f[k-1]
                That is, the next cycle mid=f[k-1-1]-1
                 */
                k--;
            }else if (key > temp[mid]){ //We should continue to look behind the array (to the right)
                low = mid + 1;
                /*
                Why k -=2
                explain
                1.All elements = front elements + rear elements
                2.f[k] = f[k-1] + f[k-2]
                3.Because there are f[k-2] in the back, you can continue to split f[k-1] = f[k-3] + f[k -4]
                4.That is, find k -=2 in front of f[k-2]
                5.That is, the next cycle mid = f[k-1-2]-1
                 */
                k -=2;
            }else { //find
                //You need to make sure that the subscript is returned
                if (mid <=high){
                    return mid;
                }else {
                    return high;
                }
            }
        }
        return -1;
    }
}

Posted by wsh on Fri, 19 Nov 2021 10:44:54 -0800