在C中编写递归二进制搜索

时间:2011-07-23 23:26:46

标签: c

我在网上找到了以下代码,

int binary_search(int a[], int low, int high, int target) {
    if (high < low)
        return -1;
    int middle = (low + high)/2;
    if (target < a[middle])
        return binary_search(a, low, middle-1, target);
    else if (target > a[middle])
        return binary_search(a, middle+1, high, target);
    else if (target == a[middle])
        return middle;
}

我的函数有一个指定的原型(意味着它有一定数量的参数不能改变)这是我到目前为止所拥有的

bool search(int value, int array[], int n) {
    if (array[n/2] == value)
        return 1; 
    else if (array[n/2] < value)
        return search(value, &array[n/2], (n)/2);
    else
        // how do I "return" the other half?
}

到目前为止,我的实施是否正确?我似乎无法弄清楚如何实现最终的else语句。

7 个答案:

答案 0 :(得分:2)

高和低表示继续研究的子阵列的边界。如果您分析代码,您会注意到如果target小于a[middle],您将不得不继续在数组的前半部分进行研究(实际上它调用binary_search传递相同的下限)但是,作为一个上限,实际middle - 1)。另一方面,如果target大于a[middle],则您必须继续在数组的后半部分进行研究(从middle + 1到high) 。当然,如果target等于a[middle],那么您已经完成了。

答案 1 :(得分:1)

编写递归函数的技巧:

  1. 弄清楚它应该如何结束。
  2. 弄清楚它应该在它结束之前看起来一步。
  3. 弄清楚它应该在它结束前看两个步骤,以及从#2到#1的转变与从#3转到#2的方式完全相同。
  4. 步骤1:

    如果搜索范围开头的数字是所需的数字,则返回true。

    如果搜索范围的结尾与搜索范围的开头相同,并且搜索范围中的数字不是所需的数字,则返回false。

    步骤2:

    如果搜索范围的长度为2,请将其拆分为两个元素搜索范围,并搜索可能包含所需数字的范围。

    步骤3:

    如果搜索范围的长度超过两个,请将其拆分为两个大致相等的搜索范围,并搜索可能包含所需数字的范围。

    (两者结合起来会是这样的)

    如果搜索范围的长度为两个或更多元素,请将其拆分为两个大致相等的范围,检查&#34;下限&#34;中的最高(最后)数字。范围,如果数字等于或小于该数字,则搜索较低范围;否则,搜索更高的范围。

    除非您选择最佳方法来解决问题,否则此技术不会为您提供最佳解决方案;但是,它会为您提供正确的解决方案(前提是您没有犯任何错误)。

    现在代码

    bool search(int value int array[], int lowIndex, int highIndex) {
      if (array[lowIndex] == value) {
        return true;
      } else if (lowIndex == highIndex) {
        return false;
      }
      int middleIndex = lowIndex + highIndex / 2;
      if (array[middleIndex] <= value) {
         return search(value, array, lowIndex, middleIndex);
      } else {
         return search(value, array, middleIndex+1, highIndex);
      }
    }
    

    在线阅读代码时,你有一个很大的劣势。你没有做上述三个步骤中的任何一个,所以你真的必须向后解决问题。这就像说,我有一个解决方案,但现在我必须弄清楚其他人如何解决它(假设他们没有犯任何错误,并假设他们有与你完全相同的要求)。< / p>

答案 2 :(得分:0)

高低变量代表您正在搜索的当前范围。您通常从数组的开头和结尾开始,然后确定该值是在第一个还是在后半部分,还是恰好在中间。如果它在中间,则返回该点。如果它低于中间,则再次搜索(递归),但现在仅在下半部分。如果它高于中间,则搜索上半部分。你重复这一点,每次分开并缩小范围。如果找到该值,则返回,否则,如果范围太窄而且为空(低位和高位索引都相同),则表示您没有找到它。

答案 3 :(得分:0)

高和低是阵列候选索引的上限和下限。换句话说,它们定义了子阵列中搜索目标可能存在的部分。由于每次迭代时子阵列的大小减半,因此很容易看出算法为O(log n)。

答案 4 :(得分:0)

return search(value, &array[(n)/2], (n)/2);

在您当前的代码中,首先,n不应该在括号中(它没有区别,但它让我感到困惑)。

接下来,如果要返回数组中的索引,则代码不会这样做,它会返回1。根据原型判断,您可能会考虑使用非递归方法,但如果您为每个返回添加正确的值,这可以正常工作。

你可以找出另一个陈述。只需绘制一张图片,找出指针应该在哪里,然后对它们进行编码。这是一个开始:

       new array if > n/2
         v-----------v
0, 1, 2, 3, 4, 5, 6, 7
         ^
        n/2

实际上,您可能不希望包含中间值。最后,请务必考虑长度为零,一,二和三的帐户列表。请写单元测试。这可能是最常被错误实现的算法之一。

答案 5 :(得分:0)

我试图解决您的问题,以下代码确实有效。但是,如果想要搜索的值不在数组

中,那么逃避递归的条件是什么
if(value==a[size/2]) return size/2;

    if( value<a[size/2]) {
        search(a,size/2,value);
    } else if (value>a[size/2] && a[size/2]<a[(a.length-1)/2]) {
        search(a,size/2+size,value);
    } else {
        search(a,size/2+a.length-1,value);
    }

答案 6 :(得分:0)

int * binSearch (int *arr,int size, int num2Search)
{

    if(size==1)
        return ((*arr==num2Search)?(arr):(NULL));

    if(*(arr+(size/2))<num2Search)
        return binSearch(arr+(size/2)+1,(size/2),num2Search);

    if(*(arr+(size/2))==num2Search)
        return (arr+(size/2));

    return binSearch(arr,(size/2),num2Search);
}