繁体   English   中英

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

[英]Binary Search is giving me a segfault

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

#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;
}

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

正如@Claies所说,中间索引的计算是错误的。 它应该是low +(high-low)/ 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;
}
int mid = (low + (high-low)) / 2; // wrong formula

@paganinist很好的答案指出了OP的搜索方法中的缺陷并已修复。


尚未深入。

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

在极端情况下,数组大小可能接近最大值或超过int的范围。
对于int范围较高的尺寸,以下更好。 @乔纳森·莱夫勒

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

要容纳所有数组大小,请在int上使用size_t 这也可以处理大小,包括INT_MAX附近和以上的 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

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

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

@paganinist对大小写倒写是正确的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM