Java implements binary search, interpolation search (traversal search, recursive search)

1 Introduction

Binary search is also called binary search (Binary Search), which is a more efficient search method. However, the binary search requires that the linear table must adopt a sequential storage structure, and the elements in the table are arranged in order according to the key.

2. Thinking analysis

  • Set a variable mid pointing to the subscript of the middle element, mid=(left + right)/2
    • If left, right is a very large number then it may overflow
    • 所以(left+right)/2 = left - left/2 + right/2 = left+(right-left)/2
    • Compare the element to be found with the element of the mid subscript of the array
    • If the searched element is greater than arr[mid], left becomes the subscript of an element after mid
    • If the searched element is smaller than arr[mid], right becomes the subscript of the element before mid
    • If the element to be found is equal to arr[mid], mid is the position where the element is to be found
  • When left > rigth, the element is not in the array

3. Diagram

3.1 Calculate the position of mid and compare it with the searched number

insert image description here

3.2 After comparison, move mid

insert image description here
Because num>arr[mid], then it is necessary to search from the back of mid
insert image description here
and find it directly

3.3 What if the number we are looking for is a number that does not exist?

insert image description here

num<arr[mid], mid searches to the left

insert image description here
Continue to search left
insert image description here
At this time right = mid - 1, because mid is 0 so right = -1, left > right, then the loop is over

4. Code Analysis

4.1 Use traversal to solve binary search

package com.sky.find;

/**
 * 二分查找非递归版
 * @author 尹稳健~
 * @version 1.0
 * @time 2022/9/23
 */
public class BinarySearch {
    
    
    public static void main(String[] args) {
    
    
        //进行二分查找的数组必须是有序
        int[] arr = {
    
    -1, 0, 2, 11, 30};
        int result = binarySearch(arr, 11);
        if(result == -1) {
    
    
            System.out.println("未找到该元素");
        }else {
    
    
            System.out.println("该元素的下标是:" + result);
        }
    }

    /**
     * 设置一个指向中间元素下标的变量mid,mid=(left + right)/2
     * 让要查找的元素和数组mid下标的元素进行比较
     * 如果查找的元素大于arr[mid],则left变为mid后面一个元素的下标
     * 如果查找的元素小于arr[mid],则right变为mid前一个元素的下标
     * 如果查找的元素等于arr[mid],则mid就是要查找元素所在的位置
     * 当left > rigth时,说明元素不在该数组中
     * @param arr
     * @param num
     * @return
     */
    public static int binarySearch(int[] arr,int num){
    
    
        int left = 0;
        int right = arr.length - 1;
        while (left<=right){
    
    
            /**
             * 这里为什么需要 int mid = left+(right-left)/2;?
             * 原因是如果left 、right 是一个非常大的数那么就可能溢出,所以
             * (left+right)/2 = left - left/2 + right/2 = left+(right-left)/2
             */
            int mid = left+(right-left)/2;
            // 如果寻找的数大于mid那么就从mid的后面开始寻找
            if (arr[mid] < num){
    
    
                left = mid+1;
                // 如果寻找的数小于mid那么就从mid的前面开始寻找
            }else if (arr[mid] > num){
    
    
                right = mid -1;
            }else{
    
    
                return mid;
            }

        }
        return -1;
    }
}

4.2 Using recursion to solve binary search

package com.sky.find;

/**
 * 使用递归实现二分查找
 * @author 尹稳健~
 * @version 1.0
 * @time 2022/9/23
 */
public class BinarySearch2 {
    
    
    public static void main(String[] args) {
    
    
        //进行二分查找的数组必须是有序
        int[] arr = {
    
    -1, 0, 2, 11, 30};
        int left = 0;
        int right = arr.length - 1;
        int result = binarySearch(arr, left,right,11);
        if(result == -1) {
    
    
            System.out.println("未找到该元素");
        }else {
    
    
            System.out.println("该元素的下标是:" + result);
        }
    }

    public static int binarySearch(int[] arr , int left ,int right,int num){
    
    
        int mid = left+(right-left)/2;
        while (left<=right){
    
    
            if (arr[mid] < num){
    
    
                return binarySearch(arr,mid + 1,right,num);
            }else if (arr[mid] > num){
    
    
                return binarySearch(arr,left,mid - 1,num);
            }else{
    
    
                return mid;
            }
        }
        return -1;
    }
}

5. think

It suddenly occurred to me that if there are multiple identical values ​​in a number, this method can only find one position, so we need to optimize based on this code.

5.1 Thought analysis

It is possible to find more than one element. At this time, it is necessary not to return immediately after finding an element, but to scan the left and right elements, save all the subscripts of the same element into an array, and then return together

5.2 Code implementation

import java.util.ArrayList;
import java.util.List;

/**
 * 二分查找非递归版
 * @author 尹稳健~
 * @version 1.0
 * @time 2022/9/23
 */
public class BinarySearch3 {
    public static void main(String[] args) {
        //进行二分查找的数组必须是有序
        int[] arr = {-1, 0, 11, 11, 11, 11, 30};
        List<Integer> result = binarySearch(arr, 11);
        if(result.size() ==0) {
            System.out.println("未找到该元素");
        }else {
            System.out.println("该元素的下标是:" + result);
        }
    }

    /**
     * 设置一个指向中间元素下标的变量mid,mid=(left + right)/2
     * 让要查找的元素和数组mid下标的元素进行比较
     * 如果查找的元素大于arr[mid],则left变为mid后面一个元素的下标
     * 如果查找的元素小于arr[mid],则right变为mid前一个元素的下标
     * 如果查找的元素等于arr[mid],则mid就是要查找元素所在的位置
     * 当left > rigth时,说明元素不在该数组中
     * @param arr
     * @param num
     * @return
     */
    public static List<Integer> binarySearch(int[] arr, int num){
        List<Integer> result = new ArrayList<>();
        int left = 0;
        int right = arr.length - 1;
        while (left<=right){
            /**
             * 这里为什么需要 int mid = left+(right-left)/2;?
             * 原因是如果left 、right 是一个非常大的数那么就可能溢出,所以
             * (left+right)/2 = left - left/2 + right/2 = left+(right-left)/2
             */
            int mid = left+(right-left)/2;
            // 如果寻找的数大于mid那么就从mid的后面开始寻找
            if (arr[mid] < num){
                left = mid+1;
                // 如果寻找的数小于mid那么就从mid的前面开始寻找
            }else if (arr[mid] > num){
                right = mid -1;
                // 如果找到了,不要立刻返回查找左右两边是否还有相同的元素
            }else{
                result.add(mid);
                int leftIndex = mid - 1;
                while (leftIndex > 0 && arr[leftIndex] == num){
                    result.add(leftIndex);
                    leftIndex--;
                }
                int rightIndex = mid +1;
                while (rightIndex < right && arr[rightIndex] == num){
                    result.add(rightIndex);
                    rightIndex++;
                }
                return result;
            }

        }
        return result;
    }
}

6. Interpolation lookup

6.1 Introduction

Interpolation search, a search method for ordered tables. Interpolation search is a search method based on the comparison between the search key and the maximum and minimum record keys in the lookup table. Interpolation search is based on binary search, which improves the selection of search points to adaptive selection and improves search efficiency.

6.2 Algorithm formula

// 插值查找算法: 
int mid = left + (right – left) * (findVal – arr[left]) / (arr[right] – arr[left])

6.3 Code implementation

package com.sky.find;

import java.util.ArrayList;
import java.util.List;

/**
 * 插值查找
 * @author 尹稳健~
 * @version 1.0
 * @time 2022/9/23
 */
public class BinarySearch4 {
    
    
    public static void main(String[] args) {
    
    
        //进行二分查找的数组必须是有序
        int[] arr = {
    
    -1, 0, 11, 11, 11, 11, 30};
        List<Integer> result = binarySearch(arr, 11);
        if(result.size() ==0) {
    
    
            System.out.println("未找到该元素");
        }else {
    
    
            System.out.println("该元素的下标是:" + result);
        }
    }

    /**
     * 设置一个指向中间元素下标的变量mid,
     * int mid = left + (right – left) * (findVal – arr[left]) / (arr[right] – arr[left])
     * 让要查找的元素和数组mid下标的元素进行比较
     * 如果查找的元素大于arr[mid],则left变为mid后面一个元素的下标
     * 如果查找的元素小于arr[mid],则right变为mid前一个元素的下标
     * 如果查找的元素等于arr[mid],则mid就是要查找元素所在的位置
     * 当left > rigth时,说明元素不在该数组中
     * @param arr
     * @param num
     * @return
     */
    public static List<Integer> binarySearch(int[] arr, int num){
    
    
        List<Integer> result = new ArrayList<>();
        int left = 0;
        int right = arr.length - 1;
        while (left<=right){
    
    
            int mid = left + (right - left) * (num - arr[left]) / (arr[right]- arr[left]);
            // 如果寻找的数大于mid那么就从mid的后面开始寻找
            if (arr[mid] < num){
    
    
                left = mid+1;
                // 如果寻找的数小于mid那么就从mid的前面开始寻找
            }else if (arr[mid] > num){
    
    
                right = mid -1;
                // 如果找到了,不要立刻返回查找左右两边是否还有相同的元素
            }else{
    
    
                result.add(mid);
                int leftIndex = mid - 1;
                while (leftIndex > 0 && arr[leftIndex] == num){
    
    
                    result.add(leftIndex);
                    leftIndex--;
                }
                int rightIndex = mid +1;
                while (rightIndex < right && arr[rightIndex] == num){
    
    
                    result.add(rightIndex);
                    rightIndex++;
                }
                return result;
            }

        }
        return result;
    }
}



7. Summary

Interpolation search is optimized in binary search, just remember the formula

Guess you like

Origin blog.csdn.net/weixin_46073538/article/details/127005260