C 无限递归:二进制搜索&;断言

C 无限递归:二进制搜索&;断言,c,recursion,binary-search,C,Recursion,Binary Search,我正在用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

我正在用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);
    }
}

我有一个后续问题:是否有一种方法可以使用资产来帮助我自己找到这个解决方案?(我只是在学习断言,所以我想知道在哪里可以应用它们)

您的函数应该如下所示:

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);
    }
}
void binary_搜索(int键,int数组[],int first_索引,int last_索引){
中间;
中间=(第一个指数+最后一个指数)/2;
if(数组[中间]==键){
printf(“%d位于位置%d\n”,键,中间+1);
}
else if(第一个索引==最后一个索引){
printf(“未找到项目”);
}
else if(键>数组[中间]){
二进制搜索(键、数组、中间+1、最后一个索引);
}
否则{
//assert(key
换句话说,在递归调用中适当地增加或减少中间值

这一点很重要,因为,例如,当搜索的大小减小到2,中间是第一个元素时,实际上在递归调用中不会更改数组的维度


我还将您的函数更改为
void
,因为您没有返回任何内容。

您可以搜索排序数组中更小的范围。数组的bounadries包含在内

递归的基本情况是:如果范围为空,则找不到键。或者,在代码中:

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);
        }
    }
}
这个函数仍然有两件事困扰着我:

  • 打印索引的函数几乎没有实际用途。打印应通过客户端代码完成,即通过调用函数的代码完成。返回找到的索引或“未找到”的特殊值
  • 该范围具有包含边界。那不是很像C。在C语言中,范围通常由一个包含的下界和一个独占的上界来描述。这就是循环的数组索引和
    的工作方式。遵循此约定意味着您的客户端代码不必进行笨拙的
    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 binary_search1(int键,int数组[],int first_索引,int last_索引)
{
if(第一个索引<最后一个索引){
中间整数=(第一个索引+最后一个索引)/2;
如果(数组[middle]==键)返回middle;
if(键>数组[中间]){
返回二进制搜索1(键、数组、中间+1、最后一个索引);
}否则{
返回二进制搜索1(键、数组、第一个索引、中间);
}
}
返回-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;
}
intmain()
{
int-arr[6]={3,4,6,8,12,13};
int i;
对于(i=0;i<20;i++){
int ix=二进制搜索(i,arr,0,6);
如果(ix<0){
printf(“%d未找到。\n”,i);
}否则{
printf(“索引%d处的%d.\n”,i,ix);
}
}
返回0;
}

请注意,原始数组中有重复的条目。这没关系,但您将获得任何重复值的索引,不一定是第一个。

在调试器中逐行遍历代码。如果您认为数组的大小太大,请减小它。只需查看您的代码:如果
first\u index
last\u index
相差1会怎么样?这也是递归应该停止的情况,而不是1。尝试在数组
{1}
中查找值
1
。结果是什么。尝试在数组
{1,2,3}
中查找值
2
。结果是什么?当项目不在数组中时,这是有效的,但当项目在数组中时,我的命令行绝对不会给出任何输出。@PythonNewb您没有考虑到
middle
实际上可能是
first\u index==last\u index
之前的值。那些如果不应该嵌套。我不知道为什么会有这么多的投票。它仍然不能解决一个空搜索范围检查错误和错误嵌套的基本问题。因为我有太多的时间,这里的代码不能正常工作:考虑ARR [3 ]={0,1,2},密钥为1的情况;middle=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;
}