把二分查詢演算法寫正確需要注意的地方《轉》

2021-07-03 20:12:29 字數 2031 閱讀 3570

把二分查詢演算法寫正確需要注意的地方

今天再次解決乙個需要使用二分查詢的問題,再一次的,我又沒有一次過寫對.(為什麼我說」又」?)

抓狂了,似乎開始有一些」二分查詢恐懼症」.

為了以後能夠一次將這個基本的演算法寫對,我決定再仔細研究一下.我之前有寫過乙個二分查詢的演算法,在這裡,這一次再以這個問題為例來說明.

我今早寫下的錯誤**類似於下面的樣子:

#include int search(int

array, int n, int v)

else

if (array[middle] < v)

else

}return -1;

}int main()

; int m = search(array, sizeof(array)/sizeof(array[0]), 1);

printf("m = %d\n", m);

return 0;

}

實際上,如果使用測試用例來測試,這個演算法並不是在所有情況下都會出錯的,還是有時可以得到正確的結果的.但是,你能看出來它錯在哪兒嗎?

在這裡,迴圈的開始處,把迴圈遍歷的序列區間是這樣的:

left =0, right = n;

while (left < right)

也就是說,這是乙個左閉右開的區間:[0, n).

但是,在迴圈內部, 卻不是這樣操作的:

if (array[middle] > v)

else

if (array[middle] < v)

else

當array[middle] > v條件滿足時, 此時v如果存在的話必然在左閉右開區間[left, middle)中, 因此,當這個條件滿足時, right應該為middle, 而在這裡, right賦值為middle - 1了, 那麼, 就有可能遺漏array[middle - 1] = v的情況.

因此,這種錯誤的寫法並不是在所有的情況下都會出錯,有時還是可以找到正確的結果的.

這是一種典型的二分查詢演算法寫錯的情況,迴圈體是左閉右開區間,而迴圈體內部卻是採用左閉右閉區間的演算法進行操作.

下面給出的兩種正確的演算法,演算法search是左閉右閉區間演算法,而演算法search2是左閉右開區間演算法,可以對比一下差異.

int search(int

array, int n, int v)

else

if (array[middle] < v)

else

}return -1;

}int search2(int

array, int n, int v)

else

if (array[middle] < v)

else

}return -1;

}

下面再給出另一種典型的錯誤的二分查詢演算法,當查詢的元素不在序列內時,它可能造成程式的死迴圈.

int search(int

array, int n, int v)

else

if (array[middle] < v)

else

}return -1;

}

為什麼會造成死迴圈?

從迴圈條件來看,這個演算法的操作區間是左閉右閉區間的,因此當array[middle] > v時,v如果存在的話應該在[left, middle- 1]中,因此此時right應該是middle - 1,而不是middle;類似的,當array[middle] < v時,下一次操作的區間應該是[middle + 1, right]中.而當元素不存在這個序列中時,演算法在乙個錯誤的區間中迴圈,但是又不能終止迴圈,於是就造成了死迴圈.

因此,要將二分查詢演算法寫對,其實很多人都大概知道思想,具體到編碼的時候,就會被這些看似微小的地方搞糊塗.因此,需要注意這一點:

演算法所操作的區間,是左閉右開區間,還是左閉右閉區間,這個區間,需要在迴圈初始化,迴圈體是否終止的判斷中,以及每次修改left,right區間值這三個地方保持一致,否則就可能出錯.

把二分查詢演算法寫正確需要注意的地方

今天再次解決乙個需要使用二分查詢的問題,再一次的,我又沒有一次過寫對.為什麼我說 又 抓狂了,似乎開始有一些 二分查詢恐懼症 為了以後能夠一次將這個基本的演算法寫對,我決定再仔細研究一下.我之前有寫過乙個二分查詢的演算法,在 這裡,這一次再以這個問題為例來說明.我今早寫下的錯誤 類似於下面的樣子 i...

二分查詢需要注意的Bug

不應該使用middle left right 2這種情況,否則對於大資料來說會產生溢位問題。切記!值不同的時候,left相對middle應該 1,不要直接用middle進行賦值。include include using namespace std 下面乙個移位是一樣的,相當於除去2,主要是要用ri...

二分查詢需要注意的幾點及優化

我們都已經很清楚普通的二分查詢演算法的寫法 1.處理無效輸入的時候 bool isinvalidinput false 可以用作訊號量處理 int binaryserach int array,int n,int key isinvalidinput false 區分 1表示的意思是無效輸入還是沒找...