折半(二分)查找


問題描述##

折半查找

思路##

明顯的解法是從左到右掃描數(shù)據(jù),其運行花費的是線性時間。然而,這個算法沒有用到該表已經(jīng)排序的事實,這就使得算法可能不是最好的。一個好的策略是驗證X是否是居中元素。如果是,則答案就找到了。如果X小于居中元素,那么我們可以應(yīng)用同樣的策略于居中元素左邊已經(jīng)排好序的子序列;同理,如果X大于居中元素,那么我們檢查數(shù)據(jù)的右半部分。

代碼##

    public static <AnyType extends Comparable<? super AnyType>> int binarySearch(AnyType[] a, AnyType x) {
        int low = 0, high = a.length - 1;

        while (low <= high) {
            int mid = (low + high) / 2;
            if (a[mid].compareTo(x) < 0) {
                low = mid + 1;
            } else if (a[mid].compareTo(x) > 0) {
                high = mid - 1;
            } else {
                return mid;
            }
        }

        return -1;
    }

分析##

根據(jù)上面的算法,二分查找的過程可以用二叉判定樹來描述。例如,有序表{44,45,47,50,65,70}的二叉判定樹如下圖所示:

二叉判定樹

在二分查找過程中,查找失敗時需要比較的關(guān)鍵字至多為log2(N+1)向上取整(二叉樹的層數(shù)),查找成功時需要比較的關(guān)鍵字至多為log2(N+1)向上取整。二分查找的時間復(fù)雜度為O(log2N)。二分查找的平均性能和最壞性能相當(dāng)接近。其優(yōu)點是查找效率比順序查找高,缺點是要求查找有序表,并且二分查找只適用于順序存儲結(jié)構(gòu),鏈?zhǔn)酱鎯Y(jié)構(gòu)的順序表無法采用二分查找算法。

二分查找提供了在O(logN)時間內(nèi)的contains操作,但是所有其他操作(特別是insert操作)均需要O(N)時間。在數(shù)據(jù)穩(wěn)定(即不允許插入操作和刪除操作)的應(yīng)用中,這種操作可能是非常有用的。此時輸入數(shù)據(jù)需要一次排序,但是此后的訪問會很快。有個例子是一個程序,它需要保留(產(chǎn)生于化學(xué)和物理領(lǐng)域的)元素周期表的信息。這個表是相對穩(wěn)定的,因為很少會引入新元素。元素名可以始終是排序的。由于大約只有110種元素,因此找出一個元素最多需要8次。但是執(zhí)行順序查詢就需要多得多的查找次數(shù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容