演算法筆記 二分查詢(上)

2021-10-01 09:08:09 字數 1568 閱讀 1273

5.總結

二分查詢針對的是乙個有序的資料集合,查詢思想有點類似分治思想。每次都通過跟區間的中間元素對比,將待查詢的區間縮小為之前的一半,直到找到要查詢的元素,或者區間被縮小為 0。

二分查詢是目前為止遇到的第乙個時間複雜度為 o(logn) 的演算法。堆、二叉樹的操作等等,它們的時間複雜度也是 o(logn)。這是一種極其高效的時間複雜度,有的時候甚至比時間複雜度是常量級 o(1) 的演算法還要高效。

logn 是乙個非常「恐怖」的數量級,即便 n 非常非常大,對應的 logn 也很小。比如 n 等於 2 的 32 次方,這個數很大了吧?大約是 42 億。也就是說,如果我們在 42 億個資料中用二分查詢乙個資料,最多需要比較 32 次。

最簡單的情況就是有序陣列中不存在重複元素:

非遞迴實現

public

intbsearch

(int

a,int n,

int value)

else

if(a[mid]

< value)

else

}return-1

;}

迴圈退出條件

注意是 low<=high,而不是 lowmid 的取值

實際上,mid=(low+high)/2 這種寫法是有問題的。因為如果 low 和 high 比較大的話,兩者之和就有可能會溢位。改進的方法是將 mid 的計算方式寫成 low+(high-low)/2。更進一步,如果要將效能優化到極致的話,我們可以將這裡的除以 2 操作轉化成位運算 low+((high-low)>>1)。因為相比除法運算來說,計算機處理位運算要快得多。

low 和 high 的更新

low=mid+1,high=mid-1。注意這裡的 +1 和 -1,如果直接寫成 low=mid 或者 high=mid,就可能會發生死迴圈。比如,當 high=3,low=3 時,如果 a[3] 不等於 value,就會導致一直迴圈不退出

2.遞迴實現

// 二分查詢的遞迴實現

public

intbsearch

(int

a,int n,

int val)

private

intbsearchinternally

(int

a,int low,

int high,

int value)

else

if(a[mid]

< value)

else

}

二分查詢的核心思想理解起來非常簡單,有點類似分治思想。即每次都通過跟區間中的中間元素對比,將待查詢的區間縮小為一半,直到找到要查詢的元素,或者區間被縮小為 0。但是二分查詢的**實現比較容易寫錯。你需要著重掌握它的三個容易出錯的地方:迴圈退出條件、mid 的取值,low 和 high 的更新。

二分查詢雖然效能比較優秀,但應用場景也比較有限。底層必須依賴陣列,並且還要求資料是有序的。對於較小規模的資料查詢,我們直接使用順序遍歷就可以了,二分查詢的優勢並不明顯。二分查詢更適合處理靜態資料,也就是沒有頻繁的資料插入、刪除操作。

1024 二分查詢(上)

目錄 一 什麼是二分查詢?二 時間複雜度分析?三 如何實現二分查詢?四 使用條件 應用場景的侷限性 五 思考 二分查詢針對的是乙個有序的資料集合,每次通過跟區間中間的元素對比,將待查詢的區間縮小為之前的一半,直到找到要查詢的元素,或者區間縮小為0。1.時間複雜度 假設資料大小是n,每次查詢後資料都會...

2 二分查詢(上)

二分模板有兩個,分別適用於不同的情況。演算法思路 假設目標值在閉區間 l,r 中,每次將區間長度縮小一半,當l r時,我們就找到了目標值。版本一 當我們將區間 l,r 劃分成 l,mid 和 mid 1,r 時,其更新操作時l mid 1或者 r mid 計算mid時不需要加1。版本二 當我們將區間...

《演算法筆記》二分查詢

二分查詢 非遞迴實現 二分查詢的前提是有序,並且每次查詢的範圍都是閉區間 include include include using namespace std int a 10 intmain else if a mid n right mid 1 else if a mid n left mid...