二进制搜索给我一个段错误

时间:2018-11-04 04:33:26

标签: c

我正在尝试运行此二进制搜索实现。我不知道为什么,但是它一直在给我段错误。我在想问题可能是我传递数组的方式,或者递归调用有问题。

#include <stdio.h>

int hasBinarySearch(int *array, int low, int high, int element)
{

    int mid = (low + (high-low)) / 2;

  if (high>=low)
  {

    if (array[mid] == element)
    {
      return mid;
    }
    else if(array[mid]<element)
    {
        return hasBinarySearch(array, low, mid-1, element);
    }
    else
    {
      return hasBinarySearch(array, mid+1, high, element);
    }
  }

  return 0;
}



int main(void)
{
  int array[10] = {1,2,3,4,5,6,6,6,7,8};
  hasBinarySearch(array, 0, 9, 2);

  return 0;
}

3 个答案:

答案 0 :(得分:3)

我认为您对二进制搜索有些误解。阅读一些有关此的文章或书。

正如@Claies所说,中间索引的计算是错误的。 它应该是低+(高-低)/ 2 。只需考虑一下数学中两点的内部划分。

此外,您还必须修复递归调用的参数,例如下面的代码。

#include <stdio.h>

int hasBinarySearch(int *array, int low, int high, int element)
{

    int mid = low + (high - low) / 2; // changed
    printf("%d %d\n", high, low);
    if (high >= low)
    {
        if (array[mid] == element)
        {
            return mid;
        }
        else if (array[mid] < element)
        {
            return hasBinarySearch(array, mid + 1, high, element); // changed
        }
        else
        {
            return hasBinarySearch(array, low, mid - 1, element); // changed
        }
    }
    return 0;
}

int main(void)
{
    int array[10] = { 1,2,3,4,5,6,6,6,7,8 };
    hasBinarySearch(array, 0, 9, 2);
    return 0;
}

答案 1 :(得分:2)

int mid = (low + (high-low)) / 2; // wrong formula

@paganinist好的答案指出了OP的搜索方法中的缺陷并提供了解决方案。


还需要更深入地挖掘。

即使某些编译器可能能够“取消递归”代码(Example),在这里也不需要递归。一个简单的循环就足够了。

在极端情况下,数组大小可能接近最大值或超过int的范围。
对于int高范围的尺寸,以下效果更好。 @Jonathan Leffler

// int mid = (low + high)/2;  // could overflow
int mid = low + (high-low)/2; // better, will not overflow when low >= 0

要容纳所有个数组大小,请在size_t上使用int。这也可以处理尺寸,包括在和以上 INT_MAX附近的尺寸。


候选解决方案,返回匹配元素或NULL(如果找不到)的地址。

#include <stdlib.h>
#include <stdio.h>

int *BinarySearch_int(const int *array, size_t count, int key) {
  while (count > 0) {
    size_t mid = count / 2;
    if (key > array[mid]) {
      array += mid + 1;
      count -= mid + 1;
    } else if (key < array[mid]) {
      count = mid;
    } else {
      return (int *) &array[mid];
    }
  }
  return NULL;
}

测试代码

bool BinarySearch_int_test(const int *array, size_t count, int key, bool target){
  int *p = BinarySearch_int(array, count, key);
  bool success = (p != NULL) == target && (p == NULL || *p == key);
  printf("f(Array:%p count:%zu, key:%2d) --> ptr:%p value:%2d success:%d\n",
      (void*) array, count, key, (void*) p, p ? *p : 0, success);
  return success;
}

int main(void) {
  int array[] = {10, 20, 30, 40, 50, 60};
  size_t n = sizeof array / sizeof array[0];
  for (size_t i = 0; i < n; i++) {
    BinarySearch_int_test(array, n, array[i], 1);
  }
  BinarySearch_int_test(array, n, 0, 0);
  for (size_t i = 0; i < n; i++) {
    BinarySearch_int_test(array, n, array[i] + 1, 0);
  }
}

输出

f(Array:0xffffcb90 count:6, key:10) --> ptr:0xffffcb90 value:10 success:1
...
f(Array:0xffffcb90 count:6, key:60) --> ptr:0xffffcba4 value:60 success:1
f(Array:0xffffcb90 count:6, key: 0) --> ptr:0x0 value: 0 success:1
...
f(Array:0xffffcb90 count:6, key:61) --> ptr:0x0 value: 0 success:1

答案 2 :(得分:1)

mid的计算可简化为high / 2,因为您已经添加了,然后又减去了下界。看来您打算将差值的一半加到下限,但除法为时已晚。它应该是 low + (high-low) / 2 。 (这比(low + high) / 2复杂一点,但避免了其他地方提到的整数问题。)

我认为当high低于low并变得太小而您从数组的开头落下时,就会发生段错误。

@paganinist正确地说大写和小写都向后。