二分查詢(一)

2022-07-24 00:57:21 字數 2025 閱讀 7874

非遞迴實現:

public int bsearch(int a, int n, int value)  

else if (a[mid] < value)

else

} return -1;

}

著重強調一下容易出錯的 3 個地方。

1.迴圈退出條件

注意是 low<=high,而不是 low2.mid 的取值

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

3.low 和 high 的更新

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

遞迴實現:

public int bsearch(int a, int n, int val) 

private int bsearchinternally(int a, int low, int high, int value)

else if (a[mid] < value)

else

}

首先,二分查詢依賴的是順序表結構,簡單點說就是陣列。

那二分查詢能否依賴其他資料結構呢?比如鍊錶。答案是不可以的,主要原因是二分查詢演算法需要按照下標隨機訪問元素。陣列按照下標隨機訪問資料的時間複雜度是 o(1),而鍊錶隨機訪問的時間複雜度是 o(n)。所以,如果資料使用鍊錶儲存,二分查詢的時間複雜就會變得很高。

二分查詢只能用在資料是通過順序表來儲存的資料結構上。如果你的資料是通過其他資料結構儲存的,則無法應用二分查詢。

其次,二分查詢針對的是有序資料。

二分查詢對這一點的要求比較苛刻,資料必須是有序的。如果資料沒有序,我們需要先排序。排序的時間複雜度最低是 o(nlogn)。所以,如果我們針對的是一組靜態的資料,沒有頻繁地插入、刪除,我們可以進行一次排序,多次二分查詢。這樣排序的成本可被均攤,二分查詢的邊際成本就會比較低。

但是,如果我們的資料集合有頻繁的插入和刪除操作,要想用二分查詢,要麼每次插入、刪除操作之後保證資料仍然有序,要麼在每次二分查詢之前都先進行排序。針對這種動態資料集合,無論哪種方法,維護有序的成本都是很高的。

所以,二分查詢只能用在插入、刪除操作不頻繁,一次排序多次查詢的場景中。針對動態變化的資料集合,二分查詢將不再適用。

再次,資料量太小不適合二分查詢。

如果要處理的資料量很小,完全沒有必要用二分查詢,順序遍歷就足夠了。比如我們在乙個大小為 10 的陣列中查詢乙個元素,不管用二分查詢還是順序遍歷,查詢速度都差不多。只有資料量比較大的時候,二分查詢的優勢才會比較明顯。

不過,這裡有乙個例外。如果資料之間的比較操作非常耗時,不管資料量大小,我都推薦使用二分查詢。比如,陣列中儲存的都是長度超過 300 的字串,如此長的兩個字串之間比對大小,就會非常耗時。我們需要盡可能地減少比較次數,而比較次數的減少會大大提高效能,這個時候二分查詢就比順序遍歷更有優勢。

最後,資料量太大也不適合二分查詢。

二分查詢的底層需要依賴陣列這種資料結構,而陣列為了支援隨機訪問的特性,要求記憶體空間連續,對記憶體的要求比較苛刻。比如,我們有 1gb 大小的資料,如果希望用陣列來儲存,那就需要 1gb 的連續記憶體空間。

注意這裡的「連續」二字,也就是說,即便有 2gb 的記憶體空間剩餘,但是如果這剩餘的 2gb 記憶體空間都是零散的,沒有連續的 1gb 大小的記憶體空間,那照樣無法申請乙個 1gb 大小的陣列。而我們的二分查詢是作用在陣列這種資料結構之上的,所以太大的資料用陣列儲存就比較吃力了,也就不能用二分查詢了。

二分查詢(一)

在演算法題目中,很重要的乙個就是邊界條件的設定,需要我們去明確,變數代表的含義,在迴圈的過程中一直保證此變數的含義不發生變化。含義不發生變化,而非變數值。class binaryclass system.out.println binarysearch2 arr,arr.length,4 publi...

二分查詢(一)

二分查詢 1.首先找到列表中排在中間的元素,比較目標元素與該元素的大小,如果中間的元素等於目標元素,則返回true,否則返回false 2.如果目標元素比該元素大,則在中間元素與最後乙個元素之間重複步驟1 在中間元素右邊進行查詢目標元素 3.如果目標元素比該元素小,則在中間元素與第乙個元素之間重複步...

迭代二分查詢二分查詢

在寫這篇文章之前,已經寫過了幾篇關於改迭代二分查詢主題的文章,想要了解的朋友可以去翻一下之前的文章 bentley在他的著作 writing correct programs 中寫道,90 的計算機專家不能在2小時內寫出完整確正的二分搜尋演算法。難怪有人說,二分查詢道理單簡,甚至小學生都能明確。不過...