第一次在这里发帖。我最近实施了二进制搜索,但有时我的输出将返回一个巨大的负数。现在我的第一个想法是我打印一个数字,我的指针指向一个随机的内存位置。有人可以帮助我修改逻辑以及如何改进我的代码吗?
#include <stdio.h>
#include <stdlib.h>
int binarysearch(int *array, int size, int target);
int main() {
int array[] = { 1, 2, 3, 4, 5, 6 };
printf("%d\n", binarysearch(array, 8, 15));
return 0;
}
int binarysearch(int *array, int size, int target) {
int mid;
mid = size / 2;
if (size < 1) {
return -1;
}
if (size == 1) {
return array[0];
}
if (target == array[mid]) {
return target;
} else
if (target < array[mid]) {
binarysearch(array, mid, target);
} else{
binarysearch(array + mid, size - mid, target);
}
}
答案 0 :(得分:3)
对于初学者,你用数组中只有6个元素的元素数量无效来调用函数。
int array[] = { 1, 2, 3, 4, 5, 6 };
printf("%d\n", binarysearch(array, 8, 15));
^^^
此片段
if (size == 1) {
return array[0];
}
不正确。第一个元素不必等于目标。
本声明
binarysearch(array + mid, size - mid, target);
必须像
一样写 binarysearch(array + mid + 1, size - mid - 1, target);
最后,该函数具有未定义的行为,因为它在这些情况下不返回任何内容
if (target < array[mid]) {
binarysearch(array, mid, target);
} else{
binarysearch(array + mid, size - mid, target);
}
你需要写
if (target < array[mid]) {
return binarysearch(array, mid, target);
} else{
return binarysearch(array + mid, size - mid, target);
}
关于编程风格的两个词。最好将功能命名为binary_search
或类似binarySearch
,或最后命名为BinarySearch
,而不是binarysearch
。
一般来说,这不是一个好的功能设计。想象一下,数组有一个值为-1的元素。您如何确定该元素是否存在于数组中或不存在?
通常这样的函数会返回指向目标元素的指针(如果找到它),否则返回NULL指针。
这是一个演示程序,展示了如何实现这种方法。
#include <stdio.h>
int * binary_search( const int *a, size_t n, int target )
{
if ( n == 0 ) return NULL;
size_t middle = n / 2;
if ( a[middle] < target )
{
return binary_search( a + middle + 1, n - middle - 1, target );
}
else if ( target < a[middle] )
{
return binary_search( a, middle, target );
}
return a + middle;
}
int main(void)
{
int array[] = { 1, 2, 3, 4, 5, 6 };
const size_t N = sizeof( array ) / sizeof( *array );
for ( int i = 0; i < 8; i++ )
{
int *target = binary_search( array, N, i );
if ( target )
{
printf( "%d is found at position %d\n", *target, ( int )(target - array ) );
}
else
{
printf( "%d is not found\n", i );
}
}
return 0;
}
程序输出
0 is not found
1 is found at position 0
2 is found at position 1
3 is found at position 2
4 is found at position 3
5 is found at position 4
6 is found at position 5
7 is not found
顺便说一句,根据C标准函数main,没有参数应该声明为
int main( void )
答案 1 :(得分:2)
您拨打binarysearch(array, 8, 15))
,但您的阵列只有6个条目。
以下是如何自动计算合适的尺寸:
int main(void) {
int array[] = { 1, 2, 3, 4, 5, 6 };
printf("%d\n", binarysearch(array, sizeof(array) / sizeof(array[0]), 15));
return 0;
}
请注意,您的函数binarysearch
也存在问题:
返回数组条目是假的,如果目标小于第一个条目,你会返回什么? -1
不一定小于第一个条目。
您应该将索引返回到包含条目(如果找到)的数组中,如果找不到则-1
。
当你递归时,你不会从这些递归调用返回值:你应该在启用警告的情况下进行编译(例如:gcc -Wall -W
)并查看编译器生成的所有有用的诊断消息。 / p>
以下是修改后的版本:
int binarysearch(const int *array, int size, int target) {
int a, b;
for (a = 0, b = size; a < b;) {
int mid = a + (b - a) / 2;
if (target <= array[mid]) {
b = mid;
} else {
a = mid + 1;
}
}
// a is the offset where target is or should be inserted
if (a < size && target == array[a])
return a;
else
return -1;
}
注意:
计算mid = (a + b) / 2;
对于大尺寸可能不正确,因为可能存在算术溢出。自mid = a + (b - a) / 2;
以来,a < b
没有此问题。
时间复杂度为 O(Log N),对于给定的size
,该函数对所有目标值执行相同数量的步骤。
如果数组包含多个与target相同的相同值,则binarysearch
返回的索引是索引最低的匹配条目的索引。
答案 2 :(得分:1)
使用<stdlib.h>
库提供的bsearch
函数可以使这个问题更容易。
这样的事情:
#include <stdio.h>
#include <stdlib.h>
int cmpfunc(const void * a, const void * b);
int
main(void) {
int array[] = {1, 2, 3, 4, 5, 6};
size_t n = sizeof(array)/sizeof(*array);
int *item;
int key = 15;
item = bsearch(&key, array, n, sizeof(*array), cmpfunc);
if (item != NULL) {
printf("Found item = %d\n", *item);
} else {
printf("Item = %d could not be found\n", key);
}
return 0;
}
int
cmpfunc(const void * a, const void * b) {
return (*(int*)a > *(int*)b) - (*(int*)a < *(int*)b);
}
如果您不想使用bsearch
,那么此方法也可以:
#include <stdio.h>
#include <stdlib.h>
#define BSFOUND 1
#define BS_NOT_FOUND 0
int cmpfunc(const void * a, const void * b);
int binary_search(int A[], int lo, int hi, int *key, int *locn);
int
main(void) {
int array[] = {1, 2, 3, 4, 5, 6};
size_t n = sizeof(array)/sizeof(*array);
int key = 4, locn;
if ((binary_search(array, 0, n, &key, &locn)) == BSFOUND) {
printf("Found item = %d\n", array[locn]);
} else {
printf("Item = %d cound not be found\n", key);
}
return 0;
}
int
binary_search(int A[], int lo, int hi, int *key, int *locn) {
int mid, outcome;
if (lo >= hi) {
return BS_NOT_FOUND;
}
mid = lo + (hi - lo) / 2;
if ((outcome = cmpfunc(key, A+mid)) < 0) {
return binary_search(A, lo, mid, key, locn);
} else if(outcome > 0) {
return binary_search(A, mid+1, hi, key, locn);
} else {
*locn = mid;
return BSFOUND;
}
}
int
cmpfunc(const void * a, const void * b) {
return (*(int*)a > *(int*)b) - (*(int*)a < *(int*)b);
}