What is wrong with my binary search implementation? - c

#include <stdio.h>
int bsearch(int a[], int n, int lo, int hi) {
int mid;
mid = (hi + lo) / 2;
if(a[mid] == n)
return 1;
else if(a[mid] > n)
bsearch(a, n, lo, mid);
else
bsearch(a, n, mid, hi);
return 0;
}
int main(void) {
int n, a[7] = {2, 4, 5, 67, 70, 80, 81};
int hi = 6, lo = 0, j;
scanf("%d", &n);
j = bsearch(a, n, lo, hi);
if(j)
printf("Found");
else
printf("Not Found");
return 0;
}
input : 5 output: Not Found
Can anyone tell me why I'm getting this result?

You need to fix several big issues to make it work (see details in following code comments).
Change your binary search function to the following:
int bsearch(int a[], int n, int lo, int hi)
{
// add base case
if (high < low)
return 0; // not found
int mid;
mid=(hi+lo)/2;
if(a[mid]==n)
return 1;
else if(a[mid]>n)
return bsearch(a,n,lo,mid-1); // add return
else
return bsearch(a,n,mid+1,hi); // add return
}
P.S.: And based on your usage in the main() body, you actually only need to return 0/1 to indicate contains the value or not. I will suggest you to use bool return type to make it more clear.

Add "return" to the recursive calls, e.g.:
return bsearch(a,n,lo,mid);
Otherwise, when you return 1 in bsearch, it does not get returned all the way to main.
That will make it work for 5. You have other bugs, so try with many values and use an IDE and/or printf to see what's happening. Good luck and have fun!

That's because the return 0; statement in your bsearch function is always executed because you are simply discarding the values returned by the recursive calls. In a recursive function, you must first decide the base case. Here in your bsearch, the base case should be
low <= hi
This is the first condition which must be true to start the search for the sought value. If this condition is not fulfilled, then you must return false, i.e., 0.
Next, a value returning function call is an expression, i.e., it evaluates to a value. When you simply call the function and do nothing with the result, you will always fall down to the last return statement in your function. Here I list some points in comments alongside the statements in your bsearch function.
int bsearch(int a[], int n, int lo, int hi) {
// first check for the base condition here
// if(hi < low) return 0;
int mid;
// can cause integer overflow. should be
// mid = lo + (hi - lo) / 2;
mid = (hi + lo) / 2;
if(a[mid] == n)
return 1;
else if(a[mid] > n)
// you are doing nothing with the value returned
// think of the function call as an expression
// return the value of the expression
// should be
// return besearch(a, n, lo, hi);
bsearch(a, n, lo, mid);
else
// same follows here
// should be
// return bsearch(a, n, mid, hi);
bsearch(a, n, mid, hi);
// finally you will always return 0 because this statement is always executed
// all cases have been taken care of.
// no return statement needed here
return 0;
}

Related

Recursive function to find the number of continuous sub-sequences in an array having a sum in the given range

I wrote this code. The idea is to split the array into 2 parts and find the number of sub-sequences that satisfy the given condition. Now there can also be a sub-sequence with elements from both subarrays. Hence I wrote the crossub function.
The subarray function is going on an infinite loop (It's continuously printing the debug statement "BBBBBBBB"). I spent some time on this, but I guess I need some help.
Note : New to programming. I know the code is a piece of shit. But I am getting better.
#include <stdio.h>
#include <stdlib.h>
void crossub(int * A,int mid, int start, int end, int lbound, int ubound, int **k)
{
int leftsum = A[mid];
int crossum;
int rightsum = 0;
int i;int j;
for(i = mid -1; i>=0; i--)
{
leftsum = leftsum + A[i];
for(j = mid +1; j <=end; j++)
{
rightsum = rightsum + A[j];
crossum = rightsum + leftsum;
if (lbound <= crossum && crossum <= ubound) k++;
else if(crossum > ubound) break;
}
}
return;
}
void subarray(int * A, int start, int end, int lbound, int ubound, int *count)
{
printf("BBBBBBBBB ");
if(start == end)
{
if(lbound <= A[start] && A[start] <= ubound)
{
count++;
}
return;
}
int **k; int mid;
k = &count;
while (start <= end)
{
mid = (start + end)/2;
subarray(A, start, mid,lbound,ubound,count);
subarray(A, mid +1, end,lbound,ubound,count);
crossub(A, mid, start, end, lbound,ubound,k);
}
return;
}
int numRange(int* A, int n, int lbound, int ubound)
{
// printf("AAAAAAAAAAA");
int p = 0;
int *count;
count = &p;
subarray(A, 0, n-1,lbound,ubound, count);
return p;
}
int main()
{
int A[] = {30, 5,1,0,2, 15,20,25};
int n = sizeof(A)/sizeof(A[0]);
printf("%d", n);
int lbound = 6; int ubound = 8;
int k = numRange(A, n,lbound, ubound);
printf("%d ", k);
return 0;
}
I'm not sure that recursion is relevant here. The way here is to always have a range and check its sum. Initial range should contain the single first item (range can be defined via start and end indexes), initial value for sum should be equal to value of . Further processing is:
If your sum is less than you're looking for, expand range incrementing its end index and adding value of new item to current value of range's sum;
If your sum is greater than you're looking for, reduce range incrementing its start index and substracting value of excluded item from range's sum;
If your sum is OK for you, return it.
Dealing with ranges:
If your sum is less than you're looking for, and you're unable to increment its end index because it points to the last item in array you're looking through, you may return a result that says no range is satisfying your requirements;
If your sum is greater than you're looking for, and you're unable to increment its start index because it points to the last item in array, you may also return same "no answer" result.
I'm sure there is no efficient way of dealing with ranges using "divide and conquer" strategy.
Regarding your infinite loop, the issue is in the subarray function, namely:
while (start <= end)
{
mid = (start + end)/2;
subarray(A, start, mid,lbound,ubound,count);
subarray(A, mid +1, end,lbound,ubound,count);
crossub(A, mid, start, end, lbound,ubound,k);
}
As you can see, this is going to keep going forever, because you never change the values of start/end, so you keep calling subarray on the same section.
Although, as already stated by the first answer, this might not be the best way, but you can remove the while loop and see if it works, even if it might not be the best solution.

C - Recursion array checking

i would like to ask about the array recursion in C, Let say i have an array in float
float arr[] = {12.5, 5.5, 6.0, 18.0};
i want to count the number which is greater than 10, so the result should be 2. However, below is what i did
int cntArray(float arr[], int size)
{
int number = 0;
if((cntArray(&arr[1], size - 1))>=5)
number++;
return number;
}
int main()
{
float arr[] = {12.5, 5.5, 6.0, 18.0};
int result;
result = cntArray(arr, 4);
printf("The result is : %d", result);
}
But it returns 0 as result, any solutions for it? Thanks
Another example:
int cntArray(float arr[], int size) {
if (!size) return 0;
return (arr[0] > 10.0 ? 1 : 0) + cntArray(&arr[1], size - 1);
}
Edit #1 (in reply to comment):
This simply evaluate through a ternary operator (?:) if the first index of arr[] is greater than 10.0. If true, 1 will be the lvalue, otherwise will be 0. The lvalue of cntArray(&arr[1], size - 1) (which will process the next element on the array after decrementing size and if size is different than 0, which in this case will immediately return 0) will be added to the lvalue of the ternary operator. Applying this recurring logic, the aftermath will be the number of elements in the array that are greater than 10.0.
Your cntArray() function lacks a recursion base case, and also seems to hardcode the wrong value (5 instead of 10).
It should be something like:
int cntArray(const float *arr, size_t size)
{
if(size > 0)
{
/* Count the first element, then recurse. */
const int count = arr[0] >= 10.f;
return count + cntArray(arr + 1, size -1);
}
return 0;
}
Your logic is severely flawed: You don't actually check if a value in the array is larger than 10. you also always return number which will always be zero meaning the condition will always be false.
int cntArray(float arr[], int size){
int number = 0;
if((number = cntArray(&arr[1], size - 1))>=5)
number++;
return number;
}
You maybe want to change 5 to 10.
int cntArray(float arr[], int size) {
int number = 0;
if (size > 0) number = cntArray(&arr[1], size - 1);
if (arr[0] > 10) number += 1;
return number;
}
I'm not sure what does this portion of your code does.
if((cntArray(&arr[1], size - 1))>=5)
number++;
I would something like this instead:
int cntArray(float arr[], int index, int size){
if (index == size) return 0; // base case
int rest = cntArray(arr, index + 1, size); // how many elements are greater
// then 10 in rest of the array
if (arr[index] > 10)
return rest + 1;
else
return rest;
}
And call it in the main like this:
cntArray(arr, 0, 4);

Recursive unsorted array search algorithm in C?

Let's say we want to write a function in C that finds a specified target value in an unsorted array of ints. In general, this is simple and runs in O(n) time:
int search(int *data, int len, int target)
{
int i;
for(i = 0; i < len; i++)
if(data[i]==target) return i;
return -1;
}
Let's say we're being masochistic and want to approach this with a divide and conquer algorithm instead. We'll run into trouble on the recursive part because we can't exclude half the array each time, like we can with binary search:
int search(int *data, int start, int stop, int target)
{
// Base case: we've divided the array into two size subarray
if(stop==start+1)
{
if(data[start]==target) return start;
if(data[stop]==target) return stop;
return -1;
}
/* The recursion part is tricky.
We *need* to parse both halves of the array, because we can't safely
exclude any part of the array; it's not sorted, so we can't predict
which half it's going to be in.*/
else
{
/** This obviously doesn't work. */
int mid = (stop-start)/2;
return search(data, start, mid, target);
return search(data, mid+1, stop, target);
}
}
Is there any way to make this work?
NOTE: This is not asking people to do my homework for me, as some of you may think when reading this question. It is, however, inspired by curiosity after I encountered this problem when trying to solve a question in an assignment that I've submitted earlier this week.
How about changing the recursive call to:
else
{
int mid = (stop-start)/2;
int x = search(data, start, mid, target);
if (x == -1)
return search(data, mid+1, stop, target);
else
return x;
}
I think the answer to your question is no, you can't achieve any benefit using the binary split approach if the data is unsorted.
If the data are not sorted you can not use binary search.
But divide and conquer can be used with the following recursive logic (linear search):
int search(int *data, int len, int target)
{
if (len == 0)
return -1;
else if (data[0] == target);
return 0;
else
return 1 + search(++data, len-1, target);
}

Recursion How to find minimum value of a array

`/* finding the minimum number of a array */
#include<stdio.h>
int minimum(int n, int a[n], int x);
int main(void)
{
int a[5] = { 5, 4, 3, 4, 5 };
printf("%d \n", minimum(4, a, 0));
return 0;
}
int minimum(int n, int a[n], int x)
{
int minima;
if (x >= n)
return a[x];
else
minima = minimum(n, a, x + 1);
if (a[x] > minima)
return minima;
}
`
Hey I read few recursion sources in stackoverflaw. Also found same kind problem using JAVA. Can you please explain me how this code works.Or is this a good coding. I make it my self to learn recursion and it is working.Please explain.
There are two problems in your code:
The termination happens too late: you return a[x] when x==n - that's one element past the end.
There is a missing return when a[x] > minima is false: your function ends without returning a[x].
To fix these two problems, change the check of the termination condition, and add the missing return:
if(x >= n-1) return a[n-1];
// You do not need an else after a return
minima = minimum(n,a,x+1);
if (a[x] > minima) return minima;
return a[x];
Note that you can save one parameter by starting the search at the end of the array and going backward until you reach index zero.

divide and conque binary search in C

I'm trying to make a divide and conquer version of binary search, but one that divides the array to two subarrays and search similar to merging in merge sort, the reason I want to do that becuase I want to use it in cilk, but I have to make it that way.
Here is the code I wrote, which seems to have something wrong with it as its returning -1 to valid key values.
#include <stdio.h>
#include "BinarySearch.h"
int main () {
int a[] = {0,1,2,3,4,5,6,7,8,9};
int index = binarySearch(a, 0, 9, 7);
printf("%i", index);
return 0;
}
int binarySearch (int* A, int first, int last, int key) {
if (last < first)
return -1;
else {
int mid = (last + first) / 2;
if (A[mid] == key)
return mid;
int x, y;
x = binarySearch(A, first, mid - 1, key);
y = binarySearch(A, mid + 1, last, key);
if (x == -1 && y == -1)
return -1;
else if (x == -1 && y != -1)
return y;
else
return x;
}
}
It's simple, 99 doesn't exist in your array. The result is correct. You probably just messed up the parameters - the first one is the array, the next two represent the range of the search, the fourth one is what you're looking for. A correct call would be:
int index = binarySearch(A, 0, 10, 4);
Also, this
int* A = &a[0];
is useless, you can simply use a as arrays decay to pointers:
int index = binarySearch(a, 0, 7, 99); // a instead of A
Also - a binary search takes into account the fact that the array is sorted. If your key is lower than the middle value, why bother searching to the right - it's guaranteed you won't find it there.
What you're doing is O(n), as opposed to a O(log(n)) binary search solution.
For any one still looking for solutions, I found this made by ankzcode.
It finds the minimum value in an array without linear search, using divide and conquer.
#include <stdio.h>
int findMin(int a[], int l,int h)
{
int pivot = (l + h) / 2;
int minl=-1, minh = -1;
if ( (pivot - l ) > 1)
{
minl = findMin(a, l, pivot);
}
else
{
minl = (a[l] > a[pivot])?a[pivot]:a[l];
}
if ( (h - pivot ) > 1)
{
minh = findMin(a, pivot, h);
}
else
{
minh = (a[l] > a[pivot])?a[pivot]:a[l];
}
return (minl>minh)?minh:minl;
}
int main()
{
int a[]={5,2,9,10,3};
printf("%d\n",findMin(a, 0, 5));
return 0;
}
you gave the key 99,which is not in array,So its obvious the code return -1.

Resources