[英]Infinite recursion: binary search & asserts
我正在用C語言編寫二進制搜索的實現,並且在沒有明顯(對我而言)原因的情況下獲得無限遞歸。 這是我的代碼:
/*Orchestrate program*/
int main(int argc, char* argv){
int array[] = {1,2,3,3,3,6,7,8,9,9,20,21,22};
int length = 13;
int key = 23;
binary_search(key, array, 0, length - 1);
return 0;
}
int binary_search(int key, int array[], int first_index, int last_index){
int middle;
middle = (first_index + last_index)/2;
if (first_index == last_index){
if (array[middle] == key){
printf("%d has been found at position %d\n", key, middle+1);
}
printf("item not found");
}
else if (key > array[middle]){
binary_search(key, array, middle, last_index);
}
else if (key < array[middle]){
binary_search(key, array, first_index, middle);
}
}
根據main中密鑰的值,我猜問題出在第一個問題上,但是我不確定為什么。 如果我要刪除first_index == last_index
行,則該算法可以正常工作,但僅當該項目位於數組中時才有效。 如果該項不在數組中,我自然會得到無限遞歸。
另外,我嘗試通過刪除first_index == last_index
行並放置return -1;
來解決此問題return -1;
在函數的末尾,但是我遇到的問題與我現在遇到的問題相同。
編輯:
匯總從幾個不同用戶那里獲得的建議,我得出了以下解決方案(由於一個錯誤和未套用的決定而被修正):
void binary_search(int key, int array[], int first_index, int last_index){
int middle;
middle = (first_index + last_index)/2;
if (array[middle] == key){
printf("%d has been found at position %d\n", key, middle+1);
}
if (first_index == last_index){
printf("item not found");
}
else if (key > array[middle]){
binary_search(key, array, middle + 1, last_index);
}
else if (key < array[middle]){
binary_search(key, array, first_index, middle - 1);
}
}
我有一個后續問題:是否可以使用斷言來幫助我自己找到解決方案? (我只是在學習斷言,所以我想知道在哪里可以應用它們)
您搜索的數組范圍越來越小。 您的陣列中的所有部件均包含在內。
遞歸的基本情況是:如果范圍為空,則找不到鍵。 或者,在代碼中:
if (first_index > last_index){
printf("Not found\n");
}
僅在確定范圍不為空之后,才應計算並比較范圍的中間元素。 在這種情況下,您將獲得三個結果:
全部放在一起:
void binary_search(int key, int array[], int first_index, int last_index)
{
if (first_index > last_index){
printf("Not found\n");
} else {
int middle = (first_index + last_index) / 2;
if (array[middle] == key) printf("%d at index %d\n", key, middle);
if (key > array[middle]){
binary_search(key, array, middle + 1, last_index);
} else {
binary_search(key, array, first_index, middle - 1);
}
}
}
此功能還有兩點困擾我:
for
循環的工作方式。 遵循此約定意味着您的客戶端代碼不必執行笨拙的length - 1
計算。 因此,這是一個變體,如果鍵不在數組中,則返回索引或-1:
int binary_search1(int key, int array[], int first_index, int last_index)
{
if (first_index < last_index){
int middle = (first_index + last_index) / 2;
if (array[middle] == key) return middle;
if (key > array[middle]){
return binary_search1(key, array, middle + 1, last_index);
} else {
return binary_search1(key, array, first_index, middle);
}
}
return -1;
}
並使用以下命令進行測試:
int main()
{
int arr[6] = {3, 4, 6, 8, 12, 13};
int i;
for (i = 0; i < 20; i++) {
int ix = binary_search(i, arr, 0, 6);
if (ix < 0) {
printf("%d not found.\n", i);
} else {
printf("%d at index %d.\n", i, ix);
}
}
return 0;
}
請注意,原始數組具有重復的條目。 可以,但是您將獲得任何重復值的索引,而不必是第一個。
您的函數應如下所示:
void binary_search(int key, int array[], int first_index, int last_index){
int middle;
middle = (first_index + last_index)/2;
if (array[middle] == key){
printf("%d has been found at position %d\n", key, middle+1);
}
else if (first_index == last_index) {
printf("item not found");
}
else if (key > array[middle]){
binary_search(key, array, middle + 1, last_index);
}
else {
//assert (key < array[middle]); // feel free to uncomment this one and include the assert library if you want
binary_search(key, array, first_index, middle - 1);
}
}
換句話說,在遞歸調用中適當增加或減少中間值。
這很重要,因為,例如,當您縮小到搜索大小2且中間是您的第一個元素時,那么實際上您就沒有在遞歸調用中更改數組的維數。
我也將您的函數更改為void
因為您什么都不返回。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.