Programs works when compiled in clang, but not gcc in Windows - c

Have this search function that works when I compile in Linux using clang, but on Windows using MinGW gcc, I do not get the right answer. Included in the code is an array where clearly the value I'm looking for is in the array. So output should be "Found it!". Anyone know what might the issue be with windows?
#include <stdio.h>
#include <stdbool.h>
bool re_search(int value, int values[], int first, int last);
int main(void)
{
int value = 12;
int values[] = {2,4,5,12,23,34};
int n = 6;
if (re_search(value, values, 0, n-1))
{
printf("Found it!\n");
}
else
{
printf("Did not find it\n");
}
return 0;
}
bool re_search(int value, int values[], int first, int last)
{
last = last-1;
int middle = (first+last)/2;
while (first <= last)
{
if (value == values[middle])
{
return true;
}
else if (value > values[middle])
{
first = middle + 1;
middle = (first + last) / 2;
return re_search(value, &values[middle], first, last);
}
else
{
last = middle - 1;
middle = (first + last) / 2;
return re_search(value, &values[first], first, last);
}
}
return false;
}

Your recursive call return re_search(value, &values[middle], first, last); is passing in both an array which starts at the midpoint, and a new value of first which counts from the whole array's start. You want to do one or the other; not both.
That is, you first call with:
values == {2,4,5,12,23,34}
first == 0
last == 5
In the first iteration, you try middle == 2, so values[middle] is 5, which is less than 12. You then recurse with
values == {12,23,34}
first == 3
last == 5
And - oh dear! - even values[first] is now out of range. Chances are, on Linux you got (un)lucky and hit the value you were searching for past the end of the array.

does not matter whether GCC and windows.
bool re_search(int value, int values[], int first, int last){
if (first <= last){
int middle = (first+last)/2;
if (value == values[middle]){
return true;
} else if (value > values[middle]){
return re_search(value, values, middle + 1, last);
} else {
return re_search(value, values, first, middle - 1);
}
}
return false;
}
bool re_search(int value, int values[], int first, int last){
while (first <= last){
int middle = (first+last)/2;
if (value == values[middle]){
return true;
} else if (value > values[middle]){
first = middle + 1;
} else {
last = middle - 1;
}
}
return false;
}

Related

Binary search in C always returns false, even when value is contained in sorted array [duplicate]

This question already has an answer here:
C recursive function won't return true
(1 answer)
Closed 5 years ago.
New to programming. Trying to implement binary search in C but unfortunately it isn't working properly. my function always returns false even when the value is in the array. New to programming. please help.
Function takes following inputs:
"value" - integer value to be found in array.
"values" - the sorted array.
"n" - number of integers in array.
bool search(int value, int values[], int n)
{
// recursive implementation of binary search
if (n % 2 == 0)
{
search_even(value, values, n);
}
else
{
search_odd(value, values, n);
}
return false;
}
bool search_even(int value, int values[], int n)
{
// binary search
if (n <= 0)
{
return false;
}
// check middle of array
else if (value == values[n/2])
{
return true;
}
// search left half of sorted array
else if (value < values[n/2])
{
int less_than_arr[n/2];
for (int i = 0; i < n/2; i++)
{
less_than_arr[i] = values[i];
}
search(value, less_than_arr, n/2);
}
// search right half of sorted array
else if (value > values[n/2])
{
int more_than_arr[(n/2) - 1];
for (int i = 0; i < (n/2) - 1; i++)
{
more_than_arr[i] = values[i + 1 + n/2];
}
search(value, more_than_arr, n/2);
}
return false;
}
bool search_odd(int value, int values[], int n)
{
// binary search
if (n <= 0)
{
return false;
}
// check middle of array
else if (value == values[n/2])
{
return true;
}
// search left half of sorted array
else if (value < values[n/2])
{
int less_than_arr[n/2];
for (int i = 0; i < n/2; i++)
{
less_than_arr[i] = values[i];
}
search(value, less_than_arr, n/2);
}
// search right half of sorted array
else if (value > values[n/2])
{
int more_than_arr[n/2];
for (int i = 0; i < n/2; i++)
{
more_than_arr[i] = values[i + 1 + n/2];
}
search(value, more_than_arr, n/2);
}
return false;
}
You (recursively) call search functions but never return the value computed by the calls. Look at:
bool search(int value, int values[], int n)
{
// recursive implementation of binary search
if (n % 2 == 0)
{
search_even(value, values, n);
}
else
{
search_odd(value, values, n);
}
return false;
}
This function always return false.
You need at least to replace search*(...) with return search*(...), so that value determined at the leaves of the calls is transmitted back to the original (first) call.
Jean-Baptiste has already pointed out the obvious error in your function, but there are more issues:
You create local copies of the subarrays to search. This is not necessary and will make binary search slower than linear search.
Copying data is usually only necessary when you want to modify it, but retain the original state. Your search function only inspects the data. Strictly speaking, your argument int values[] should probably be const int values[] to reflect that fact.
In C, you must pass the pointer to the first element and the length of an array. Arrays decay into pointers to their first element, so the following:
int val[4] = {2, 4, 7, 12};
search(3, val, 4);
already does that.
But here's a useful idiom: If you want to pass in the subarray that starts at position k, use:
search(3, val + k, 4 - k);
More generally, you can pass the array slice [lo, hi), where lo is the zero-based inclusive lower bound and hi is the exclusive upper bound as:
search(3, val + lo, hi - lo);
In the called function, the indices will then be [0, hi - lo); the original array offset is lost.
Further, you don't need to distinguish the two cases of odd n and even n if you calculate the size of the right-hand array as difference between the original size minus the size of the left-hand array plus one:
mid == n / 2
left = [0, mid)
right = [mid + 1, n)
With this, your recursive binary search function will become:
bool search(int value, const int values[], int n)
{
if (n == 0) return false;
if (value < values[n / 2]) {
return search(value, values, n / 2);
}
if (value > values[n / 2]) {
return search(value, values + n / 2 + 1, n - n / 2 - 1);
}
return true;
}

Search of an element on a unsorted array recursively

This is an exercise that I took from an exam. It asks to write a function that receives an unsorted array v[] and a number X and the function will return 1 if X is present in v[] or 0 if X is not present in v[]. The function must be recursive and must work in this manner:
1. Compares X with the element in the middle of v[];
2. The function calls itself (recursion!!) on upper half and on the lower half of v[];
So I've written this function:
int occ(int *p,int dim,int X){
int pivot,a,b;
pivot=(dim)/2;
if(dim==0) //end of array
return 0;
if(*(p+pivot)==X) //verify if the element in the middle is X
return 1;
a=occ(p,pivot,X); //call on lower half
b=occ(p+pivot,dim-pivot,X); //call on upper half
if(a+b>=1) //if X is found return 1 else 0
return 1;
else{
return 0;
}
}
I tried to simulated it on a sheet of paper and it seems to be correct (Even though I'm not sure) then I've written it on ideone and it can't run the program!
Here is the link: https://ideone.com/ZwwpAW
Is my code actually wrong (probably!) or is it a problem related to ideone. Can someone help me? Thank you in advance!!!
The problem is with b=occ(p+pivot,dim-pivot,X); when pivot is 0. i.e. when dim is 1.
the next function call becomes occ(p,1,X); This again leads to the call occ(p,1,X); in a continuous loop.
It can be fixed by adding a condition to the call, as shown in the code below.
int occ(int *p,int dim,int X){
int pivot,a=0,b=0;
pivot=(dim)/2;
if(dim==0){
return 0;
}
if(*(p+pivot)==X)
return 1;
if (pivot != 0)
{
a=occ(p,pivot,X);
b=occ(p+pivot,dim-pivot,X);
}
if(a+b>=1)
return 1;
else{
return 0;
}
}
The implemetation is causing a stack overflow, as the recursion does not terminate if the input contains only one element. This can be fixed as follows.
int occ(int *p, int dim, int X)
{
int pivot, a, b;
pivot = (dim) / 2;
if (dim == 0)
{
return 0;
}
if (*(p + pivot) == X)
{
return 1;
}
if (dim == 1)
{
if (*(p + pivot) == X)
{
return 1;
}
else
{
return 0;
}
}
a = occ(p, pivot, X);
b = occ(p + pivot, dim - pivot, X);
if (a + b >= 1)
{
return 1;
}
else
{
return 0;
}
}
It's enought to change only this one line in the source code to avoid the endless loop with occ(p,1,X):
//if(dim==0) //end of array
if (pivot == 0)
return 0;

Infinite recursion: binary search & asserts

I'm writing an implementation of binary search in C and I'm getting infinite recursion for no apparent (to me) reason. Heres my code:
/*Orchestrate program*/
int main(int argc, char* argv){
int array[] = {1,2,3,3,3,6,7,8,9,9,20,21,22};
int length = 13;
int key = 23;
binary_search(key, array, 0, length - 1);
return 0;
}
int binary_search(int key, int array[], int first_index, int last_index){
int middle;
middle = (first_index + last_index)/2;
if (first_index == last_index){
if (array[middle] == key){
printf("%d has been found at position %d\n", key, middle+1);
}
printf("item not found");
}
else if (key > array[middle]){
binary_search(key, array, middle, last_index);
}
else if (key < array[middle]){
binary_search(key, array, first_index, middle);
}
}
Based on the value of my key in main, I guess the problem lies in the first else if, but I'm not sure why. If I were to remove the first_index == last_index line, the algorithm works fine but only when the item is in the array. If the item isn't in the array, I naturally get infinite recursion.
Also, I tried to fix this problem by removing the first_index == last_index line and placing a return -1; at the end of the function, but I get the same problem that I am getting now.
EDIT:
Putting together pieces of advice I received from a few different users, I came to the following solution (fixed off by one errors and un-nested decisions):
void binary_search(int key, int array[], int first_index, int last_index){
int middle;
middle = (first_index + last_index)/2;
if (array[middle] == key){
printf("%d has been found at position %d\n", key, middle+1);
}
if (first_index == last_index){
printf("item not found");
}
else if (key > array[middle]){
binary_search(key, array, middle + 1, last_index);
}
else if (key < array[middle]){
binary_search(key, array, first_index, middle - 1);
}
}
I have a follow-up question: Could there have been a way to use asserts to assist me in finding this solution myself? (I'm just learning about asserts so I'm wondering where I can apply them)
You search ever smaller ranges of a sorted array. The bounadries of your array are inclusive.
The base case of your recursion is: If the range is empty, the key is not found. Or, in code:
if (first_index > last_index){
printf("Not found\n");
}
You should calculate and compare the middle element of your range only after you have established that the range is not empty. In that case, you have three outcomes:
The middle element is the key: bingo!
The middle element is smaller than the key: Search the right half of the array and exclude the middle element, which we have already checked.
The middle element is larger than the key: Ditto, but with the left half.
Putting this all together:
void binary_search(int key, int array[], int first_index, int last_index)
{
if (first_index > last_index){
printf("Not found\n");
} else {
int middle = (first_index + last_index) / 2;
if (array[middle] == key) printf("%d at index %d\n", key, middle);
if (key > array[middle]){
binary_search(key, array, middle + 1, last_index);
} else {
binary_search(key, array, first_index, middle - 1);
}
}
}
This function still has two things that nag me:
A function that prints the index is of little practical use. The printing should be done by the client code, i.e. by the code that calls the function. Return the found index or a special value for "not found" instead.
The range has inclusive bounds. That's not very C-like. In C, a range is usually described by an inclusive lower and an exclusive upper bound. That's how array indices and for loops work. Following this convention means that your client code doesn't have to do the awkward length - 1 calculation.
So here's a variant that returns the index or -1 if the key is not in the array:
int binary_search1(int key, int array[], int first_index, int last_index)
{
if (first_index < last_index){
int middle = (first_index + last_index) / 2;
if (array[middle] == key) return middle;
if (key > array[middle]){
return binary_search1(key, array, middle + 1, last_index);
} else {
return binary_search1(key, array, first_index, middle);
}
}
return -1;
}
and test it with:
int main()
{
int arr[6] = {3, 4, 6, 8, 12, 13};
int i;
for (i = 0; i < 20; i++) {
int ix = binary_search(i, arr, 0, 6);
if (ix < 0) {
printf("%d not found.\n", i);
} else {
printf("%d at index %d.\n", i, ix);
}
}
return 0;
}
Note that your original array has duplicate entries. This is okay, but you will get the index of any of the duplicate values, not necessarily the first one.
Your function should look like this:
void binary_search(int key, int array[], int first_index, int last_index){
int middle;
middle = (first_index + last_index)/2;
if (array[middle] == key){
printf("%d has been found at position %d\n", key, middle+1);
}
else if (first_index == last_index) {
printf("item not found");
}
else if (key > array[middle]){
binary_search(key, array, middle + 1, last_index);
}
else {
//assert (key < array[middle]); // feel free to uncomment this one and include the assert library if you want
binary_search(key, array, first_index, middle - 1);
}
}
In other words, increment or decrement middle appropriately in the recursive call.
This is important, because, for example, when you reduce to size 2 for your search and middle is your first element, then effectively you are not changing the dimension of the array in the recursive calls.
I also changed your function to void since you are not returning anything.

Why is this binary search giving me an infinite loop?

I am trying to do a binary search. I really can't think of why I am getting an infinite loop? Is is because I ignored the null value somewhere? The value, values[], and n are being provided by a different file, and they are written by someone else, and are, for the purposes of this question, perfectly coded.
bool search(int value, int values[], int n)
{
int upper_bound = n - 1;
int lower_bound = 0;
int middle = (upper_bound + lower_bound) / 2;
while (lower_bound <= upper_bound)
{
if (values[middle] == value)
{
return true;
}
else if (values[middle] > value)
{
upper_bound = middle - 1;
}
else if (values[middle] < value)
{
lower_bound = middle + 1;
}
else
{
return false;
}
}
return false;
}
Thank you all so much.
You need to calculate the value of middle inside the while loop:
while (lower_bound <= upper_bound){
int middle = (upper_bound + lower_bound) / 2;
...
}
As the value of middle should change every time you are changing the value of either lower_bound or upper_bound.
the middle value is fixed. It is not changing as the values of upper_bound and lower_bound are changing.

find an element in infinite sorted array

I got this as an interview question ...
infinite array which is sorted and from some position (we dont know the position) only special symbol '$' will be there we need to find an element in that array ...
i gave a solution like get the first occurrance of $ and then do binary search on the previous part from $
to find the first occurance of $ i gave solution like increment in window size if (i,2i)
the code i gave is
#include<stdio.h>
int first(int *arr,int start,int end,int index)
{
int mid=(start+end)/2;
if((mid==start||arr[mid-1] != '$') && arr[mid]=='$')
return mid;
if(arr[mid]=='$')
return first(arr,start,mid-1,index);
else
{
if(arr[end] =='$')
return first(arr,mid+1,end,index);
else
return first(arr,end+1,(1<<index),index+1);
}
}
int binsearch(int *arr,int end ,int n)
{
int low,high,mid;
high=end-1;
low=0;
while(low<= high)
{
mid=(low+high)/2;
if(n<arr[mid])
high=mid-1;
else if (n >arr[mid])
low=mid+1;
else
return mid;
}
return -1;
}
int main()
{
int arr[20]={1,2,3,4,5,6,7,8,9,10,'$','$','$','$','$','$','$','$','$','$'};
int i =first(arr,0,2,2);
printf("first occurance of $ is %d\n",i);
int n=20;//n is required element to be found
if(i==0||arr[i-1]<n)
printf(" element %d not found",n);
else{
int p=binsearch(arr,i,n);
if(p != -1)
printf("element %d is found at index %d",n,p);
else
printf(" element %d not found",n);
}
return 0;
}
Is there any better way to do the above problem ??
And also i wanted to know to find the first occurance of $ why should we move the window only in powers of 2 why not 3 like (i,3i)
Can someone pls through some light on the recurrance relation ..pls help..
Seems like a fine way to do it to me. As a small optimization, you can stop your first routine when you reach any number bigger than the one you're searching for (not just $).
Growing the window by powers of 2 means you'll find the end in log_2(n) iterations. Growing by factors of 3 means you'll find it in log_3(n) iterations, which is smaller. But not asymptotically smaller, as O(log_2(n)) == O(log_3(n)). And your binary search is going to take log_2(n) steps anyway, so making the first part faster is not going to help your big-O running time.
The efficient part of first function in iterative format would be
private int searchNum(int[] arr, int num, int start, int end) {
int index = 0;
boolean found = false;
for (int i = 0; i < arr.length; i = 1 << index) {
if (start + i < arr.length) {
if (arr[start] <= num && arr[start + i] >= num) {
found = true;
return bsearch(arr, num, start, start + i);
} else {
start = start + i;
}
} else {
return bsearch(arr, num, start, arr.length - 1);
}
}
return 0;
}
this wont return you first occurance but instead try to find number directly as in your case you are missing probability that number itself could be found even before finding the $ symbol. So worst case complexity is O(logn)..
and best case would be (1)
after that you pass this to
private int bsearch(int[] array, int search, int first, int last) {
int middle = (first + last) / 2;
while (first <= last) {
if (array[middle] < search)
first = middle + 1;
else if (array[middle] == search) {
System.out.println(search + " found at location "
+ (middle + 1) + ".");
return middle;
} else
last = middle - 1;
middle = (first + last) / 2;
}
if (first > last)
System.out.println(search + " is not present in the list.\n");
return -1;
}
calling function
if ((pos = searchNum(arr, num, 0, 2)) != -1) {
System.out.println("found # " + pos);
} else {
System.out.println("not found");
}
This is python solution.
arr = [3,5,7,9,10,90,100,130,140,160,170,171,172,173,174,175,176]
elm = 171
k = 0
while (True):
try:
i = (1 << k) - 1 # same as 2**k - 1 # eg 0,1,3,7,15
# print k
if(arr[i] == elm):
print "found at " + str(i)
exit()
elif( arr[i] > elm):
break
except Exception as e:
break
k = k+1
begin = 2**(k-1) # go back to previous power of 2
end = 2**k -1
# Binary search
while (begin <= end):
mid = begin + (end-begin)/2
try:
if(arr[mid] == elm):
print "found at " + str(mid)
exit()
elif(arr[mid] > elm):
end = mid-1
else:
begin = mid+1
except Exception as e:
# Exception can occur if you are trying to access min element and that is not available. hence set end to mid-1
end = mid-1
print "Element not found"

Resources