我正在尝试运行此二进制搜索实现。我不知道为什么,但是它一直在给我段错误。我在想问题可能是我传递数组的方式,或者递归调用有问题。
#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;
}
答案 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正确地说大写和小写都向后。