1. 程式人生 > 其它 >二分法查詢的實現與總結(Java)

二分法查詢的實現與總結(Java)

技術標籤:資料結構與演算法演算法二分法

二分法查詢

基本介紹

演算法:二分法查詢適用於資料量較大時,但是資料需要先排好順序。

主要思想是:(設查詢的陣列區間為array[low, high])

  • 確定該區間的中間位置K
  • 將查詢的值T與array[k]比較。若相等,查詢成功返回此位置;否則確定新的查詢區域,繼續二分查詢。區域確定如下:a.array[k]>T 由陣列的有序性可知array[k,k+1,……,high]>T;故新的區間為array[low,……,K-1]b.array[k]<T 類似上面查詢區間為array[k+1,……,high]。

時間複雜度為: O(log2

n)。

程式碼實現

非遞迴查詢單個值

/**
     * 非遞迴的二分法查詢
     *
     * @param arr    待查詢的陣列,此處陣列預設按照從小到大排列
     * @param target 待查詢的值
     * @return 返回待查詢值的下標,若未找到返回-1
     */
    public static int binarySearchNoRecursion(int[] arr, int target) {
        int left = 0;//左角標
        int right = arr.length - 1;//右角標
        int
mid;//中間值 while (left <= right) { mid = (left + right) / 2; if (target < arr[mid]) { right = mid - 1; } else if (target > arr[mid]) { left = mid + 1; } else { return mid; } }
return -1; }

非遞迴查詢所有符合條件的值

/**
     * @param arr    待查詢的陣列,此處陣列預設按照從小到大排列
     * @param target 待查詢的值
     * @return 返回待查詢值的集合,若未找到返回null
     */
    public static List<Integer> binarySearchAllNoRecursion(int[] arr, int target) {
        int left = 0;//左角標
        int right = arr.length - 1;//右角標
        int mid;
        while (left <= right) {
            mid = (left + right) / 2;
            if (target < arr[mid]) {
                right = mid - 1;
            } else if (target > arr[mid]) {
                left = mid + 1;
            } else {
                List<Integer> list = new ArrayList<>();
                list.add(mid);
                int temp;//使用臨時變數記錄當前座標
                //向左查詢
                temp = mid - 1;
                while (temp >= 0 && arr[temp] == target) {
                    list.add(temp--);
                }
                //向右查詢
                temp = mid + 1;
                while (temp < arr.length && arr[temp] == target) {
                    list.add(temp++);
                }
                return list;
            }
        }
        return null;
    }

遞迴查詢單個值

/**
     * 遞迴的二分法查詢
     *
     * @param arr    待查詢的陣列,此處陣列預設按照從小到大排列
     * @param left   左角標
     * @param right  右角標
     * @param target 待查詢的值
     * @return 返回待查詢值的下標,若未找到返回-1
     */
    public static int binarySearchByRecursion(int[] arr, int left, int right, int target) {
        if (left > right) {
            return -1;
        }
        int mid = (left + right) / 2;
        if (target < arr[mid]) {
            return binarySearchByRecursion(arr, left, mid - 1, target);
        } else if (target > arr[mid]) {
            return binarySearchByRecursion(arr, mid + 1, right, target);
        } else {
            return mid;
        }
    }

遞迴查詢所有符合條件的值

/**
     * @param arr    待查詢的陣列,此處陣列預設按照從小到大排列
     * @param left   左角標
     * @param right  右角標
     * @param target 待查詢的值
     * @return 返回待查詢值的集合,若未找到返回null
     */
    public static List<Integer> binarySearchAllByRecursion(int[] arr, int left, int right, int target) {
        if (left > right) {
            return null;
        }
        int mid = (left + right) / 2;
        if (target < arr[mid]) {
            return binarySearchAllByRecursion(arr, left, mid - 1, target);
        } else if (target > arr[mid]) {
            return binarySearchAllByRecursion(arr, mid + 1, right, target);
        } else {
            List<Integer> list = new ArrayList<>();
            list.add(mid);
            int temp;//臨界變數記錄mid值
            //向左判斷
            temp = mid - 1;
            while (temp >= 0 && target == arr[temp]) {
                list.add(temp--);
            }
            //向右判斷
            temp = mid + 1;
            while (temp < arr.length && target == arr[temp]) {
                list.add(temp++);
            }
            return list;
        }
    }

程式碼彙總

package com.athome.binarysearch;

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

/**
 * Description:
 * Author:江洋大盜
 * Date:2021/1/17 9:11
 */
public class BinarySearch {
    public static void main(String[] args) {
        int[] arr = {1, 5, 6, 9, 9, 9, 9, 10, 24, 39, 42};
        System.out.println("非遞迴查詢10:" + binarySearchNoRecursion(arr, 10));
        List<Integer> list = binarySearchAllNoRecursion(arr, 9);
        System.out.println("非遞迴查詢所有9:" + list);
        System.out.println("遞迴查詢10:" + binarySearchByRecursion(arr, 0, arr.length - 1, 10));
        List<Integer> list1 = binarySearchAllByRecursion(arr, 0, arr.length - 1, 9);
        System.out.println("遞迴查詢所有9:" + list1);


    }

    /**
     * 非遞迴的二分法查詢
     *
     * @param arr    待查詢的陣列,此處陣列預設按照從小到大排列
     * @param target 待查詢的值
     * @return 返回待查詢值的下標,若未找到返回-1
     */
    public static int binarySearchNoRecursion(int[] arr, int target) {
        int left = 0;//左角標
        int right = arr.length - 1;//右角標
        int mid;//中間值
        while (left <= right) {
            mid = (left + right) / 2;
            if (target < arr[mid]) {
                right = mid - 1;
            } else if (target > arr[mid]) {
                left = mid + 1;
            } else {
                return mid;
            }
        }
        return -1;
    }

    /**
     * @param arr    待查詢的陣列,此處陣列預設按照從小到大排列
     * @param target 待查詢的值
     * @return 返回待查詢值的集合,若未找到返回null
     */
    public static List<Integer> binarySearchAllNoRecursion(int[] arr, int target) {
        int left = 0;//左角標
        int right = arr.length - 1;//右角標
        int mid;
        while (left <= right) {
            mid = (left + right) / 2;
            if (target < arr[mid]) {
                right = mid - 1;
            } else if (target > arr[mid]) {
                left = mid + 1;
            } else {
                List<Integer> list = new ArrayList<>();
                list.add(mid);
                int temp;//使用臨時變數記錄當前座標
                //向左查詢
                temp = mid - 1;
                while (temp >= 0 && arr[temp] == target) {
                    list.add(temp--);
                }
                //向右查詢
                temp = mid + 1;
                while (temp < arr.length && arr[temp] == target) {
                    list.add(temp++);
                }
                return list;
            }
        }
        return null;
    }

    /**
     * 遞迴的二分法查詢
     *
     * @param arr    待查詢的陣列,此處陣列預設按照從小到大排列
     * @param left   左角標
     * @param right  右角標
     * @param target 待查詢的值
     * @return 返回待查詢值的下標,若未找到返回-1
     */
    public static int binarySearchByRecursion(int[] arr, int left, int right, int target) {
        if (left > right) {
            return -1;
        }
        int mid = (left + right) / 2;
        if (target < arr[mid]) {
            return binarySearchByRecursion(arr, left, mid - 1, target);
        } else if (target > arr[mid]) {
            return binarySearchByRecursion(arr, mid + 1, right, target);
        } else {
            return mid;
        }
    }

    /**
     * @param arr    待查詢的陣列,此處陣列預設按照從小到大排列
     * @param left   左角標
     * @param right  右角標
     * @param target 待查詢的值
     * @return 返回待查詢值的集合,若未找到返回null
     */
    public static List<Integer> binarySearchAllByRecursion(int[] arr, int left, int right, int target) {
        if (left > right) {
            return null;
        }
        int mid = (left + right) / 2;
        if (target < arr[mid]) {
            return binarySearchAllByRecursion(arr, left, mid - 1, target);
        } else if (target > arr[mid]) {
            return binarySearchAllByRecursion(arr, mid + 1, right, target);
        } else {
            List<Integer> list = new ArrayList<>();
            list.add(mid);
            int temp;//臨界變數記錄mid值
            //向左判斷
            temp = mid - 1;
            while (temp >= 0 && target == arr[temp]) {
                list.add(temp--);
            }
            //向右判斷
            temp = mid + 1;
            while (temp < arr.length && target == arr[temp]) {
                list.add(temp++);
            }
            return list;
        }
    }
}

測試結果
測試結果


結語

只要能收穫甜蜜,荊棘叢中也有蜜蜂忙碌的身影,未來的你一定會感謝現在努力的自己。