折半查找(Binary search)也稱爲二分查找。
它的前提是線性數據表中的記錄必須是關鍵碼有序(通常是從小到大有序),線性表必須採用順序存儲。
折半查詢的基本思想是:
在有序表中,取中間記錄作爲比較對象,若給定值與中間記錄的關鍵字相等,則查找成功;
若給定值小於中間記錄的關鍵字,則在中間記錄的左半區繼續查找;
若給定值大於中間記錄的關鍵字,則在中間記錄的右半區繼續查找;
不斷重複上述過程直到查找成功,或所有查找區域無記錄,則查找失敗。
折半查找算法如下:
/*
array 要查的數組
n 數組大小
key 要查的關鍵字
*/
int binary_search(int *array, int n, int key)
{
int low, high, mid;
low = 0; //定義最低下標爲記錄首位
high = n-1;//定義最高下標爲記錄末尾
while (low <= high) {
mid = (low + high) / 2;//折半
if (key < array[mid]) { //查找值比中值小
high = mid - 1;//左半區 最高下標調整到中值最表小一位
}else if (key > array[mid]){//查找值比中值大
low = mid + 1;//右半區 最低小標調整到中值下標大一位
}else{
return mid; //若相等則說明mid即爲查找到的位置
}
}
return -1;//返回-1說明查找失敗
}
折半查找的前提是需要數據表順序存儲,對於靜態查找表,一次排序後不再變化,這樣的算法已經比較好了。
但對於需要頻繁執行插入或刪除操作的數據集來說,維護有序的排序會增加不少工作量,就不建議使用了。
折半查找的優化:
折半查找的關鍵是找到中間值,然後中間值和關鍵值進行比較。
如何快速的找到中間值,即循環幾次找到中間值,成爲優化折半查找的關鍵。
中間值: mid = (low + high) / 2 = mid = low + 1/2 (high - low);
算法科學家將1/2裝換爲:mid = low + (key - array[low]) / (array[high] - array[low]) * (high - low);
這樣就能極大的縮短查找中間值的速度,進而快速的查找到關鍵值。
這種算法又稱爲插值查找:
即根據奧查找的關鍵字key與查找表中最大最小記錄的關鍵字比較後的查找方法,其核心在於插值的計算公式:
(key - array[low]) / (array[high] - array[low]) 。
這種算法對於表長較長,而關鍵字的分佈又比較均勻的查找表來說,它的性能比折半查找要好很多。
對於數據極端不均勻的查找表來說,用插值查找法就不是很合適的選擇。
插值查找算法:
/*
array 要查的數組
n 數組大小
key 要查的關鍵字
*/
int binary_search(int *array, int n, int key)
{
int low, high, mid;
low = 0; //定義最低下標爲記錄首位
high = n-1;//定義最高下標爲記錄末尾
while (low <= high) {
mid = low + (key - array[low]) / (array[high] - array[low]) * (high - low);//插值查找
if (key < array[mid]) { //查找值比中值小
high = mid - 1;//左半區 最高下標調整到中值最表小一位
}else if (key > array[mid]){//查找值比中值大
low = mid + 1;//右半區 最低小標調整到中值下標大一位
}else{
return mid; //若相等則說明mid即爲查找到的位置
}
}
return -1;//返回-1說明查找失敗
}