Binary search via recursion. C
Good time of day! Does not find an element in the array. Can you tell me what's wrong? I myself assume that it's all about return 0, but if I change it to the value 1, then it finds elements that are not in the array. In general, I broke my head already how to correctly exit the recursion, if of course this is the whole point.
int main(int argc, char* argv[])
{
int der[] = {1, 2,5 ,3 ,7, 5, 7, 10, 56, 10, 4};
int s = (sizeof(der)/sizeof(der[0]));
sort(der, s);
for(int i = 0; i< s; i++)
printf("%d ", der[i]);
printf("\n");
if (bisearch(10, der, 0, s))
printf("\n10 is found\n");
return 1;
}
int bisearch(int val, int* array, int min, int max)
{
int midpoint = (min+max)/2;
if (max<min)
return -1;
if (array[midpoint] > val)
bisearch(val, array, min, midpoint-1);
else if (array[midpoint] < val)
bisearch(val, array, midpoint+1, max);
else
return 1;
return 0;
}
Thanks for attention.
4 answers
Ready-made code under the items 1 and 2. Don't take it at face value : test it. :)
Your code is very difficult to understand, and there are many flaws in it. Now we will try to fix this and solve your problem along with it, but before that we will agree that you have correctly implemented the function sort
:)
Let's start with bisearch
.
Since the function is recursive, it would be great to return something under your conditions + we will remove the "scary" else if
- constructions, even though they are and were conceived to reveal the fact of successful completion of the search:
if ( max < min ) return -1;
if ( array[midpoint] > val ) return bisearch( val, array, min, midpoint - 1 );
if ( array[midpoint] < val ) return bisearch( val, array, midpoint + 1, max );
Now you need to add the key comparison condition :
if ( val == array[midpoint] ) return 0;
If, in the end, the value is found, then we "spin" the stack and return to main
with zero, otherwise, sooner or later, the condition max < min
will be met, which will indicate a failed search.
I think the function might look like this:
1
int bisearch(int val, int* array, size_t min, size_t max)
{
if ( max < min ) return -1;
size_t midpoint = ( min + max ) / 2;
if ( array[midpoint] > val ) return bisearch(val, array, min, midpoint - 1 );
if ( array[midpoint] < val ) return bisearch(val, array, midpoint + 1, max);
if ( val == array[midpoint] ) return 0;
return -1;
}
Now let's discuss main
.
The first thing that "caught" my eye is the following :
if (bisearch(10, der, 0, s))
What prevents you from comparing the return value of a function with zero? This is where you 'got caught' :)
if (x)
- this is the equivalent of if (x != 0)
, so your program will only start when the search fails, which we don't need, so you can write either
if (0 == bisearch(10, der, 0, s))
, or
if (!bisearch(10, der, 0, s))
Alternatively, the function can be formatted as:
2
int main(int argc, char* argv[])
{
int der[] = {1, 2, 5, 3, 7, 5, 7, 10, 56, 10, 4}; /*1 2 3 4 5 5 7 7 10 10 56*/
size_t s = ( sizeof(der) / sizeof(der[0]) );
sort( der, s );
if ( 0 == bisearch(10, der, 0U, s) ) printf("10 was found\n");
else printf("10 wasn't found\n");
return 0;
}
A little 'sideline' :
For bisearch
:
- The declaration
midpoint
is in this in place, so as not to be executed once again (unless, of course, you use the ansi standard when compiling); - The restriction in the form of
size_t
was made for your own safety, because neithermin
normax
(and thereforemidpoint
) can be meaningfully negative values; - Still, in a good way, you need to add a check for the emptiness of the array, but you can already handle this yourself. Just don't add it inside a recursive function : do it outside of it, for example, by wrapping it in another one the function, and then with a valid array, checking for emptiness will be an unnecessary action. In the same place, make a check to see if the unsigned numbers for
min
andmax
were actually entered. (we take the desired value, array, int-s, check the array, checkmin
andmax
, and if successful, let it into the function)
For main
:
size_t
I pushed it in for two reasons, one of which is described above, and, secondly, there will be no unnecessary type conversion (sizeof(der)/sizeof(der[0])
will give just size_t
that is an unsigned integer data type).
UPD: replace better everywhere unsigned int
on size_t
in your work, for this is an unsigned and platform-independent type + division sizeof
's, in fact, give size_t
. Here I have already corrected
When calling, you must correctly specify the last index of the range
The results of recursive calls should be used, as already mentioned
int main()
{ int der[] = {1, 2, 3 ,3 ,5, 5, 7, 5, 10, 10, 56};
int s = (sizeof(der)/sizeof(der[0]));
for(int i = 0; i< s; i++)
printf("%d ", der[i]);
for (int v = 9; v<11; v++)
{
if (bisearch(v, der, 0, s - 1))
printf("\nvalue %d is found\n", v);
else
printf("\nvalue %d is Not found\n", v);
}
return 1;
}
int bisearch(int val, int* array, int min, int max)
{
if (max<min)
return 0;
int midpoint = (min+max)/2;
if (array[midpoint] > val)
return bisearch(val, array, min, midpoint-1);
else if (array[midpoint] < val)
return bisearch(val, array, midpoint+1, max);
else
return 1;
}
1 2 3 3 5 5 7 5 10 10 56
value 9 is Not found
value 10 is found
I found one of the solutions. However, intuitively it seems to me that this code is too ugly, if anyone has a more beautiful solution, I will be only happy to see it. Here is the solution to my problem after a couple of days of puzzles: Declaring the global variable int r = 0; And in the bisearch function we write:
int bisearch(int val, int* array, int min, int max)
{
int midpoint = (min+max)/2;
if(array[midpoint] > val) {
if(max >= min) bisearch(val, array, min, midpoint - 1);
else r = 0; }
if(array[midpoint] < val) {
if(max >= min) bisearch(val, array, midpoint + 1, max);
else r = 0; }
if(array[midpoint] == val) r = 1;
if(max<min) r = 0;
return r;
}
It seems to me that in such problems it is better to return the index of the found element (it will be in the range from 0
to n
(where n
is the size of the array)).
If the key is not found, we return -1
.
Then, offhand (I didn't check it on my computer):
int bisearch (int k, int *a, int left, int n) {
if (n <= left)
return -1;
int mid = (left + n) / 2;
if (a[mid] == k)
return mid;
if (a[mid] < k)
return bisearch(k, a, mid + 1, n);
return bisearch(k, a, left, mid);
}