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.

Author: Олег Хасьянов, 2018-04-14

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:

  1. 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);
  2. The restriction in the form of size_t was made for your own safety, because neither min nor max (and therefore midpoint) can be meaningfully negative values;
  3. 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 and max were actually entered. (we take the desired value, array, int-s, check the array, check min and max, and if successful, let it into the function)

For main:

size_tI 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 inton 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

 1
Author: Gromov Anton, 2018-04-16 21:21:07

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
 1
Author: MBo, 2018-04-15 04:16:28

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;
}
 0
Author: Олег Хасьянов, 2018-04-15 19:18:23

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);
}
 0
Author: avp, 2018-04-15 22:06:38