1. 程式人生 > 其它 >資料結構和演算法-線性查詢-二分查詢

資料結構和演算法-線性查詢-二分查詢

一、二分查詢簡述

折半查詢(Binary Search)又稱為二分查詢,其要求資料序列呈線性結構,也就是經過排序的資料序列。對於沒有經過排序的資料序列,可以先進行排序操作,然後執行折半查詢操作。它是一種效率較高的查詢方法。但二分查詢有一定的條件限制:要求線性表必須採用順序儲存結構,且表中元素必須按關鍵字有序(升序或降序均可)。

二、二分查詢分析

折半查詢的基本思路是:

在有序表中,取中間的記錄作為比較物件

(1)如果要查詢的值等於中間索引對應的值,則查詢成功。

(2)若中間索引對應的值大於要查詢的值,則在中間索引的前半部分繼續查詢。

(3)若中間索引對應的值小於要查詢的值,則在中間索引的後半部分繼續查詢。

(4)不斷重述上述查詢過程,直到查詢成功,或有序表中沒有所要查詢的值,查詢失敗。

具體操作過程如下:

現在我們有一個有序的整型陣列listData,然後設定兩個變數,一個是low,指向陣列第1個索引的位置,即:low=0;另一個是high,指向陣列最後一個索引的位置,即:high=listData.length-1。

設要查詢的值為value。當low≤high時,反覆執行以下步驟:

(1)計算中間索引的位置mid,mid=(low+high)/2。

(2)將待查詢的值value和listData[middle]進行比較。

​ ① 若listData[middle] == value,查詢成功,middle所指元素即為要查詢的元素。

​ ② 若listData[middle] > value,說明若存在要查詢的值,該值一定在查詢有序陣列的前半部分。修改查詢範圍的上界:high=middle-1,轉(1)。

​ ③ 若listData[middle] < value,說明若存在要查詢的值,該值一定在查詢有序陣列的後半部分。修改查詢範圍的下界:low=middle+1,轉(1)。

重複以上過程,當low>high時,表示查詢失敗。

接下來我們用圖文的形式分下查詢的過程:

現在有一組有序的整型資料為{2, 12, 15, 23, 25, 28, 39, 40,46,66}

若要查詢value=39的記錄,則折半查詢過程如下。

(1)初始時

low=0;

high=9;

mid=(low+high)/2, middle=4;

listData[middle]=25;

(2)比較listData[middle]和value,由於listData[middle] < 46,下一步到後半部分查詢,於是

low=middle+1,low=5;

high依舊為9, high=9;

mid=(low+high)/2, middle=7;

listData[middle]=40;

(3)比較listData[middle]和value,由於listData[middle] > 39,下一步到前半部分查詢,於是

low依舊為5, low=5;

high=middle-1, high=6;

mid=(low+high)/2, middle=5;

listData[middle]=28;

(4)比較listData[middle]和value,由於listData[middle] < 39,下一步到後半部分查詢,於是

low=middle+1,low=6;
high依舊為6, high=6;
mid=(low+high)/2,middle=6;
listData[middle]=39;

(5)比較listData[middle]和value,由於listData[middle] == 39,查詢成功,返回索引,結束。

三、二分查詢的實現

package com.joshua317;

import java.util.Arrays;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        /*
        System.out.println("折半查詢演算法例項");
        System.out.println("請輸入十個有序的整型資料");

        int[] listData = new int[10];
        Scanner scanner = new Scanner(System.in);
        // 接收資料
        for (int i = 0; i < listData.length; i++) {
            listData[i] = scanner.nextInt();
        }

        // 列印所有陣列元素
        System.out.print("輸入的資料為:");
        for (int i = 0; i < listData.length; i++) {
            System.out.print(listData[i] + ",");
        }
        System.out.println();
        System.out.println("請輸入要查詢的資料");
        int value = scanner.nextInt();
         */
        int[] listData = {2, 12, 15, 23, 25, 28, 39, 40,46,66};
        int value = 39;

        int index = binarySearch(listData, value);
        if (index != -1) {
            System.out.println("在第" + (index+1) + "個位置,資料:" + listData[index]);
        } else {
            System.out.println("資料未找到");
        }

    }

    public static int binarySearch(int[] listData, int value)
    {
        int low, middle, high;
        low = 0;
        high = listData.length - 1;
        while (low <= high) {
            middle = (low + high) / 2;
            System.out.printf("low=%d,high=%d,middle=%d,listData[middle]=%d", low, high, middle, listData[middle]);
            System.out.println();
            if (listData[middle] == value) {
                return middle;
            } else if (listData[middle] > value) {
                high = middle - 1;
            } else if (listData[middle] < value) {
                low = middle + 1;
            }
        }

        return -1;
    }
}

四、最後

折半查詢的優點是比較次數較順序查詢要少,查詢速度較快,執行效率較高。缺點是表的儲存結構只能為順序儲存,不能為鏈式儲存,且表中元素必須是有序的。折半查詢成功時的平均查詢長度log2(n+1)-1,它的時間複雜度為O(log2n)