數據結構和算法-線性查找-二分查找


一、二分查找簡述

折半查找(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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM