大話數據結構之:折半查找

折半查找(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說明查找失敗
}


發佈了124 篇原創文章 · 獲贊 29 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章