So I have an integer array called OriginalArray that contains a bunch of integers. I want to be able to make it so that the user can input any value and if it's in the array, provide the location of that value and if it appears multiple times in the array, have it provide all the locations and otherwise have it provide an error message.
I WANT to use the technique of binary search and/or linear search and/or interpolation search to be able to achieve this, recursive or iteratively I don't mind.
Sorry about the little information to go off trying to tackle a hard task for me and I'm not the most experienced :)
static object BinarySearchRecursive(int[] inputArray, int key, int min, int max)
{
if (min > max)
{
return "Nil";
}
else
{
int mid = (min + max) / 2;
if (key == inputArray[mid])
{
return ++mid;
}
else if (key < inputArray[mid])
{
return BinarySearchRecursive(inputArray, key, min, mid - 1);
}
else
{
return BinarySearchRecursive(inputArray, key, mid + 1, max);
}
}
}
Related
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;
}
I am trying to get this divide and conquer to work, but the compiler is giving me:
control may reach end of non-void function
I have read through similar scenarios, and understand the error implies the program might run forever without a return. I have reviewed some scenarios, which were resolved by using "else" instead of "if else" (as you should to begin with). However, that didn't help.
I am aware that using a do while loop and return in this scenario is redundant, I was fiddling with it in hopes to trick the compiler.
Where is the error?
bool search(int value, int values[], int n)
{
int sorted = 0;
int min = 0;
int max = n;
int mid = n / 2;
do
{
//mid is value
if (value == values[mid])
{
printf("value found!");
sorted = 1;
return 1;
}
//search right
else if (values[mid] < value)
{
min = mid + 1;
mid = (max - mid) / 2 ;
}
//search left
else if (values[mid] > value)
{
max = mid - 1;
mid = (max - mid) / 2;
}
// DNE
else
{
printf("value not found");
sorted = 1;
return 0;
}
}
while(sorted == 0);
}
Every branch of code should have a return if function suppose to return a value.
In your case after while you have to put a return. How ever, Your logic is also slightly wrong. In your code there is not any need of sorted variable and the terminating condition is also wrong as well as the way of calculating mid is also wrong. Don't worry here is your updated code:
bool search(int value, int values[], int n)
{
//int sorted = 0;
int min = 0;
int max = n;
int mid = n / 2; // S1
do
{
//mid=(max+min)/2; // S2
//mid is value
if (value == values[mid])
{
//printf("value found!");
//sorted = 1;
return 1;
}
//search right
else if (values[mid] < value)
{
min = mid + 1;
mid = (max + min) / 2 ; // S3
}
//search left
else if (values[mid] > value)
{
max = mid - 1;
mid = (max + min) / 2; //S4
}
// DNE
else
{
//printf("value not found");
//sorted = 1;
return 0;
}
}
while(min!=max);
return 0;
}
So if your function is returning 1 it mean value found otherwise value doesn't found.
you also can comment S1, S3 and S4 and uncomment S2 for minimum line of code.
And the way of finding mid will be mid=(max+min)/2.
Ignoring other problems in your code (the loop will never terminate under certain conditions although I didn't study it too closely), let's just look at why the compiler complains, because it's quite interesting.
Your compiler complains about that you don't have a return at the end of the function (pretty much what we can read from the warning message) after the while loop. You loop runs:
while(sorted == 0);
And everywhere you change sorted, you do this:
sorted = 1;
return X;
So it is pretty obvious to you and me that the while condition will always be true and you won't fall out of the while loop and need a return after it. Every time you make the while condition not true, you also return immediately. But the compiler doesn't know that. It probably could figure it out with a little bit more effort, but it can never be written to know in all cases and you wouldn't accept a compiler that slow anyway. The problem of fully analyzing any arbitrary bit of code to know what you and I know (that we'll never fall out of the loop) is pretty much the halting problem (if you don't know what it is, you should, google it).
In situations like this we need to work with the compiler and help it understand. I would add a return sorted; at the end of the function, change the loop condition to while (1) and replace sorted = 1; return X; with sorted = X; break; to break out of the loop and have the function return from just one place (it is much easier to read functions that have just one or very few return statements). Or just remove the sorted variable, do the returns properly and loop forever.
I think your compiler doesn't like your understanding of Control Flow. As a beginner this is one of the most cringing problems.
Your error explained: Control may reach end of non-void function. Whenever you branch your code (i.e. use loops, if, switch etc) you have to explicitly write what each branch will do. So in your code, you must return a bool by any means necessary.
I am unable to discern where the error might be, it would be great if someone can show me.
See we have two return x; statements, one in if block and second in else block. Now we think that control should return from either of these blocks conveniently. But your compiler is "concerned" about what will happen if control didn't enter either of these blocks and loop ends. Moreover, what will happen after the loop, how can control ever return to main? Hence the error.
Now what we can do to fix the problem is add a return 0; just before the end of the function. That will surely make the error disappear. However, there are better ways to solve this problem:
bool search(int value, int values[], int n) {
int min = 0, max = n;
int mid = n / 2;
bool is_found = 0;
while (min != max) {
if (value == values[mid]) {
is_found = 1;
break;
}
else if (value > values[mid]) {
min = mid + 1;
mid = (max + min) / 2;
}
else if (value < values[mid]) {
max = mid - 1;
mid = (max + min) / 2;
}
else break;
}
return is_found;
}
I am trying to implement binary search on an array. I tried to get rid of this error that I get while compiling but could not. This is the function that I made for binary search:
bool BinSearch(int key, int Array[], int min, int max)
{
if (max < min)
return false;
else
{
int mid = (min + max)/2 ;
if (key > Array[mid])
BinSearch(key, Array, mid+1, max);
else if (key < Array[mid])
BinSearch(key, Array, min, mid-1);
else
return true;
}
}
Your main mistake is you are missing a return statement for your recursive calls to BinSearch. To make this explanation easier to understand I have added some parenthesis in your code to make everything more explicit. Note the code below is the same as your code, just with some (redundant) parentheses and more appropriate indentation.
Now lets assume we have a code path where max < min is false followed by key > Array[mid] being true. Therefore we have the following program execution, annotated in the code:
bool BinSearch(int key, int Array[], int min, int max)
{
if (max < min) { // Step 1, false
return false;
}
else {
// Step 2, start the else block
int mid = (min + max)/2 ;
if (key > Array[mid]) { // Step 3, true
BinSearch(key, Array, mid+1, max); // Step 4 call BinSearch
// Step 5, finished with call to BinSearch
}
else if (key < Array[mid]) {
BinSearch(key, Array, min, mid-1);
}
else {
return true;
}
// Step 6, Done with else block
}
// Step 7, Done with function, no return statement
}
A similar thing would happen if key > Array[mid] is false and key < Array[mid] is true. This should make it clear why your compiler correctly thinks there are code paths that do not have a return. The solution, as previously pointed out in the comments is to do return BinSearch(...).
So I'm trying to write a binary search function that uses recursion and keep getting a segmentation fault if I go past two values in the array. I've looked at a bunch of other code doing what I'm trying to do and as far as I can see they appear to do the same thing. I'm a very novice programmer and feel like I'm banging my head against the wall with this. Any help would be appreciated.
int search(int value, int array[], int start, int end)
{
//Define new variables for use in recursion
int sizeArray, middleOfArray;
//Get size of array
sizeArray = (end - start) + 1;
//Find midpoint of array based off size
middleOfArray = sizeArray / 2;
//Base Case 1, if array unscannable, return -1
if (start > end) {
return -1;
}
//Recursive Cases
else
{
//If midpoint in array is > target value,
//Search from beginning of array->one below midpoint
if (array[middleOfArray] > value){
return search(value, array, start, middleOfArray - 1);
}
//If midpoint in array is < target value,
//search from one above midpoint->end of array
else if (array[middleOfArray] < value) {
return search(value, array, middleOfArray + 1, end);
}
//If none of the other cases are satisfied, value=midpoint
//Return midpoint
else {
return middleOfArray;
}
}
}
The problem is here:
middleOfArray = sizeArray / 2;
It should be like this:
middleOfArray = start + sizeArray / 2;
You can also get middle of array like this. Which will save you from one extra variable sizeofArray.
middleofArray=(start+end)/2;
Given an array first increasing then decreases at a point and again increases?
find a given number N exists in array or not.
Example 1:
Array = 7,8,3,4,5,6
number = 7
answer should be true.
Example 2:
Array = 3,4,6,7,8,5,9,10,11
number = 10
answer should be true.
All numbers are unique.
can be done with linear search in O(N),
Can we do that lesser than that. (more efficient)
In general, no. Suppose we have the following, in Python:
l = range(n)
and we randomly stick a -1 in there:
if random.random() < 0.5:
l[random.randrange(len(l))] = -1
The only way to tell if there's a -1 in the list is to look through every element until you find it or don't. The structure of the list ends up not helping at all.
a linear search is as good as you will get for a non-linear array
Optimized Algorithm : -
Use binary search for key on array if found then return true.
If not found use linear search
Time Complexity : -
Unsuccessful search : Here we would do both linear search and binary search hence O(N) for large inputs
Successful search : Here is where our optimization work to some extent. There is on average 1/2 chance that you end up searching in right part of array in binary search . Hence atleast 2 times faster search on average.
Java Code for optimized algorithm with results :-
public class UniqueSearch {
static int linearCount = 0;
public static boolean binSearch(int[] arr,int key,int high,int low) {
while(high>=low) {
int mid = (low+high)/2;
if(arr[mid]==key)
return(true);
if(arr[mid]<key) {
low = mid+1;
}
else {
high = mid-1;
}
}
return(false);
}
public static boolean linearSearch(int arr[],int key) {
//System.out.println("linearSearch");
linearCount++;
for(int i=0;i<arr.length;i++) {
if(key==arr[i]) {
return(true);
}
}
return(false);
}
public static boolean optSearch2(int arr[],int key) {
boolean flag = binSearch(arr, key, arr.length-1,0);
if(!flag) {
return(linearSearch(arr, key));
}
return(flag);
}
public static void main(String[] args) {
int n = 100000;
int[] arr = new int[n];
int error = 0;
Random r = new Random();
long start = System.currentTimeMillis();
int totalCount = 0;
for(int i=0;i<1000;i++) {
error = r.nextInt(arr.length-1);
for(int k=0;k<error;k++) {
arr[k] = 2*k+1;
}
for(int k=error;k<arr.length;k++) {
arr[k] = 2*(k-error);
}
for(int j=0;j<1000;j++) {
int x = r.nextInt(arr.length);
totalCount++;
boolean flag = optSearch2(arr,arr[x]);
if(!flag) {
System.out.println("error");
}
}
}
System.out.println("linearSearch Percentage: "+linearCount*100/totalCount);
System.out.println(System.currentTimeMillis()-start);
}
}
Results :
Run the code and wait for 6-7 secs and you will see that for random successfull search on random array of the special kind as your problem requires linear search about 30% times and rest can be done using binary search in O(logn)
Can be done in O(logN) time complexity
Find maximum element in array (call this pivot). Here's the pseudo code
public static int getMax(int start, int end){
if(start==end)
return start;
if(start>end)
return -1;
int mid = start + (end-start)/2;
// check if maxima
if(arr[mid-1]<arr[mid] && arr[mid]>arr[mid+1])
return mid;
// check slope
if(arr[mid-1]<arr[mid] && arr[mid]<arr[mid+1]){
//increasing slope
return getMax(mid+1, end);
}
if(arr[mid-1]>arr[mid] && arr[mid]>arr[mid+1]){
return getMax(start, mid-1);
}
return -1;
}
Partition array on pivot element and run two binomial searches for left(increasing) and right(decreasing)
findElem(int key, int pivot){
int index = binSearchInc(start, pivot-1);
if(index>=0)
return index;
else
return binSearchDec(pivot+1, end);
}
Both steps take O(logN) time for execution.