Binary Search in C using recursion - c

The program crashes in finding a number which is not available in the array.The code works perfectly when i search for elements which are available in the array.Help much appreciated.
#include<stdio.h>
int binarySearch(int a[],int s,int key)
{
int middle;
if(s!=1)
middle=s/2;
if(a[middle]==key)
return 1;
else if(key<a[middle])
binarySearch(a,middle,key);
else if(key>a[middle])
binarySearch(&a[middle],middle,key);
else
return 0;
}
void main()
{
int i;
int a[]={1,2,3,4,6,9,10,11};
for (i =0;i<8;i++)
printf("%i ",a[i]);
if(binarySearch(a,8,5))
printf("\nFound");
else
printf("\nNot Found");
}

Change
if(s!=1)
middle=s/2;
if(a[middle]==key)
return 1;
else if(key<a[middle])binarySearch(a,middle,key);
else if(key>a[middle])binarySearch(&a[middle],middle,key);
to
if (s != 1){
middle = s / 2;
if (a[middle] == key)
return 1;
else if (key<a[middle])binarySearch(a, middle, key);
else if (key>a[middle])binarySearch(&a[middle], middle, key);
}
The variable middle is initialized only if s!=1.
I have run this code and got the value Not Found for input 5.
If you are running your code in release mode, try building it in debug mode and run step by step you will see what happens when middle is used directly without assigning it a specific value. This is harmful.
Hope this helps.

The code if(key<a[middle])binarySearch(a,middle,key); does not return anything.
Try if(key<a[middle]) return binarySearch(a,middle,key);
This may still not work as you intend it to, but at least you will get past the major, immediately visible, cause of runaway recursion.

Because there is no case if the s == 1. "Middle" is not initialized and a[middle] is potential crash, or it will just go infinite.

A few notes:
Every branch of a recursive function should return something. You'll need to modify your recursive calls to return the call
Change
binarySearch(a, middle, key)
to
return binarySearch(a, middle, key)
Also, make sure middle is computed properly. You don't properly initialize it in the situation where s == 1. You'll want this to start at 0 most likely.

Related

C-How to increase in recursion?An example of recursively judging prime numbers

I'm a programming rookie who has not yet started. I just learned recursion and there are some problems with the use of recursion. There is a homework is judge prime numbers :using int prime(int x); and return boolean value.
Initially I found that because the variable is initialized and assigned inside the function,the program can't achieve self-increment. Because every time it enters a new level of recursion, the variable will be reassigned. Even if you write a variable auto-increment statement, it will only auto-increase the variables stored in the current recursive stack. Once the variable enters a new recursive level, the variable is only initialized according to the definition and cannot be continuously auto-incremented.
The solution to the failure is as follows:
#include <math.h>
#define false 0
#define true 1
int prime(int x){
double high=sqrt(x);
int low=2;
if((x%low==0 && x!=2) || low>high){
return false;
}
else if(x<2){
return false;
}
else{
return true;
}
low++;
return prime(x);
}
When asking questions, I found a successful solution:
#include <math.h>
#define false 0
#define true 1
int prime(int x){
double high=mysqrt(x);
static int low=2;
if((x%low==0 && x!=2)||low>high){
return false;
}
else if(x<2){
return false;
}
else{
return true;
}
low++;
return prime(x);
}
But I can't understand why using static to modify the variable can make the variable correctly increment when entering a new layer of recursion instead of executing the previous int low=2;
Ask the master to solve the confusion for me, what happened to the two in the memory space?
In addition, there seems to be another solution, which seems to be to set a flag variable, but I did not understand it. Can someone provide other solutions?
In a nutshell, ordinary variables (int low;) get created for each function call independently, while static (static int low = 2;) are created once and shared between all the functions.
However, static is not the best approach to use in such cases, because different function calls may need to have different values of high/low.
Instead, you may add explicit parameters to the function, something like this (the algorithm is wrong, but it's the general principle):
int prime(int x) { return prime_impl(x, 2, sqrt(x)); }
int prime_impl(int x, int low, double high) {
if(x<2) {
return false;
}
else if((x%low==0 && x!=2)||low>high) {
return true;
}
else {
return prime_impl(x, low+1, high);
}
}

Stack implemented as an array defaulting first value to 0 in C

I have an assignment where I am supposed to use this very very simple (or so I thought) stack that my teacher wrote in C, just using an array. From this, I have to implement reverse polish notation from a text file.
In order for me to implement this, I am using a stack, pushing values on until I hit an operation. I then do the operation and push the result back onto the stack until the user hits p to print the value.
The problem is, for some reason, my professor's implementation of the stack array defaults the first (index 0) value to 0. Printing the stack without pushing anything onto it should result in null but it appears the output is 0.
Here is my professor's implementation of the stack:
#define STK_MAX 1024
#define ELE int
ELE _stk[STK_MAX];
int _top = 0;
void stk_error(char *msg)
{
fprintf(stderr, "Error: %s\n", msg);
exit(-1);
}
int stk_is_full()
{
return _top >= STK_MAX;
}
int stk_is_empty()
{
return _top == 0;
}
void stk_push(ELE v)
{
if ( stk_is_full() )
stk_error("Push on full stack");
_stk[_top++] = v;
}
ELE stk_pop()
{
if ( stk_is_empty() )
stk_error("pop on empty stack");
return _stk[--_top];
}
void print()
{
for(int i = 0; i <= _top; ++i)
printf("%d ", _stk[i]);
printf("\n");
}
I realize that the print statement will print a value that has not been pushed yet, but the problem is, is that when I don't print it, it still ends up there and it ends up screwing up my rpn calculator. Here is what happens when I do this:
// input
stk_push(2);
print();
stk_push(4);
print();
// output
2 0
2 4 0
How do I get rid of the 0 value that is affecting my calculator? Doing stk_pop() after the pushing the first value onto the stack didn't seem to work, and checking that top == 0, then directly inserting that element before incrementing _top didn't work.
When you are printing, loop from 0 to (_top - 1), since your top most element is actually at _top - 1. Hint : Look at your pop/push method.
void print()
{
for(int i = 0; i < _top; ++i)
printf("%d ", _stk[i]);
printf("\n");
}
"The problem is, is that the rpn calculator relies on the TOS being accurate. When I do pop() though, it will pop 0 and not the real TOS."
Sounds like a problem with your calculator implementation. You assumed the top of the stack would be null, but that's not the case for your professors stack implementation. Simply a invalid assumption.
Instead he's provided a stk_is_empty() method to help determine when you've pop everything.
If you need to pop all elements, you'll need to break on the condition of stk_is_empty().
stk_push(2);
stk_push(4);
while( stk_is_empty() == false)
{
stk_pop();
}
Of course in reality you'd be setting the pop return to a variable and doing something with it. The key point is leveraging stk_is_empty().
I haven't written C++ in few years so hopefully I didn't make a minor syntax error.

Implementation of recursive Mergesort

I made a recursive merge sort code,but it is not working,can anyone tell me where am I going wrong in the code.
void mergesort(int A[],int start,int end)
{
int B[(end-start)/2],C[(end-start)/2],i,j,k,flag=0;
if(start==end)
return;
else
{
mergesort(A,start,(start+end)/2);
mergesort(A,(start+end)/2+1,end);
}
for(i=start;i<(start+end)/2;i++)
B[i]=A[i];
for(i=(start+end)/2+1;i<end;i++)
C[i]=A[i];
for(i=start,j=start,k=(start+end)/2+1;i<end;i++)
{
if(j==(start+end)/2)
{
while(k!=end)
A[i]=C[k++];
flag=1;
}
if(k==end)
{
while(j!=(start+end)/2)
A[i]=B[j++];
flag=1;
}
if(flag)
break;
if(A[j]>C[k])
A[i]=C[k++];
else
A[i]=B[j++];
}
return;
}
In the first part of the code i am trying to divide the array into 2 sub arrays and if i am left with only one element, I start merging and reach the top to obtain the sorted array.
One of the end points in your recursive calls is wrong. You need to decide if end is included in the sub-array or one past the end of the array. The code appears to want to exclude end, however your recursive calls look like this:
mergesort(A,start,(start+end)/2); // should be (start+end)/2+1 if end is excluded
mergesort(A,(start+end)/2+1,end);
A killer problem is that the loop
for(i=(start+end)/2+1;i<end;i++)
C[i]=A[i];
immediately writes beyond the array. All bets are off, but in any case C doesn't contain what you expect it to.

Control may reach end of non-void function C

I am not able to compile my code, I am getting error: control may reach the end of a non-void function
/**
* Returns true if value is in array of n values, else false.
*/
bool search(int value, int values[], int n)
{
//Binary search algorithm
int first = 0;
int last = n-1;
int middle = (first+last)/2;
if (n<1)
return false;
else
{
while (first <= last)
{
if (values[middle]==value)
return true;
else if(values[middle]<value)
first=middle+1;
else if (values[middle]>value)
{
last=middle-1;
}
middle=(first+last)/2;
}
}
if (first>last)
return false;
}
Can anyone look through my code and help me figure out where the issue is? I am struggling to see it myself! From my point of view, this function returns true or false
Your return type of bool means that your function is always expected to return a boolean value before it exits, no matter which path of execution it takes. As it stands now, it appears on inspection that you can "fall through" the last if and never hit a return statement. To verify otherwise would require stepping through your logic in a way the compiler cannot reasonably be expected to do. At the end simply change to say:
if (first>last) {
return false;
} else {
return true;
}
Or more concisely:
return (first > last) ? false : true;
In your code it's not possible for the function to fall off the end.
However, the compiler is not required to accurately diagnose whether a function can get to the end or not. In general, to do so would require solving the halting problem.
Instead, as a practical measure, your compiler is doing some basic checks and warning because it sees the if ( first > last ) return false;, it didn't do enough code analysis to determine that this branch can never be reached unless first > last.
To suppress this warning you could just remove the line if ( first > last ). BTW this is a warning, not an error; so it should not prevent your compilation.

Deciding the base condition in backtracking recursive algorithm

I was solving the N Queen problem where we need to place 4 queens on a 4 X 4 chess board such that no two queens can attack each other. I tried this earlier but my approach did not involve backtracking, so I was trying again. The code snippets are
int size=4,i,j;
int arr[4][4];
int lastjindex[4]; // to store the last location which we may need to backtrack
void placeQueen(int i,int j)
{
int availableornot=0;
for(j=0;j<size;j++)
{
if(isAvailable(i,j)==1)
{
availableornot=1;
break;
}
}
if(availableornot==1)
{
arr[i][j]=1;
lastjindex[i]=j;
if((i+1)!=size)
{
placeQueen(i+1,0);
}
}
else
{
// no column was availabe so we backtrack
arr[i-1][lastjindex[i-1]]=0;
placeQueen(i-1,lastjindex[i-1]+1);
}
}
The isAvailable() method returns 1 if arr[i][j] is not under attack, else it returns 0.
int isAvailable(int i,int j)
{
int m,n,flag=0;
for(m=0;m<i;m++)
{
for(n=0;n<size;n++)
{
int k=abs(i-m);
int l=abs(j-n);
if(arr[m][j]==0 || arr[k][l]==0)
{
flag=1;
break;
// means that spot is available
}
}
}
return flag;
}
I call the above method from main as
placeQueen(0,0);
My program compiles successfully but it prints all zeroes.
Is there any problem with my recursion? Please help me correct my code as I am trying to learn how to implement backtracking algorithms!
Also I am not able to decide the base condition to end recursion. How do I choose it here?
There's no printing in the code you posted. If you print after you have backtracked, you will be back to the initial condition of no queens on the board. Print after you have placed N queens, which is also the end condition for recursion. If you only want to print one solution, exit after printing, or set a flag that tells the caller that you're done so you pop all the way out. If you print all solutions, that will include reflections and rotations. You can eliminate one axis of reflection by only placing queens within size/2 in the first level.
Also, there are some clear logic errors in you code, such as
arr[m][j]==0 || arr[k][l]==0
A queen can only be placed if it isn't attacked on the file and it isn't attacked along a diagonal. Use a debugger or add printfs to your code to trace where it is trying to place queens -- that will help you figure out what it is doing wrong.
And aside from being wrong, your isAvailable is very inefficient. You want to know if the [i,j] square is attacked along the file or a diagonal. For that you should have a single loop over the rows of the previous queens for (m = 0; m < i; m++), but you only need three tests, not a loop, to check the file and the diagonals. As soon as you find any previous queen on a file or diagonal, you're done, and the square isn't available -- return false. (And ignore people who tell you that a function should only have one return -- they are wrong, and there are lengthly discussions here at SO and even scientific studies of error rates in code that bear this out.) Only if no previous queen is found is the square available.
Your placeQueen is also wrong. For each available square on a row, you need to place a queen and then recurse, but you're just finding the first available square. And backtracking is achieved simply by removing the queen you placed and then returning ... the previous level of placeQueen will try the next available spot.
Again, trace the code to see what it's doing. And, even more importantly, think through the logic of what is needed. Write your algorithm in words, convince yourself that it will solve the problem, then write the code to carry out the algorithm.
#include <stdio.h>
#define SIZE 4
int size=SIZE;
int arr[SIZE][SIZE] = { 0 };
void placeQueen(int col){
int r,c;
if(col == size){//all queen put!
//print out
for(r = 0;r<size;++r){
for(c = 0;c<size;++c)
printf("%d", arr[c][r]);
printf("\n");
}
printf("\n");
return ;
}
for(r=0;r<size;++r){
if(isAvailable(col, r)==1){
arr[col][r]=1;
placeQueen(col+1);
arr[col][r]=0;//reset
}
}
}
int isAvailable(int col,int row){
int c;
for(c=0;c<col;++c){
int d = col - c;
if(arr[c][row]==1)
return 0;//queen already same row
if(row+d < size && arr[c][row+d]==1 || row-d >= 0 && arr[c][row-d]==1)
return 0;//queen already same slanting position
}
return 1;
}
int main(){
placeQueen(0);
return 0;
}

Resources