我刚刚学习了C的第一步(我以前用python编写代码),因此我在语法和二进制搜索实现方面都面临着巨大的困难。 (我是编程新手。)
这是我的代码:
#include <stdlib.h>
#include <stdio.h>
#define size 1000
int binary_search(int array[size], int givenNumber) {
do {
int start = 0;
int end = size;
int middle = start + end / 2;
int left = size - 1;
int right = size + 1;
if (array[middle] == givenNumber) {
printf("location: %d, number: %i", middle, givenNumber);
return middle;
} else if (array[left] < givenNumber) {
int start = 0;
int end = array[left];
int middle = start + end / 2;
return middle;
} else if (array[right] > middle) {
int start = array[right];
int end = size;
int middle = start + end / 2;
return middle;
} else {
return -1;
break;
}
}
} while (int middle != givenNumber)
int main() {
int sorted_array[size];
for (int i = 0; i < size; i++) {
sorted_array[i] = i;
}
return binary_search(sorted_array, 349);
}
我的问题是:
1-编译时,错误是类似于“在未定义块”中”的情况下发生的”
我不知道为什么值没有从do块传递到while块。请注意,我在每个if / else-if块中添加了“ return middle”,因为我认为它可能有帮助。
2-我什至不确定我的这种二进制搜索的自己实现是否正确。我已经看过如何实现它,但是我发现它几乎无法阅读语法,这只是给个提示。
更新:
我已经根据用户在下面的答案中给出的注释重构了整个代码,而且,我的算法正在运行,现在可以在任何给定的数组中找到任何数字,但是我无法找出一种方法来判断是否数组没有那个givenNumber
,因为它最终会卡住。
这是输入/输出:
int array[size] = {1,2,3,4,5,6,8,9,10,11,14,24,53,100};
功能:binary_search(array, 24);
输出:Location: 11, Number: 24
这很好,但是,如果我输入了数组中不存在的数字,则循环会不断搜索(陷入递归状态)
here's the updated code:
#include <stdio.h>
#include <stdlib.h>
#define size 14
int start = 0;
int end = size -1;
int middle;
int left;
int right;
int binary_search(int array[size], int givenValue)
{
middle = (start + end) / 2;
printf("\nstart: %d \nend: %d \nmiddle: %d \n\n",start, end, middle);
do
{
if (start > end)
{
printf("item isn't found");
break;
return -1;
}
middle = (start+end)/2;
left = middle -1;
right = middle +1;
if (array[middle] == givenValue)
{
printf("Location: %d, Number: %d", middle, givenValue);
return middle;
break;
}
if(array[middle] > givenValue)
{
end = right;
return binary_search(array, givenValue);
}
if(array[middle] < givenValue)
{
start = left;
return binary_search(array, givenValue);
}
}
while (start <= end);
}
int main(void)
{
int array[size] = {1,2,3,4,5,6,8,9,10,11,14,24,53,100};
return binary_search(array, 24);
}
我的条件是,如果start
大于end
,则该项目不存在,并且根本不起作用,因为left/right
一直停留在相同的值(运行代码以了解我的意思)
如何解决此问题?
答案 0 :(得分:1)
有很多问题:
if/else
的所有部分都有一个return
left
和right
应该分别从0
和size - 1
开始start
既是数组索引又是数组 value )首先,我建议删除所有遮盖外部作用域的变量的“子作用域”变量声明(即,将所有变量置于最外部作用域)。
执行此操作,直到您对这些声明更满意为止。详细了解以下内容之间的区别:
int x;
int x = 5;
x = 5;
我已经注释了您的原始功能,创建了测试/诊断功能,并创建了通过诊断测试的重构功能:
#include <stdio.h>
#define size 1000
int
binary_fixed(int *array, int givenNumber)
{
int left;
int right;
int middle;
int curval;
int retindex = -1;
left = 0;
right = size - 1;
while (left <= right) {
middle = (left + right) / 2;
curval = array[middle];
if (curval == givenNumber) {
retindex = middle;
break;
}
if (curval > givenNumber)
right = middle - 1;
else
left = middle + 1;
}
return retindex;
}
int
binary_search(int *array, int givenNumber)
{
int middle;
// NOTE/BUG: this does _not_ iterate
// NOTE/BUG: _massive_ amount of "shadowing" of variables
// NOTE/BUG: size is _invariant_ so left/right are _always_ set to the
// same thing
// NOTE/BUG: left and right should start at 0 and size - 1 respectively
// NOTE/BUG: variables are used _inconsistently_ (e.g. start is both
// an array index and an array _value_)
do {
int start = 0;
int end = size;
int middle = start + end / 2;
int left = size - 1;
int right = size + 1;
if (array[middle] == givenNumber) {
printf("location: %d, number: %i\n", middle, givenNumber);
return middle;
}
else if (array[left] < givenNumber) {
int start = 0;
int end = array[left];
int middle = start + end / 2;
return middle;
}
else if (array[right] > middle) {
int start = array[right];
int end = size;
int middle = start + end / 2;
return middle;
}
else {
return -1;
}
} while (middle != givenNumber);
printf("BADRETURN givenNumber=%d\n", givenNumber);
}
int sorted_array[size];
void
test(const char *who,int (*fnc)(int *,int))
{
int i;
int r;
for (i = 0; i < size; i++) {
r = fnc(sorted_array, i);
if (r != i) {
printf("ERROR -- EXPECTED: %d ACTUAL: %d (from %s)\n", i, r, who);
// break;
}
}
}
int
main()
{
for (int i = 0; i < size; i++) {
sorted_array[i] = i;
}
//test("ORIGINAL",binary_search);
test("FIXED",binary_fixed);
return 0;
}
更新:
由于您来自python
,因此以下几点可能有助于您的理解。
数组作为 pointers 传递给函数,因此在函数参数列表中,int *array
是等效的。进行int array[size]
是一项高级技术。现在避免它。在C语言中,您无法像在python中那样执行array.count
。因此,暂时将计数作为附加参数传递。
指针是python所没有的,因此您必须学习如何使用它们。一旦掌握了这些技巧,它们就会非常强大,并且可以使代码运行得很快。
在C语言(以及大多数语言 python [和php]除外)中,默认范围是 global 。与python相反。在python中,除非您指定global x
,否则x
是函数专有的。在其他语言中,要使x
在函数本地,必须在函数范围内声明它。
在C语言中,必须在所有位置声明所有变量 :全局范围,函数范围[或函数内的块范围]或作为争论。并且,每个声明必须指定一个显式类型。没有与JavaScript的var x
声明等效的声明。之后,x
可以是字符串或值,具体取决于您将其设置为什么(例如x = 23
或x = "abc"
)
在C语言中,x
必须具有以下类型:int x;
或double x;
或int *x;
或char *x
。
这是带注释的修改后代码:
#include <stdio.h>
#include <stdlib.h>
// NOTE: this is hardwired
#define size 14
// NOTE: this is _global_ scope -- while not absolutely wrong, using function
// scope below is faster/better and provides better isolation -- this doesn't
// scale as well
int start = 0;
int end = size - 1;
int middle;
int left;
int right;
// NOTE: in C, using "int *array" is equivalent [and in many cases preferred]
// NOTE: the array count should be passed in as a separate argument
int
binary_search(int array[size], int givenValue)
{
// NOTE: this is _function_ scope
// NOTE: this calc of middle is extraneous because it is recalculated
// below
middle = (start + end) / 2;
printf("\nstart: %d \nend: %d \nmiddle: %d \n\n", start, end, middle);
// NOTE/BUG: this function combines _both_ a loop implementation and a
// recursive implementation -- we have to pick one or the other as trying
// to do both messes things us -- the recursion is broken [see below]
// NOTE: this loop checks start vs end _twice_ in the loop -- it only
// needs to check in one place -- convert this to "while (start <= end) {"
// instead of a "do {...} while (whatever);" loop [which is usually not
// as good]
do {
if (start > end) {
printf("item isn't found");
break;
// NOTE/BUG: this return will _never_ be executed because we
// break out of the loop and what is worse we'll return an
// unknown/undefined value because
return -1;
}
middle = (start + end) / 2;
// NOTE/BUG: these are reversed
left = middle - 1;
right = middle + 1;
if (array[middle] == givenValue) {
printf("Location: %d, Number: %d", middle, givenValue);
return middle;
break;
}
// NOTE/BUG: these recursive calls do nothing because they do _not_
// further limit the scope and cause infinite recursion -- to make
// a recursive version work, start/end would need to be arguments:
// return binary_search(array,givenValue,start,end)
// and we shouldn't loop -- the recursive calls just aren't needed
// NOTE/BUG: the tests here are broken -- they are the reverse of
// the correct ones
if (array[middle] > givenValue) {
end = right;
return binary_search(array, givenValue);
}
if (array[middle] < givenValue) {
start = left;
return binary_search(array, givenValue);
}
// NOTE/BUG: this extra test is extraneous and would be done too late
// if the array size was zero -- a case that isn't handled here
} while (start <= end);
// NOTE/BUG: when we break out of the loop, we need to return _some_ value
// here -- this would be flagged by the compiler using the -Wall option
}
int
main(void)
{
int array[size] = { 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 14, 24, 53, 100 };
// NOTE/BUG: the return value from main can only handle numbers 0-255
// better to print the return value
return binary_search(array, 24);
}
这是您修改后的代码的有效版本。
循环现在是一个简单的while
。该函数采用 separate 计数参数。它循环而不是递归。反向if
逻辑已得到修复。再次,添加了诊断测试。
#include <stdio.h>
#include <stdlib.h>
int
binary_search(int *array, int size, int givenValue)
{
// NOTE: this is _function_ scope
int start = 0;
int end = size - 1;
int middle;
int left;
int right;
int match_index;
// assume failure
match_index = -1;
// NOTE: this calc of middle is extraneous because it is recalculated
// below
middle = (start + end) / 2;
printf("\nstart: %d \nend: %d \nmiddle: %d \n\n", start, end, middle);
while (start <= end) {
middle = (start + end) / 2;
left = middle - 1;
right = middle + 1;
if (array[middle] == givenValue) {
printf("Location: %d, Number: %d\n", middle, givenValue);
match_index = middle;
break;
}
if (array[middle] > givenValue) {
end = left;
}
if (array[middle] < givenValue) {
start = right;
}
}
if (match_index < 0)
printf("match not found -- givenValue=%d\n",givenValue);
return match_index;
}
int
main(void)
{
int array[] = { 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 14, 24, 53, 100 };
int count = sizeof(array) / sizeof(array[0]);
int curidx;
int valwant;
int match;
printf("%d\n",binary_search(array, count, 24));
// run diagnostic on all values
for (curidx = 0; curidx < count; ++curidx) {
// get value to search for
valwant = array[curidx];
match = binary_search(array,count,valwant);
if (match != curidx) {
printf("fault: curidx=%d valwant=%d match=%d\n",
curidx,valwant,match);
}
}
// test lower range failure
valwant = array[0] - 1;
match = binary_search(array,count,valwant);
if (match >= 0)
printf("fault: valwant=%d match=%d\n",valwant,match);
// test upper range failure
valwant = array[count - 1] + 1;
match = binary_search(array,count,valwant);
if (match >= 0)
printf("fault: valwant=%d match=%d\n",valwant,match);
return 0;
}
答案 1 :(得分:0)
典型的二进制搜索实现将循环或递归直到找到数字。天真的递归代码是这样的:
#include <stdio.h>
#define size 1000
int binary_search(int array[size], int givenNumber, int start, int end) {
int middle;
middle = (start + end) / 2;
if (start > end)
return -1;
if (array[middle] == givenNumber) {
printf("location: %d, number: %i", middle, givenNumber);
return middle;
} else if (array[middle] < givenNumber) {
return binary_search(array, givenNumber, middle + 1, end);
} else { // if (array[middle] > givenNumber)
return binary_search(array, givenNumber, start, middle - 1);
}
}
int main() {
int sorted_array[size];
for (int i = 0; i < size; i++) {
sorted_array[i] = i * 2;
}
if (binary_search(sorted_array, 349, 0, size - 1) < 0) {
printf("value not found\n");
}
if (binary_search(sorted_array, 34, 0, size - 1) < 0) {
printf("value not found\n");
}
}
在递归中,我们每次都根据已排序的数组和givenNumber
中提供的输入,使用新的开始和结束范围来调用binary_search。
答案 2 :(得分:-2)
尝试一下:
#include <stdlib.h>
#include <stdio.h>
#define size 1000
int binary_search(int array[size], int givenNumber) {
int middle;
do {
int start = 0;
int end = size;
int middle = start + end / 2;
int left = size - 1;
int right = size + 1;
if (array[middle] == givenNumber) {
printf("location: %d, number: %i", middle, givenNumber);
return middle;
} else if (array[left] < givenNumber) {
int start = 0;
int end = array[left];
int middle = start + end / 2;
return middle;
} else if (array[right] > middle) {
int start = array[right];
int end = size;
int middle = start + end / 2;
return middle;
} else {
return -1;
}
} while (middle != givenNumber);
}
int main() {
int sorted_array[size];
for (int i = 0; i < size; i++) {
sorted_array[i] = i;
}
return binary_search(sorted_array, 349);
}