1. 程式人生 > >Java常見演算法之二分法查詢演算法詳解

Java常見演算法之二分法查詢演算法詳解

一、簡介

二分法查詢,是在已經排好序的序列中,定義一個起始位置start(即序列第一個元素)和一個終止位置end(即序列最後一個元素),通過mid=(start+end)/2計算出中間位置,通過待查詢元素與mid中間位置的元素進行比較,如果待查詢元素比中間位置mid對應的值小,那麼將end = mid -1(即將end結束位置移動到mid中間左邊一個位置),如果比中間對應的值大,那麼將start = mid + 1 (即將start的位置移動到mid右邊一個位置),一直迴圈查詢,直到start > end,證明沒找到對應的元素,停止迴圈。

二、查詢思路

【a】待查詢有序陣列序列:1, 2, 3, 4, 5, 6, 7  

起始: 定義start = 0 , end = 6, mid = (start + end ) / 2 = (0 + 6) / 2 = 3,arr[mid] = arr[3] = 4

【b】假設需要查詢"2", 因為2 < arr[mid] = arr[3] = 4; 所以需要將end移動到mid左邊一個位置,即end = mid - 1 = 3 - 1 = 2,

此時重新計算mid = (start +end ) / 2 =  (0 + 2) / 2 = 1; arr[mid] = arr[1] = 2 ,繼續將2與arr[mid] = arr[1] = 2進行比較,發現相等,成功找到數字"2"所在的位置。

【c】假設需要查詢"7",因為 7 > arr[mid] = arr[3] = 4,所以需要將start移動到mid右邊一個位置,即start = mid + 1 = 4,此時重新計算mid = (start +end) / 2 = (4+ 6)/2 = 5, arr[mid] = arr[5] = 6, 因為7>arr[mid] = arr[5] = 6,所以還是需要將start移動到mid右邊一個位置,即start = mid + 1 = 5 + 1 = 6,  此時重新計算mid =  (start +end) / 2 = (6 + 6) / 2 = 6.arr[6] = 7, 此時arr[mid] = arr[6] = 7,剛好等於待查詢數字7,說明成功找到數字"7"所在的位置.

 【d】假設查詢"0", 因為 0 <  arr[mid] = arr[3] = 4, 所以需要將end移動到mid左邊一個位置,即end = mid - 1 = 3 - 1 = 2,此時重新計算mid = (start +end) / 2 = (0 + 2) / 2 = 1,arr[mid] = arr[1] = 2, 因為0 < arr[mid] = arr[1] = 2,所以需要將end移動到mid左邊一個位置,即end = mid - 1 = 1 - 1 =  0, 此時mid = (start +end) / 2 = (0 + 0) / 2 = 0,arr[mid] = arr[0] = 1,因為0 < arr[mid] = arr[0] = 1,所以需要將end移動到mid左邊一個位置,即end = mid - 1 = 0 - 1 = -1 ,因為此時start = 0, end = -1,start >end,即start 已經大於end結束位置,說明沒有找到相應的元素0。

三、演算法實現

public class BinarySearchUtils {

    /**
     * 根據指定值查詢在陣列中的位置
     *
     * @param arr   待查詢有序陣列
     * @param value 指定值
     * @return 返回值在陣列中對應的下標位置
     */
    public static int binarySearch(int[] arr, int value) {
        //起始位置
        int start = 0;
        //結束位置
        int end = arr.length - 1;

        while (true) {
            //計算中間位置下標
            int mid = (start + end) / 2;
            //中間值
            int midValue = arr[mid];

            if (value == midValue) {
                return mid;
            } else {
                //待查詢數值比中間值小,需要將end = mid - 1
                if (midValue > value) {
                    end = mid - 1;
                } else {
                    //待查詢數值比中間值大,需要將start = mid + 1
                    start = mid + 1;
                }
            }

            if (start > end) {
                //start > end,說明未找到相應的元素,返回-1
                return -1;
            }
        }
    }

}

測試:

public class TestBinarySearchUtils {

    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5, 6, 7};
        int index1 = BinarySearchUtils.binarySearch(arr, 2);
        System.out.println(index1);
        int index2 = BinarySearchUtils.binarySearch(arr, 7);
        System.out.println(index2);
        int index3 = BinarySearchUtils.binarySearch(arr, 0);
        System.out.println(index3);
    }

}

測試結果:

四、總結

本文是作者對二分查詢演算法的一些總結以及思路,僅供大家參考學習,一起學習一起進步。