1. 程式人生 > >二分查詢(binary search)

二分查詢(binary search)

二分查詢(binary search)

二分查詢對於學過資料結構或者演算法的人來說,應該是非常熟悉的。其基本思想是:比較目標(target)和中間關鍵字的大小關係,如果二者相等,則查詢完畢;如果二者不等,則可以根據二者的大小關係,將查詢的範圍減半。

雖然二分查詢的演算法很簡單,但是對於一個code新手來說,正確無誤地實現一個二分查詢演算法也不是那麼容易的。

最近,刷了幾道二分查詢的題目,將刷題的一點收穫整理如下:

1.二分查詢演算法適用的範圍:

①必須是順序表,不適用於鏈式儲存
②查詢之前,序列必須是有序的。對於無序的序列,可以先採用合適的排序演算法進行排序後,再使用二分查詢。

2.二分查詢演算法的基本模式:

遞迴方式:

int binary_search(const int[] arr,int start,int end,int khey){
    if(start > end)
        return -1;
    int mid = start + (end - start) / 2;
    if(arr[mid] > khey)
        return binary_search(arr,start,mid-1,khey);
    if(arr[mid] < khey)
        return binary_search(arr,mid+1
,end,khey); return mid;//最後檢測相等是因為大多數情況下是小於或者大於 }

非遞迴方式:(更常用)

int binary_search(const int[] arr,int start,int end,int khey){
    int mid;
    while(start <= end){
        mid = start + (end - start) / 2;
        if(arr[mid] < khey)
            start = mid +1;
        else if(arr[mid] > khey)
            end = mid - 1
; else return mid; } return -1; }

其中,需要注意的地方有:
① 我們學習二分演算法的時候,求mid可能會用:mid = (start + end)/2,這時,在計算start+end的時候,可能會產生溢位,故以上所寫的兩種方式,均採用start + (end - start) / 2的方式,有時候可以避免溢位。
②在非遞迴演算法中,while迴圈中究竟應該是(start < end)還是(start <= end),這應該具體情況具體分析;
③對於mid和khey比較的三種情況(大於,小於,相等)的排列順序,大多數情況下,是影響不大的,實際中,可以根據三種情況出現的概率,決定其順序;
④以上僅僅是二分查詢演算法的模板,具體使用時應該具體情況具體分析,靈活運用。

3.二分查詢的複雜度

時間複雜度:O(logn)
空間複雜度:O(1)

在有些地方你可能會看到三分查詢(ternary search),三分查詢基本思想和二分查詢一致,具體來講:每次選出三分之一點和三分之二點,而不是中點,然後比較target和這兩個點的大小關係,從而將查詢的範圍縮小至原來的三分之一。

二分查詢和三分查詢的空間複雜度都是O(1),而二分查詢的時間複雜度是O(log2n),三分查詢的時間複雜度是O(log3n)。既然三分查詢的時間複雜度要優於二分查詢,那我們為什麼不經常使用三分查詢,而經常使用二分查詢呢?原因在於在最壞情況下,三分查詢要明顯劣於二分查詢。這個具體的推導過程就不詳述了, 想了解的可以參考這道題目