Binary searching using const pointer - c++

We should implement a function that uses binary search to check if a value key is in the array and give either true or false.
My goes like this:
bool binary_search(const int* begin, const int * end, int key){
if(begin < end){
int mid = (end-begin)/2;
if(mid == key){
return true;
}else if (key < mid){
int h = mid-1;
end = &h;
binary_search(begin, end, key);
}else if (mid < key){
int i = mid+1;
begin = &i;
binary_search(begin, end, key);
}
}else{
return false;
}
}
but it wouldn't give any output but instead it gives me the error.
warning: control reaches end of non-void function [-Wreturn-type]
I don't really understand what I have to do here so can someone explain me what is going wrong here?

In case of these if else statements
}else if (key < mid){
int h = mid-1;
end = &h;
binary_search(begin, end, key);
}else if (mid < key){
int i = mid+1;
begin = &i;
binary_search(begin, end, key);
}
the function returns nothing. That is these code blocks do not have return statements.
Moreover the function does not make sense because for example in these statements
int mid = (end-begin)/2;
if(mid == key){
there are compared key with an index of the array instead of comparing key with the value of the element in the array with index mid.
Or these statements
int h = mid-1;
end = &h;
also do not make sense because the variable end will store an address of the local variable h.
The function can be implemented the following way as it is shown in this demonstrative program.
#include <iostream>
#include <iomanip>
bool binary_search( const int *begin, const int *end, int key )
{
if ( begin < end )
{
const int *mid = begin + ( end - begin ) / 2;
if ( *mid < key ) return binary_search( ++mid, end, key );
else if ( key < *mid ) return binary_search( begin, mid, key );
else return true;
}
else
{
return false;
}
}
int main()
{
int a[] = { 1, 3, 5 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i <= a[N-1] + 1; i++ )
{
std::cout << i << " is present in the array - "
<< std::boolalpha << binary_search( a, a + N, i )
<< std::endl;
}
return 0;
}
Its output is
0 is present in the array - false
1 is present in the array - true
2 is present in the array - false
3 is present in the array - true
4 is present in the array - false
5 is present in the array - true
6 is present in the array - false

You should return in all the possible branches.
Change
binary_search(begin, end, key);
to
return binary_search(begin, end, key);
to return the result from the recursive invocation.

Related

Is this a proper implementation of binary search? And has this program complexity of O(logn)?

int szukaj2(int tab[], int n, int s){
if(n==1&&s==n){
return 0;
} else if(n==1&&s!=tab[n]){
return -1;
}
int m= n/2;
while(m>0){
if(tab[m]==s){
return m;
}
if(tab[m]<s){
m=m+(m/2);
cout<<"wieksze"<<endl;
}
if(tab[m]>s){
m/=2;
cout<<"mniejsze"<<endl;
}
m--;
}
return -1;
}
the complexity must be O(logn) so if its not, make sure to guide me to the right thinking. I will edit this every time if something aint right.
Binary search (not tested):
int binary( int *array, int size, int value ) {
int left = 0, right = size -1;
while ( left < right ) {
int mid = (int)( ( (long long)left + right ) / 2 );
if ( array[mid] == value ) return mid;
else if ( value < array[mid] ) right = mid - 1;
else /* if ( value > array[mid] ) */ left = mid + 1;
}
return -1;
}

C++ Binary search algorithm to work like lower_bound

I do have another question following my previous -
I am creating a version of lower_bound with something like binary search. With the BinarySearch function I find a place where to insert the new item and with the for cycle I do move the rest of the array and insert the right item so I can insert it to the right position.
But the following BinarySearch function does not work properly.
Can anyone see why?
bool CReg::AddCar ( const char *name){
CArr * tmp = new CArr(name); // an item I am going to insert
int pos = BinarySearch(name,0,len); //len = number of items in array
checkLen(); // whether I do have enough space to move the array right
if (length!=0)
for (int i = m_len; i>=pos; i-- )
Arr[i+1] = spzArr[i];
Arr[pos] = tmp;
length++;
checkLen();
return true;
}
int BinarySearch(const char * name, int firstindex, int lastindex) {
if (lenght == 0) return 0; //number of items in array
if (firstindex == lastindex) return lastindex;
int tmp = lastindex - firstindex;
int pos = firstindex + tmp / 2; //position the new item should go to
if (tmp % 2)++pos;
if (lastindex == pos || firstindex == pos) return pos;
if (strcmp(name, Arr[pos]) < 0) return BinarySearch(name, firstindex, pos - 1);
if (strcmp(name, Arr[pos]) > 0) return BinarySearch(name, pos + 1, lastindex);
return pos;
}
A fixed version of BinarySearch
int BinarySearch(const char* name, int firstindex, int lastindex)
{
if (firstindex == lastindex) return lastindex;
int dist = lastindex - firstindex;
int mid = firstindex + dist / 2; //position the new item should go to
if (strcmp(name, Arr[mid]) < 0) return BinarySearch(name, firstindex, mid);
if (strcmp(name, Arr[mid]) > 0) return BinarySearch(name, mid + 1, lastindex);
return mid;
}
But you may directly use std::lower_bound:
// Assuming std::vector<std::string> Arr;
void CReg::AddCar(const std::string& name)
{
auto it = std::lower_bound(Arr.begin(), Arr.end(), name);
Arr.insert(it, name);
}

Unhandled Exception while trying to sort

I keep getting an unhandled exception in this portion of code whenever it runs, I have looked through it and can't see a clear reason. It will run fine up to the system pause that is commented out so it has to be something past that.Or maybe it is how I am setting my pivot?
template <class elemType>
int arrayListType<elemType>::medianpartition(int p, int r)
{
int middle = list[(r+p)/2];
int pivot = 0;
if(list[p]<list[r]){
if(middle<list[r]){
if(list[p]<middle){
pivot = middle;
}else if(list[p]>middle){
pivot = list[p];
}
}else if(middle>list[r]){
pivot = list[r];
}
}else if(list[p]>list[r]){
if(middle<list[r]){
pivot = list[r];
}else if(middle>list[r]){
if(middle<list[p]){
pivot = middle;
}else if(middle>list[p]){
pivot = list[p];
}
}
}
//system("Pause>nul");
while ( p < r )
{
while ( list[p] < pivot )
p++;
while ( list[r] > pivot )
r--;
if ( list[p] == list[r] )
p++;
else if ( p < r )
{
int tmp = list[p];
list[p] = list[r];
list[r] = tmp;
}
}
return r;
}
This is the function that calls it:
template <class elemType>
void arrayListType<elemType>::medianquicksort(int p, int r)
{
if ( p < r )
{
int j = medianpartition(p, r);
medianquicksort(p, j-1);
medianquicksort(j+1, r);
}
}
Any help would be appreciated!
If list[p] == list[r] then pivot is not assigned any value from the array and stays with its default value of zero. And if all items of the array are greater than zero, or all are less than zero, then one of the while loops runs p or r out of array's bounds.
Think about this: what happens if every element in your array is the same value?
You have too many if else if statements when trying to figure out the pivot, and you didn't account for the possibility that list[p], list[r] and/or middle have the same value. I don't know if that's the root of your problem, but it's certainly a problem.

C++ Binary Search Algorithm not working

So I have a vector of ints named bList that has information already in it. I have it sorted before running the binary search.
//I have already inserted random ints into the vector
//Sort it
bubbleSort();
//Empty Line for formatting
cout << "\n";
//Print out sorted array.
print();
cout << "It will now search for a value using binary search\n";
int val = binSearch(54354);
cout<<val;
My bubble sort algorithm does work.
I have it returning an int which is the location of the searched value in the list.
//Its one argument is the value you are searching for.
int binSearch(int isbn) {
int lower = 0;
int upper = 19;//Vector size is 20.
int middle = (lower + upper) / 2;
while (lower < upper) {
middle = (lower + upper) / 2;
int midVal = bList[middle];
if (midVal == isbn) {
return middle;
break;
} else if (isbn > midVal) {
lower = midVal + 1;
} else if (isbn < midVal) {
upper - midVal - 1;
}
}
}
But for some reason, when I run it, it just keeps running and doesn't return anything.
Here the bug is:
// ...
} else if (isbn > midVal) {
lower = midVal + 1;
} else if (isbn < midVal) {
upper - midVal - 1;
}
You may want
lower = middle + 1;
and
upper = middle - 1;
instead.
You also need to explicitly return something when the required number cannot be found.
You still have a slight logic problem with your while condition:
int binary_search(int i, const std::vector<int>& vec) // you really should pass in the vector, if not convert it to use iterators
{
int result = -1; // default return value if not found
int lower = 0;
int upper = vec.size() - 1;
while (lower <= upper) // this will let the search run when lower == upper (meaning the result is one of the ends)
{
int middle = (lower + upper) / 2;
int val = vec[middle];
if (val == i)
{
result = middle;
break;
}
else if (i > val)
{
lower = middle + 1; // you were setting it to the value instead of the index
}
else if (i < val)
{
upper = middle - 1; // same here
}
}
return result; // moved your return down here to always return something (avoids a compiler error)
}
Alternatively, you could switch it to use iterators instead:
template<class RandomIterator>
RandomIterator binary_search(int i, RandomIterator start, RandomIterator end)
{
RandomIterator result = end;
while (start <= end) // this will let the search run when start == end (meaning the result is one of the ends)
{
RandomIterator middle = start + ((end - start) / 2);
if (*middle == i)
{
result = middle;
break;
}
else if (i > *middle)
{
start = middle + 1;
}
else if (i < *middle)
{
end = middle - 1;
}
}
return result;
}

Binary search to find the range in which the number lies

I have an array
Values array: 12 20 32 40 52
^ ^ ^ ^ ^
0 1 2 3 4
on which I have to perform binary search to find the index of the range in which the number lies. For example:
Given the number -> 19 (It lies between index 0 and 1), return 0
Given the number -> 22 (It lies between index 1 and 2), return 1
Given the number -> 40 (It lies between index 3 and 4), return 3
I implemented the binary search in the following manner, and this comes to be correct for case 1, and 3 but incorrect if we search for case 2 or 52, 55 32, etc.
#include <iostream>
using namespace std;
int findIndex(int values[], int number, unsigned first, unsigned last)
{
unsigned midPoint;
while(first<last)
{
unsigned midPoint = (first+last)/2;
if (number <= values[midPoint])
last = midPoint -1;
else if (number > values[midPoint])
first = midPoint + 1;
}
return midPoint;
}
int main()
{
int a[] = {12, 20, 32, 40, 52};
unsigned i = findIndex(a, 55, 0, 4);
cout << i;
}
Use of additional variables such as bool found is not allowed.
A range in C or C++ is normally given as the pointing directly to the lower bound, but one past the upper bound. Unless you're feeling extremely masochistic, you probably want to stick to that convention in your search as well.
Assuming you're going to follow that, your last = midpoint-1; is incorrect. Rather, you want to set last to one past the end of the range you're going to actually use, so it should be last = midpoint;
You also only really need one comparison, not two. In a binary search as long as the two bounds aren't equal, you're going to set either the lower or the upper bound to the center point, so you only need to do one comparison to decide which.
At least by convention, in C++, you do all your comparisons using < instead of <=, >, etc. Any of the above can work, but following the convention of using only < keeps from imposing extra (unnecessary) requirements on contained types.
Though most interviewers probably don't care, there's also a potential overflow when you do midpoint = (left + right)/2;. I'd generally prefer midpoint = left + (right - left)/2;
Taking those into account, code might look something like this:
template <class T>
T *lower_bound(T *left, T *right, T val) {
while (left < right) {
T *middle = left + (right - left) / 2;
if (*middle < val)
left = middle + 1;
else
right = middle;
}
return left;
}
template <class T>
T *upper_bound(T *left, T *right, T val) {
while (left < right) {
T *middle = left + (right - left) / 2;
if (val < *middle)
right = middle;
else
left = middle + 1;
}
return left;
}
Why not to use standard library functions?
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int main() {
for (int input = 10; input < 55; input++) {
cout << input << ": ";
// Your desire:
vector<int> v = { 12, 20, 32, 40, 52 };
if (input < v.front() || input > v.back()) {
cout << "Not found" << endl;
} else {
auto it = upper_bound(v.begin(), v.end(), input);
cout << it - v.begin() - 1 << endl;
}
}
}
Note: a pretty-cool site - http://en.cppreference.com/w/cpp/algorithm
This will work under the condition that min(A[i]) <= key <=max(A[i])
int binary_search(int A[],int key,int left, int right)
{
while (left <= right) {
int middle = left + (right - left) / 2;
if (A[middle] < key)
left = middle+1;
else if(A[middle] > key)
right = middle-1;
else
return middle;
}
return (left - 1);
}
For INPUT
4
1 3 8 10
4
OUTPUT
3 (the minimum of the 3 and 8)
#include <stdio.h>
int main()
{
int c, first, last, middle, n, search, array[100];
scanf("%d",&n);
for (c = 0; c < n; c++)
scanf("%d",&array[c]);
scanf("%d", &search);
first = 0;
last = n - 1;
middle = (first+last)/2;
while (first <= last) {
if (array[middle] < search)
{
first = middle + 1; }
else if (array[middle] == search) {
break;
}
else
{
last = middle - 1;
}
middle = (first + last)/2;
}
printf("%d\n",array[middle]);
return 0;
}
A regular binary search on success returns the index of the key. On failure to find the key it always stops at the index of the lowest key greater than the key we are searching. I guess following modified binary search algorithm will work.
Given sorted array A
Find a key using binary search and get an index.
If A[index] == key
return index;
else
while(index > 1 && A[index] == A[index -1]) index = index -1;
return index;
binsrch(array, num, low, high) {
if (num > array[high])
return high;
while(1) {
if (low == high-1)
return low;
if(low >= high)
return low-1;
mid = (low+high)/2
if (num < arr[mid])
high = mid;
else
low = mid+1;
}
}
here is a more specific answer
int findIndex(int values[],int key,int first, int last)
{
if(values[first]<=key && values[first+1]>=key)// stopping condition
{
return first;
}
int imid=first+(last-first)/2;
if(first==last || imid==first)
{
return -1;
}
if(values[imid]>key)
{
return findIndex(values,key,first,imid);
}
else if(values[imid]<=key)
{
return findIndex(values,key,imid,last);
}
}
I feel this is more inline to what you were looking for...and we won't crap out on the last value in this thing
/* binary_range.c (c) 2016 adolfo#di-mare.com */
/* http://stackoverflow.com/questions/10935635 */
/* This code is written to be easily translated to Fortran */
#include <stdio.h> /* printf() */
#include <assert.h> /* assert() */
/** Find the biggest index 'i' such that '*nSEED <= nVEC[i]'.
- nVEC[0..N-1] is an strict ascending order array.
- Returns and index in [0..N].
- Returns 'N' when '*nSEED>nVEC[N-1]'.
- Uses binary search to find the range for '*nSEED'.
*/
int binary_range( int *nSEED, int nVEC[] , int N ) {
int lo,hi, mid,plus;
if ( *nSEED > nVEC[N-1] ) {
return N;
}
for (;;) { /* lo = binary_range_search() */
lo = 0;
hi = N-1;
for (;;) {
plus = (hi-lo)>>1; /* mid = (hi+lo)/2; */
if ( plus == 0 ) { assert( hi-lo==1 );
if (*nSEED <= nVEC[lo]) {
hi = lo;
}
else {
lo = hi;
}
}
mid = lo + plus; /* mid = lo + (hi-lo)/2; */
if (*nSEED <= nVEC[mid]) {
hi = mid;
}
else {
lo = mid;
}
if (lo>=hi) { break; }
}
break;
} /* 'lo' is the index */
/* This implementation does not use division. */
/* ========================================= */
assert( *nSEED <= nVEC[lo] );
return lo;
}
/** Find the biggest index 'i' such that '*nSEED <= nVEC[i]'.
- nVEC[0..N-1] is an strict ascending order array.
- Returns and index in [0..N].
- Returns 'N' when '*nSEED>nVEC[N-1]'.
- Uses sequential search to find the range for '*nSEED'.
*/
int sequential_range( int* nSEED, int nVEC[] , int N ) {
int i;
if ( *nSEED > nVEC[N-1] ) {
return N;
}
i=0;
while ( i<N ) {
if ( *nSEED <= nVEC[i] ) { break; }
++i;
}
return i;
}
/** test->stackoverflow.10935635(). */
void test_10935635() {
{{ /* test.stackoverflow.10935635() */
/* http://stackoverflow.com/questions/10935635 */
/* binary_range search to find the range in which the number lies */
/* 0 1 2 3 4 */
int nVEC[] = { 12,20,32,40,52 }; int val;
int N = sizeof(nVEC)/sizeof(nVEC[0]); /* N = DIM(nVEC[]) */
val=19; val = binary_range( &val,nVEC,N );
/* 19 -> [12 < (19) <= 20] -> return 1 */
val=19; assert( binary_range( &val,nVEC,N ) == 1 );
/* 22 -> [20 < (22) <= 32] -> return 2 */
val=22; assert( binary_range( &val,nVEC,N ) == 2 );
/* 40 -> [32 < (40) <= 40] -> return 3 */
val=40; assert( binary_range( &val,nVEC,N ) == 3 );
/* Everything over 52 returns N */
val=53; assert( binary_range( &val,nVEC,N ) == N );
}}
}
/** Test program. */
int main() {
if (1) {
printf( "\ntest_10935635()" );
test_10935635();
}
printf( "\nEND" );
return 0;
}
/* Compiler: gcc.exe (tdm-1) 4.9.2 */
/* IDE: Code::Blocks 16.01 */
/* Language: C && C++ */
/* EOF: binary_range.c */
I know this is an old thread, but since I had to solve a similar problem I thought I would share it. Given a set of non-overlapping ranges of integers, I need to test if a given value lies in any of those ranges. The following (in Java), uses a modified binary search to test if a value lies within the sorted (lowest to highest) set of integer ranges.
/**
* Very basic Range representation for long values
*
*/
public class Range {
private long low;
private long high;
public Range(long low, long high) {
this.low = low;
this.high = high;
}
public boolean isInRange(long val) {
return val >= low && val <= high;
}
public long getLow() {
return low;
}
public void setLow(long low) {
this.low = low;
}
public long getHigh() {
return high;
}
public void setHigh(long high) {
this.high = high;
}
#Override
public String toString() {
return "Range [low=" + low + ", high=" + high + "]";
}
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
//Java implementation of iterative Binary Search over Ranges
class BinaryRangeSearch {
// Returns index of x if it is present in the list of Range,
// else return -1
int binarySearch(List<Range> ranges, int x)
{
Range[] arr = new Range[ranges.size()];
arr = ranges.toArray(arr);
int low = 0, high = arr.length - 1;
int iters = 0;
while (low <= high) {
int mid = low + (high - low) / 2; // find mid point
// Check if x is present a
if (arr[mid].getLow() == x) {
System.out.println(iters + " iterations");
return mid;
}
// If x greater, ignore left half
if (x > arr[mid].getHigh()) {
low = mid + 1;
}
else if (x >= arr[mid].getLow()) {
System.out.println(iters + " iterations");
return mid;
}
// If x is smaller, ignore right half of remaining Ranges
else
high = mid - 1;
iters++;
}
return -1; // not in any of the given Ranges
}
// Driver method to test above
public static void main(String args[])
{
BinaryRangeSearch ob = new BinaryRangeSearch();
// make a test list of long Range
int multiplier = 1;
List<Range> ranges = new ArrayList<>();
int high = 0;
for(int i = 0; i <7; i++) {
int low = i + high;
high = (i+10) * multiplier;
Range r = new Range(low, high);
multiplier *= 10;
ranges.add(r);
}
System.out.println(Arrays.toString(ranges.toArray()));
int result = ob.binarySearch(ranges, 11);
if (result == -1)
System.out.println("Element not present");
else
System.out.println("Element found at "
+ "index " + result);
}
}
My python implementation:
Time complexity: O(log(n))
Space complexity: O(log(n))
def searchForRange(array, target):
range = [-1, -1]
alteredBinarySerach(array, target, 0, len(array) -1, range, True)
alteredBinarySerach(array, target, 0, len(array) -1, range, False)
return range
def alteredBinarySerach(array, target, left, right, range, goLeft):
if left > right:
return
middle = (left+ right)//2
if array[middle] > target:
alteredBinarySerach(array, target, left, middle -1, range, goLeft)
elif array[middle] < target:
alteredBinarySerach(array, target, middle +1, right, range, goLeft)
else:
if goLeft:
if middle == 0 or array[middle -1] != target:
range[0] = middle
else:
alteredBinarySerach(array, target, left, middle -1 , range, goLeft)
else:
if middle == len(array) -1 or array[middle+1] != target:
range[1] = middle
else:
alteredBinarySerach(array, target, middle +1, right , range, goLeft)