Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在我的C二进制搜索代码中我做错了什么?(迭代和递归)_C_Algorithm_Recursion_Search_Binary Search - Fatal编程技术网

在我的C二进制搜索代码中我做错了什么?(迭代和递归)

在我的C二进制搜索代码中我做错了什么?(迭代和递归),c,algorithm,recursion,search,binary-search,C,Algorithm,Recursion,Search,Binary Search,我做错了什么? 原型是不可变的。 我需要写这两个函数,这就是我写的。 他们90%的时间都在工作。当我试图搜索中间元素时,迭代方法遇到了一个问题 递归方法有一些问题,但我真的不知道是怎么回事。有时它会找到元素,有时则不会 还有一件事我不能改变,那就是我必须避免检查函数内部是否array[middle]==key。老师希望我们只在我退出循环时做这个检查,他希望循环只检查我应该向右还是向左 int *BinarySearchIter(const int SortedArray[], int key,

我做错了什么? 原型是不可变的。 我需要写这两个函数,这就是我写的。 他们90%的时间都在工作。当我试图搜索中间元素时,迭代方法遇到了一个问题

递归方法有一些问题,但我真的不知道是怎么回事。有时它会找到元素,有时则不会

还有一件事我不能改变,那就是我必须避免检查函数内部是否
array[middle]==key
。老师希望我们只在我退出循环时做这个检查,他希望循环只检查我应该向右还是向左

int *BinarySearchIter(const int SortedArray[], int key, size_t length)
{
    /*  variables that will set the boundries of the searched area      */
    int left_index = 0, right_index = 0, middle = 0;
    int *result = NULL;
    
    assert(SortedArray);
    assert(length);
    
    left_index = 0;             /*  first elemenet in the array         */
    right_index = length - 1;   /*  last elemenet in the  array         */

    /* while only one elemenet is left in the searched area             */
    while (left_index <= right_index)
    {
        /* split it to half                                             */
        middle = (left_index + right_index) / 2;
        
        /*  if key greater, ignore left half, search only in right half */
        if (SortedArray[middle] < key)
        {
            left_index = middle + 1;
        }
        /*  if key smaller, ignore right half, search only in left half */
        else
        {
            right_index = middle - 1;
        }
    }

    /*  if we reach here, then element is the key or was not found      */
    result = (int *)SortedArray + middle;
            
    return (key == *result ? result : NULL);
}
/******************************************************************************/
int *BinarySearchRec(const int SortedArray[], int key, size_t length)
{
    int left_index = 0; /*  first elemenet of the array */
    int right_index = length - 1; /* last elemenet in the array */  
    int middle = 0, isBigger = 0;
    
    if (1 == length)    
    {
        return (key == *SortedArray ? (int *)SortedArray : NULL);
    }
    
    middle = (left_index + right_index) / 2;    

    isBigger = (key > SortedArray[middle]);
    
    return (BinarySearchRec(SortedArray+(middle + 1)*isBigger, key, isBigger * (length - length /2 ) + !isBigger*(length/2)));
    
}
/******************************************************************************/
用于迭代函数 让我们想想你的代码在做什么。您有一个由5个元素组成的数组,假设您正在搜索8

2 4 8 10 12
    ^
在第一次迭代中,值如下所示:

left_index = 0, right_index = 4, middle_index = 2
const int *BinarySearchIter(const int SortedArray[], int key, size_t length) {

    int left_index = 0, right_index = length - 1;

    while (left_index < right_index) {

        int middle = (left_index + right_index) / 2;

        if (SortedArray[middle] < key) {
            left_index = middle + 1;
        } else {
            right_index = middle;
        }
    }

    return SortedArray[right_index] == key ? SortedArray + right_index : NULL;
}
在if语句中,程序检查(SortedArray[middle_index],这是错误的,因为8不大于8。因此它执行else语句。错误就在这里

在else语句中,您将丢弃中间的元素。但在这种情况下,中间元素是您要寻找的关键

因此,您需要更改的第一件事就是将您的else语句更改为:

else {
  right_index = middle;
}
while (left_index < right_index)
让我们继续第二次迭代:

2 4 8
  ^
left_index = 0, right_index = 2, middle_index = 1
在第二次迭代之后,第三次迭代只包含1个元素

8
left_index = 2, right_index = 2, middle_index = 2
此时,程序将进入无限循环,因为它总是执行else语句。左右索引始终保持不变

因此,您需要做的第二个更改是将while条件更改为:

else {
  right_index = middle;
}
while (left_index < right_index)
其原因与迭代函数相同。您需要包含中间元素。对于阵列的下部,阵列长度需要等于ceil(长度/2),对于阵列的上部,阵列长度需要等于floor(长度/2)

2 4 8 10 12
    ^
您也可以这样做:

const int *BinarySearchRec(const int SortedArray[], int key, size_t length) {   
    if (1 == length) return (key == *SortedArray ? SortedArray : NULL);

    int middle = (length + 1) / 2;

    if (key >= SortedArray[middle]) return BinarySearchRec(SortedArray + middle, key, length / 2);
    else return BinarySearchRec(SortedArray, key, middle);
}

BinarySearchRec
中,假设
length
为5。然后,
右索引
为5,
中间
(0+4)/2
=2。然后,如果
isbiger
为0,则传递给递归调用的长度为
length/2
,即2。因此递归调用将搜索两个元素,即索引为0和1的元素。如果
更大
为1,则它通过
SortedArray+(中间+1)*1
,因此
SortedArray+3
,它通过长度
长度-长度/2
,即5−2 = 3. 因此,递归调用被要求搜索索引为3、4和5的元素,这是错误的。在迭代代码中,如果您没有测试中间值是否相等,那么您就不能在下一次迭代中删除它。@斯塔克问题是,他不希望我们在退出循环之前测试中间值是否相等。如果middle==key,只需添加
就很容易了。。返回while循环开始时的
。但他不想让我们这么做。他希望我们找到一种方法,仅当您退出循环并需要返回找到的索引时才检查它。这就是为什么我要在
return
行中检查它。@NoobCoder:Stark的评论告诉你问题出在哪里。它并没有说要检验中间人是否平等。它说,因为您无法测试中间值是否相等,所以在准备下一次迭代时不要删除它。分配<代码>右索引=中间-1是错误的,因为它排除了中间部分。因为没有测试中间值是否相等,所以不能排除它。赋值应该是
right\u index=middle
@EricPostpischil嘿,谢谢你的回答。如果我们假设
length
为5,则意味着
right\u索引
4
,因为
right index=length-1
<在这种情况下,code>middle实际上是
2
。然后,如果
更大
0
,这意味着
小于
中间
,我们需要扫描数组的左侧。它传递到递归调用:
SortedArray[]的原始开始作为开始、键,2作为长度,..
好,说实话,我迷路了。你能指出我到底应该修什么吗?也许除了
length/2
我应该发送
length/2+1吗?
Wow!多么完美的答案,你帮助我理解了我的错误,并从中吸取教训,还提供了一个固定的代码。谢谢,我很感激!在编辑答案之前,您在my
reccursive
函数中编写了三件要修复的事情。为什么要删除其中的两个?我想问你为什么要在
中间索引=(左索引+右索引+1)/2中添加
+1
?我可以只写
middle=length/2吗?
我意识到有一个修改较小的补丁,所以我修改了递归函数的补丁。我添加了1,因为当我试图解决这个问题时,我没有使用first_索引和last_索引,而是直接使用长度,所以它导致了有限循环。然后我用ceil找到了一个解决方案,然后将该解决方案实现到您的代码中。我认为如果不加1,它将导致无限循环。然后我意识到您使用的是第一个和最后一个索引,不需要做其他更改。我想这是一个更好的方法。谢谢。如果你有任何其他的提示和建议,我很乐意听到,因为你的评论帮助我深刻理解我在实现中的错误。