假設我們有1000萬個整數資料,每個資料佔8個位元組,如何設計資料結構和演算法,快速判斷某個整數是否出現在這1000萬資料中?我們希望這個功能不要占用太多的記憶體空間,最多不要超過100m,你會怎麼做?
二分查詢時一種非常簡單易懂的快速查詢演算法,生活中到處可見。比如說,我們現在來做乙個猜字遊戲。我隨機寫乙個0到99之間的數字,然後你來猜我寫的是什麼。猜的過程中,你每猜一次,我就會告訴你猜的大了還是小了,直到猜中為止。
二分查詢針對的時乙個有序的資料集合,查詢思想有點類似分治思想。每次都通過跟區間的中間元素對比,將待查詢的區間縮小為之前的一半,直到找到查詢的元素,或者區間被縮小為0。
二分查詢最簡單的情況就是有序陣列中不存在重複元素,我們在其中用二分查詢值等於給定值的資料。
public int bsearch(int a, int n, int value) else if (a[mid] < value) else
} return -1;
}
現在,著重強調一下容易出錯的三個地方:
迴圈退出條件
注意low <= high,而不是low < high
mid的取值
實際上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[2]不等於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
}
首先,二分查詢依賴的是順序表結構,簡單點說就是陣列。
其次,二分查詢針對的是有序資料。
再次,資料量太小不適合二分查詢
最後,資料量太大也不適合二分查詢
資料結構與演算法之二分查詢
二分查詢又稱折半查詢,優點是比較次數少,查詢速度快,平均效能好 其 缺點是要求待查表為有序表,且插入刪除困難。因此,折半查詢方法適用於不經常變動而查詢頻繁的有序列表。首先,假設表中元素是按公升序排列,將表中間位置記錄的 關鍵字與查詢關鍵字比較,如果兩者相等,則查詢成功 否則利用中間位置 記錄將表分成...
資料結構與演算法之二分查詢
二分查詢法作為一種常見的查詢方法,將原本是線性時間提公升到了對數時間範圍,大大縮短了搜尋時間,但它有乙個前提,就是必須在有序資料中進行查詢。二分查詢過程如下 1.將表中間位置記錄的關鍵字與查詢關鍵字比較,如果兩者相等,則查詢成功 2.否則利用中間位置記錄將表分成前 後兩個子表,如果中間位置記錄的關鍵...
資料結構與演算法之二分查詢法
public static void main string args 目標元素 int target 9 目標元素的索引 int index 1 記錄開始位置 int begin 0 記錄結束位置 int end arr.length 記錄中間位置 int mid begin end 2 迴圈查詢...