This question already has answers here:
C++ return value without return statement
(6 answers)
Why does flowing off the end of a non-void function without returning a value not produce a compiler error?
(11 answers)
Closed last year.
This is the code for recursive binary search
Without using cout << binarySearch
int binarySearch(int arr[], int l, int h, int key)
{
int mid = l + (h - l) / 2;
if (l <= h)
{
if (arr[mid] == key)
{
return mid;
}
else if (key < arr[mid])
{
binarySearch(arr, l, mid - 1, key);
}
else
{
binarySearch(arr, mid + 1, h, key);
}
}
else
return -1;
}
int main()
{
int arr[5] = {1,2,3,4,5};
int key = 2;
int size = sizeof(arr)/sizeof(arr[0]);
cout << binarySearch(arr, 0, size - 1, key);
return 0;
}
Output : 1
but when cout << binarySearch() is used the required output is changed
else if (key < arr[mid])
{
cout << binarySearch(arr, l, mid - 1, key) << "\n"; // Adding cout here
}
else
{
cout << binarySearch(arr, mid + 1, h, key) <<"\n"; // Adding cout here
}
Output :
1
1875946688
1875946688
Why the result is changed on using cout ?
return mid;
Here you have an explicit return statement that returns some value from this recursive function. So far, so good.
binarySearch(arr, l, mid - 1, key);
This is one of the recursive calls. When this recursive call returns ...nothing happens. The caller continues to execute. And after this statement ...nothing happens. The execution leaves from this function without explicitly returning anything. The caller to this function receives randomly-generated garbage as its return value.
Your compiler has an option to turn on all warnings. If it were used your C++ compiler would've likely pointed out this common bug.
You have UB, since you don't return values on your recursive cases.
binarySearch(arr, l, mid - 1, key);
Should instead be
return binarySearch(arr, l, mid - 1, key);
For your cout version, you'd need something like
int ret = binarySearch(arr, l, mid - 1, key);
std::cout << ret;
return ret;
Related
I am trying to find the minimum element in an array that has been sorted and rotated (Edit: distinct elements).
I wrote a function that uses binary search, splitting the array into smaller components and checking whether the "mid" value of the current component was either greater than the "high" value or lesser than the "starting" value moves towards either end because by my rough logic, the smallest element must be "somewhere around there".
Thinking about it a little harder, I realized that this function would not return the correct answer for a fully sorted component/array, but for some reason, it does.
// Function to find the minimum element in sorted and rotated array.
int minNumber(int arr[], int low, int high)
{
int mid = (low + high) / 2;
if (low > high)
return -1;
if (low == high)
return arr[low];
if (mid == 0 || arr[mid - 1] > arr[mid])
return arr[mid];
else if (arr[mid] > arr[high])
{
return (minNumber(arr, mid + 1, high));
}
else if (arr[mid] < arr[low])
{
return (minNumber(arr, low, mid - 1));
}
}
Passing the array "1,2,3,4,5,6,7,8,9" through it returns 1. I though maybe the rax register might have accidentally stored a 1 at some point and now the function was just spitting it out as there was no valid return statement for it to go through. Running it through g++ debugger line-by-line didn't really help and I'm still confused as to how this code works.
FULL CODE
// { Driver Code Starts
#include <bits/stdc++.h>
using namespace std;
// } Driver Code Ends
class Solution
{
public:
// Function to find the minimum element in sorted and rotated array.
int minNumber(int arr[], int low, int high)
{
int mid = (low + high) / 2;
if (low > high)
return -1;
if (low == high)
return arr[low];
if (mid == 0 || arr[mid - 1] > arr[mid])
return arr[mid];
else if (arr[mid] > arr[high])
{
return (minNumber(arr, mid + 1, high));
}
else if (arr[mid] < arr[low])
{
return (minNumber(arr, low, mid - 1));
}
}
};
// { Driver Code Starts.
int main()
{
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
int a[n];
for (int i = 0; i < n; ++i)
cin >> a[i];
Solution obj;
cout << obj.minNumber(a, 0, n - 1) << endl;
}
return 0;
} // } Driver Code Ends
Short answer: Undefined behavior doesn't mean it can't give the right answer.
<source>: In member function 'int Solution::minNumber(int*, int, int)':
<source>:31:5: warning: control reaches end of non-void function [-Wreturn-type]
When the array isn't rotated you hit that case and you are simply getting lucky.
Some nitpicking:
turn on the compiler warnings and read them
int is too small for a large array
int mid = (low + high) / 2; is UB for decently sized arrays, use std::midpoint
minNumber should take a std::span and then you could use std::size_t size = span.size();, span.first(size / 2) and span.last(size - size / 2)
I have tried to search a data in a structure like 1D array, but it always tell me that the target data has not been found, although I have make the algorithm exactly as it is. now I am totally confused
the below is how I define function
int RecBinarySearch (int a[], int low, int high, int key) {
int mid{ };
if (high >= low ) {
mid = low + (high-low)/2;
if (key == a[mid]) return mid;
if (key > a[mid]) RecBinarySearch(a, mid + 1, high, key);
if (key < a[mid]) RecBinarySearch(a, low, mid - 1, key);
}
return -1;
}
and here you see how I define my array
int n{};
int* a = new int [n] {};
When you recursively call a function that is supposed to return something, you need to return what the recursive call would return.
if (key > a[mid]) return RecBinarySearch(a, mid + 1, high, key);
if (key < a[mid]) return RecBinarySearch(a, low, mid - 1, key);
Okay, don't take that literally. It is true for most divide and conquer style recursive algorithms and greedy style algorithms, where the recursive call is designed to find the answer. Then, that answer has to be propagated up. There are other cases where the recursive call is just finding a portion of the solution. In those cases, the result needs to be incorporated into the final answer.
The point is, however, that you are ignoring the returned result of the recursive call, which is triggering a bug where you will return -1 instead of the answer found by the call.
Note that C++ includes binary_search (and C includes bsearch).
This is what you want:
#include <iostream>
int RecBinarySearch(int a[], int low, int high, int key)
{
if (high >= low)
{
int mid = low + (high - low) / 2;
if (key == a[mid])
return mid;
if (key > a[mid])
return RecBinarySearch(a, mid + 1, high, key); // you forgot the return statement
if (key < a[mid])
return RecBinarySearch(a, low, mid - 1, key); // you forgot the return statement
}
return -1;
}
int main()
{
int values[] = { 1,3,4,5,6,7 }; // must be sorted
// check if we find each of the values contained in values
for (auto v : values)
{
if (RecBinarySearch(values, 0, 7, v) == -1)
{
std::cout << v << " not found\n";
}
}
int valuesnotcontained[] = {0,2,8,10};
// check we don't find values not contained in values
for (auto v : valuesnotcontained)
{
if (RecBinarySearch(values, 0, 7, v) != -1)
{
std::cout << v << " should not be found\n";
}
}
}
It includes some basic test code.
I need to make this tail recursive by adding a parameter but I am not sure the first step to take.
int countVal (int A[], int size, int val)
{
if (size == 0)
return 0;
else if (A[size - 1] == val)
return 1 + countVal(A, size-1, val);
else
return countVal(A, size - 1, val);
}
The added parameter should accumulate the result, and when recursion terminates you return the accumulated result rather than the base value.
In this case, you can give the base value as a default parameter value:
int countVal (int A[], int size, int val, int accumulator = 0)
{
if (size == 0)
return accumulator;
else if (A[size - 1] == val)
return countVal(A, size - 1, val, accumulator + 1);
else
return countVal(A, size - 1, val, accumulator);
}
but it's also common to use a separate (and hidden) helper function.
I am getting this-' process exited with return value 3221225725 ' for some of the values. I am facing problem to find where i goes wrong. Please someone help me. Here's the code-
#include<iostream>
using namespace std;
int binsearch(int a[],int find,int l,int u,int n);
int main()
{
int a[10]={1,54,76,89,123,145,198,230,345,654};
int n=sizeof(a)/sizeof(a[0]);
int find,l=0,u=n-1,x;
cout<<"Enter number which you want to find"<<endl;
cin>>find;
x= binsearch(a,find,l,u,n);
if(x==0)
cout<<"Element is not found";
else
cout<<"Element is present at "<<x;
}
int binsearch(int a[],int find,int l,int u,int n){
if(n==1)
{
if(find==a[l])
return l;
else
return 0;
}
else
{
int mid=l+u/2;
if(a[mid]==find)
return mid;
else if(a[mid]<find)
return binsearch(a,find,mid+1,u,n);
else
return binsearch(a,find,l,mid-1,n);
}
}
3221225725 is 0xC00000FD in hex, which is Microsoft's code for a stack overflow.
You have written a recursive binsearch() function, so that's the obvious place to look for a problem.
Your recursion stops only if n == 1 or if a[mid]==find. But in your code, n will never equal 1, because it is passed unchanged in each recursive call. That's a bug (there may be more, I haven't checked). So you will get a stack overflow if you enter a number that isn't in the array, because in that case a[mid]==find will never be true either.
My advice would be to eliminate n from your code. n is always equal to u - l + 1, so there is no need for a separate variable. If you need to know the value of n, you can always calculate it from l and u.
When you enter a number that is not found, binsearch will call itself over and over again until the stack overflows because your terminating condition if(n==1) will never be true since you call binsearch with the same n all the time. n isn't needed since you have both l and u so just make it int n = u - l + 1;.
mid=l+u/2 is also incorrect. It's the same as mid = u/2 + l. You want mid = (l + u) / 2.
Also, if you search for 1 it'll return the index 0 but you treat 0 as "not found". Since you use a signed integer for indexing, you could return -1 to signal that the number wasn't found.
Example:
#include <iostream>
#include <iterator> // std::size()
int binsearch(int a[], int find, int l, int u) {
int n = u - l + 1;
if(n == 1) {
if(find == a[l])
return l;
else
return -1;
} else {
int mid = (l + u) / 2;
if(a[mid] == find)
return mid;
else if(a[mid] < find)
return binsearch(a, find, mid + 1, u);
else
return binsearch(a, find, l, mid - 1);
}
}
int main() {
int a[] = {1, 54, 76, 89, 123, 145, 198, 230, 345, 654};
int l = 0, u = std::size(a) - 1, x;
std::cout << "Enter number which you want to find\n";
if(int find; std::cin >> find) {
x = binsearch(a, find, l, u);
if(x == -1)
std::cout << "Element is not found";
else
std::cout << "Element is present at " << x;
std::cout << '\n';
}
}
I wrote a divide and conquer binary search, it works in all cases except for when I search for the first or the last number, where instead of giving me 0 and v.size()-1 as the result it gives me 1 and v.size()-2.
For example if I input n=5 and the vector {1; 2; 3; 4; 5} and search for 1 it returns me "1" instead of "0".
#include <iostream>
#include <vector>
using namespace std;
int binarySearch(std::vector<int> v, int nr, int left, int right)
{
int mij = (left + right) / 2;
if (v[mij] < nr){
binarySearch(v, nr, mij+1, right);
}
else if (v[mij] > nr){
binarySearch(v, nr, left, mij-1);
}
else if (v[mij] == nr){
return mij;
}
else return -1;
}
int main()
{
vector <int> v;
int n; cout << "n="; cin >>n;
for (int i = 0; i < n; i++){
int x;
cout << "v[" << i << "]=";
cin >> x;
v.push_back(x);
}
cout << binarySearch(v, 1, 0, v.size());
return 0;
}
Your code has undefined behavior because you do not return a value from your function in all cases. Your program might crash, do nothing, format your hard drive or give you the correct value - it's undefined what happens. In this case, your compiler knows exactly what the problem is and really wants to tell you, but you need to ask it: Turn on the warnings (e.g. -Wall in gcc or clang).
warning: control may reach end of non-void function [-Wreturn-type]
Currently, you do not return a value if you recurse, which is easily fixed:
int binarySearch(std::vector<int> v, int nr, int left, int right)
{
int mij = (left + right) / 2;
if (v[mij] < nr){
return binarySearch(v, nr, mij+1, right);
// ^^^^^^
}
else if (v[mij] > nr){
return binarySearch(v, nr, left, mij-1);
// ^^^^^^
}
else if (v[mij] == nr){
return mij;
}
else return -1;
}
Your binary search works fine but You sure you had passed inputs to the program correctly? input should be like this -
5
1 2 3 4 5
output
0
you can verify that here link to code