[英]Binary search implementation in C
第一次在这里发布。 我最近实现了二进制搜索,但有时我的输出将返回一个巨大的负数。 现在我的第一个想法是,我正在打印一个数字,我的指针指向一个随机的内存位置。 有人可以帮助我解决逻辑问题,以及如何改善我的代码吗?
#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);
}
}
对于初学者,您可以在只有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 )
您调用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
),并查看编译器产生的所有有用的诊断消息。
这是修改后的版本:
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
,该函数对所有目标值执行相同数量的步骤。
如果数组包含等于目标的多个相同值,则binarysearch
返回的索引是具有最低索引的匹配条目的索引。
通过使用<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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.