I am trying to search an array using a binary search algorithm when the array is in ascending order. I don't know why every single time I search for a value it says it isn't in the array... Here is my code.
int main()
{
int found, value;
int array[] = {0,2,2,3,5,9,11,12,12,12,13,17,18,19,19,34}; // array to be searched
cout << "Enter an integer to search for:" << endl;
cin >> value;
found = binarySearch(array, SIZE, value); //function call to perform the binary search
//on array looking for an occurrence of value
if (found == -1)
cout << "The value " << value << " is not in the list" << endl;
else
{
cout << "The value " << value << " is in position number "
<< found + 1 << " of the list" << endl;
}
system("pause");
return 0;
}
//**********BINARY SEARCH**********
int binarySearch(int array[],int numElems,int value) //function heading
{
int first = 0; // First element of list
int last = numElems - 1; // last element of the list
int middle; // variable containing the current
// middle value of the list
while (first <= last)
{
middle = first + (last - first) / 2;
if (array[middle] == value)
return middle; // if value is in the middle, we are done
else if (array[middle] < value)
last = middle - 1; // toss out the second remaining half of
// the array and search the first
else
first = middle + 1; // toss out the first remaining half of
// the array and search the second
}
return -1; // indicates that value is not in the array
}
your condition for binary search is inverted.
if array[middle] < value then you want to search for your element in upper half and not the lower half.
Exchange last = middle - 1 and first = middle + 1, and binary search would work fine.
Lets search for 7.
2 3 5 6 [7] 8 8 9
0 1 2 3 4 5 6 7
^f....^m............^l
m = (7 + 0) / 2 = 3
Element with index 3 is 6.
6 < 7. Then we should change first to mid + 1.
If mid value is less than value for search, then we should change first, so that value for search is still in interval [first; last]
Related
Given an integer and a sorted array of integers, write a binary search function named binary_search that prints the number of comparisons performed doing a binary search. The function should take 3 arguments:
the number searched for,
the array of integers, and
the number of elements in the array.
If the number searched for is not in the array then the function should return the maximum number of searches to determine the element is not in the array.
Here is an example call to the function:
#include <iostream>
using namespace std;
//Function for binary_search
int binary_search(int search_value, int lst[], int elements)
{
//Dividing the array elements to its half
int mid = elements / 2;
//Condition to check search value is less then list of mid element and return it.
if (lst[mid] > search_value)
return binary_search( elements,lst, mid);
//Condition to check search value is greater then list of mid element and return it.
else if (lst[mid] < search_value)
return binary_search( search_value,&lst[mid], (elements + 1)/2);
else
return mid;
}
int main()
{
int lst[] = {0, 1, 2, 18, 19, 20, 25};
std:cout << binary_search(20, lst, 7);
}
When I search for 20 it returns the index it is found, which is 5, instead of the number of comparisons, which should be 2.
There are a few problems with your code. First off this line:
return binary_search( elements,lst, mid);
Since your first argument is the number you are searching for, it should always be the same, search_value.
Then, the idea behind a binary search is that the number of elements is halved with each call, so you don't need to change your third argument at any point, it always is elements/2 + 1.
Finally, as mentioned in the comments, your function doesn't return the number of comparisons but rather the number "mid". Since each call does a single comparison, you essentially have to find the number of calls. So, your base case for recursion (when you find the number you are searching for) should return 1, since to find it you have done a comparison. Then you just return 1 + the number of recursive calls already made.
In the end the code should look like this,
int binary_search(int search_value, int lst[], int elements)
{
int mid = elements / 2;
if (lst[mid] > search_value)
return 1 + binary_search( search_value, lst, elements/2 + 1);
else if (lst[mid] < search_value)
return 1 + binary_search( search_value, &lst[mid], elements/2 + 1);
else
return 1;
}
I would propose the solution below:
[Demo]
#include <iostream> // cout
//Function for binary_search
int binary_search(int search_value, int lst[], int elements)
{
//Base case: not found
if (elements == 0) { return 1; }
//Dividing the array elements to its half
int mid = elements / 2;
//Condition to check search value is less then list of mid element and return it.
if (lst[mid] > search_value)
{
return 2 + binary_search(search_value, lst, mid);
}
//Condition to check search value is greater then list of mid element and return it.
else if (lst[mid] < search_value)
{
return 3 + binary_search(search_value, &lst[mid + 1], elements - mid - 1);
}
else
{
return 3;
}
}
int main()
{
int lst[] = {0, 1, 2, 18, 19, 20, 25};
std::cout << "lst: ";
for (auto&& i : lst)
{
std::cout << i << " ";
}
std::cout << "\n";
for (auto&& i : lst)
{
std::cout << "binary_search(" << i << ", lst, 7): "
<< binary_search(i, lst, 7) << "\n";
}
std::cout << "binary_search(10, lst, 7): "
<< binary_search(10, lst, 7) << "\n";
}
// Outputs:
//
// lst: 0 1 2 18 19 20 25
// binary_search(0, lst, 7): 7
// binary_search(1, lst, 7): 5
// binary_search(2, lst, 7): 8
// binary_search(18, lst, 7): 3
// binary_search(19, lst, 7): 8
// binary_search(20, lst, 7): 6
// binary_search(25, lst, 7): 9
// binary_search(10, lst, 7): 9
Explanation:
We add a base case for calls to binary_search with 0 elements. This is a safety case for calls with 0 elements, but also a base case during recursive calls when an element is not found. Since we are doing a comparison, we return 1.
if (elements == 0) { return 1; }
For values smaller than the pivot element, lst[mid], we do 2 comparisons (== 0, > search_value) plus the ones returned by the recursive call.
//Condition to check search value is less then list of mid element and return it.
if (lst[mid] > search_value)
{
return 2 + binary_search(search_value, lst, mid);
}
For values bigger than the pivot element, we do 3 comparisons (== 0, > search_value, < search_value) plus the ones returned by the recursive call.
//Condition to check search value is greater then list of mid element and return it.
else if (lst[mid] < search_value)
{
return 3 + binary_search(search_value, &lst[mid + 1], elements - mid - 1);
}
Otherwise, the value is equal to the pivot element, and we return 3 comparisons (== 0, > search_value, < search_value). This is the second base case.
else
{
return 3;
}
Write a C++ program to find the number of pairs of integers in a given array of integers whose sum is equal to a specified number. The program will ask the user to input 10 numbers and check if a pair of integers will be equal to a user-specified number.
Your program will show the location of the pair of integers in the array and their corresponding values.
SAMPLE INPUT:
Enter an array of integers: 75 90 100 32 1 55 92 123 56 10
Sum of pairs of integers: 101
SAMPLE OUTPUT:
The location of the pair of integers are number[2] and number[4] and the values are
100 and 1, respectively
Depending on how you'd like to implement it, you could consider a recursive approach similar to this:
void pairAddToK(vector<int> L, int left, int right, int K) {
if (left == right) // Our base case
return;
if (left + 1 == right) { // 2 elements, check if they add to K
if (L[left] + L[right] == K)
cout << L[left] << " + " << L[right] << " = " << K << endl;
}
int mid = (left + right) / 2; // General case, use recursion to divide and conquer
pairAddToK(L, left, mid, K);
pairAddToK(L, mid + 1, right, K);
for (int i = left; i <= mid; i++) // Check for pairs from both halves
for (int j = mid + 1; j <= right; j++)
if (L[i] + L[j] == K)
cout << L[i] " + " << L[j] << " = " << K << endl;
}
Something along these lines should work. I did not test this and wrote this only inside the StackOverflow answer box, so let me know if this needs clarity.
You will need a nested while loop or nested for-loop.
check if arr[0] + arr[1] == sum_of_pair_of_int
if it is, insert it into the pair... an array can work too.
then check if arr[0] + arr[2].
repeat for rest of array.
then start at arr[1] + arr[2], then arr[1] + arr[3], etc.
If you have a more specific question, that would be more helpful.
My function works for the first 4 elements, but returns -1 for 12 and 14..even though there in the array.
I've tried changing some of the if statements and using .compare but haven't had any luck.
Any ideas?
Thanks
/** Searches the array anArray[first] through anArray[last]
for a given value by using a binary search.
#pre 0 <= first, last <= SIZE - 1, where SIZE is the
maximum size of the array, and anArray[first] <=
anArray[first + 1] <= ... <= anArray[last].
#post anArray is unchanged and either anArray[index] contains
the given value or index == -1.
#param anArray The array to search.
#param first The low index to start searching from.
#param last The high index to stop searching at.
#param target The search key.
#return Either index, such that anArray[index] == target, or -1.
*/
int binarySearch(const string anArray[], int first, int last, string target)
{
int index;
if (first > last)
index = -1; // target not in original array
else {
// If target is in anArray,
// anArray[first] <= target <= anArray[last]
int mid = first + (last - first) / 2;
if (anArray[mid] == target)
index = mid; // target found at anArray[mid]
else if (anArray[mid] > target)
// Point X
index = binarySearch(anArray, first, mid - 1, target);
else
// Point Y
index = binarySearch(anArray, mid + 1, last, target);
} // end if
return index;
}
int main()
{
const string v[6] = {"1","5","6","9","12","14"};
int index;
string searchItem = "12";
cout << "Searching For: " << searchItem << endl;
index = binarySearch(v, 0, 6, searchItem);
cout << "Element found at index " << index << endl;
system("pause");
return 0;
}
Problem is the fact that for binary search to work your array has to be sorted with the same criteria you use with your binary search. Array you provided is not sorted. You sorted numbers, but you have strings and they compare differently - lexicographically. Which means that "12" comes before "5" and so on. So you either need to convert strings to numbers before you compare, use proper data type (probably int) or change order of elements in your array accordingly.
Note: your function "works" for the first four elements because for single digit numbers lexicographical and numerical compare is the same.
Note2: you also seem to pass wrong number as last, your doc clearly says "SIZE - 1", which is equal to 5. (your array has indexes from 0 to 5, not to 6)
Problem is that you can't compare full strings like you compare numbers (although you can do that with chars according to ascii value). You have two options, the first and simpler one is defining a function to compare strings, something like:
int compareStrings (string a, string b) { // -1: a>b, 0: a=b, 1: a<b
if (a.length() == b.length()) {
if (a == b) return 0;
else for (int i = 0; i < a.length(); i++)
if (a[i] < b[i]) return 1;
else if (a[i] > b[i]) return -1;
}
else return (a.length() < b.length()? 1 : -1);
}
and then when you need to retrieve what string is bigger you could do:
int compResult = compareStrings (anArray[mid], target);
switch (compResult) {
case -1:
index = binarySearch(anArray, first, mid - 1, target); break;
case 1:
index = binarySearch(anArray, mid + 1, last, target); break;
}
The other one is creating a custom "wrapper" class for the strings such that you can override a comparing operator within it, but is a little bit more complicated, and the body of the functions would be pretty much the same, so I would suggest the former solution. But if you want to see how you could accomplish the latter of the solutions, here's a source:
https://www.geeksforgeeks.org/c-program-to-compare-two-strings-using-operator-overloading/
Hope it helps man
I need to find a number in the 2D array.
Columns are sorted (from smallest value to the biggest).
Here is my code:
const int SIZE = 4;
const int NOT_FOUND = 1;
int binarySearch(int mat[][SIZE], int &line , int num);
void main()
{
int num, index, mat[SIZE][SIZE] = { 11,1,5,11,
11,6,7,2,
8,7,7,7,
0,12,9,10 };
int line = sizeof(mat) / sizeof(mat[0][0]);
cout << "please type a number to search: " << endl;
cin >> num;
index = binarySearch(mat, line, num);
if (index == NOT_FOUND) {
cout << "The value: " << num << "doesn't exist in the array\n";
}
else {
cout << "The value: " << num << " exists in line " << line+1
<<" and column: " << index+1 << endl;
}
system("pause");
}
int binarySearch(int mat[][SIZE], int &line, int num)
{
for (int j = 0; j < SIZE; j++)
{
int low = 0;
int high = SIZE - 1;
int middle;
while (low <= high)
{
middle = (low + high) / 2;
if (num == mat[middle][j])
{
line = middle;
return j;
}
else if (num < mat[middle][j]) {
high = middle - 1;
{
else {
low = middle + 1;
}
}
}
return NOT_FOUND;
}
The program doesn't find all the numbers in the array.
Something doesn't work.
What is the problem?
Your binarySearch doesn't go through all the numbers, it checks the first number, so in your case 11, then it moves to the next number, but it skips the whole row of numbers (1, 5, 11) and the first number in second row and then moves to the next second number which will be 6 in second row.
Since you have a Matrix of number it consists of Rows and Columns, that means you have to create two loops for(...), once for the Rows and one for the Columns so you can go through all the numbers in your 2D array.
I recommend setting a Break point on the binarySearch function and going through with that, it'll help you a lot.
A few things that I see wrong in your code are ::
1) It appears that you are applying binary search to every column in your input array, and if the number is not found in the corresponding column, you increment j and move to the next column.
The most important thing about binary search is "The array in which you are searching should always be sorted". Since here you are searching columns, all your columns shall be sorted! Which appears unsorted in the code above! Which is a major reason why you don't find most elements. So, your input array shall look something like this (if you want to apply binary search) ::
int mat[SIZE][SIZE] = { 0,1,5,2,
8,6,7,7,
11,7,7,10,
11,12,9,11 }
All columns sorted in ascending order here!
2) The value of the variable NOT_FOUND you have set it to 1 and from your function you return the column number from where you found the element. So, if you found the element in the 2D array in column 1 your program will print Element Not Found because the condition if (index == NOT_FOUND) evaluates to true if the element was found in column 1. So, a better solution would be to change the value of NOT_FOUND to some negative value, since it can never be the column number in a valid case. Something like this ::
const int NOT_FOUND = -1;
Ideone link of code :: http://ideone.com/9cwHnY
I am having problems with my timing functions here. I have a program that is timing how long a binary search is taking to find a given number in a list of sorted elements in an array.
So i am getting strange results and I'm not sure why.
For example this last run i did, the program said that it took 0 microseconds to find the value not in the array of size 100,000 elements, but just before it the program searched an array of 95,000 elements which also found the value was not in the array yet it took 4080005 microseconds.
Here is my function code.
Thanks for any help!
int binarySearch(int array[], int numElems, int value)
{
auto start =chrono::steady_clock::now();
cout << "Searching..."<< endl;
//variables
int first = 0,
last = numElems - 1,
middle,
position = -1;
bool found = false;
//Checks values for match
while (!found && first <= last)
{
//divides elements
middle = (first + last) / 2;
if (array[middle] == value)
{
found = true;
position = middle;
}
else if (array[middle] > value)
last = middle - 1;
else
first = middle + 1;
}
auto end = chrono::steady_clock::now();
auto elasped = std::chrono::duration_cast<std::chrono::microseconds>(end-start);
cout << "Time Taken: " << elasped.count() << " microseconds." << endl;
return position;
}
Running your code with a worst case search I consistently get between 25 and 86 microseconds on my machine. Moving the cout outside the clocked section of code, I get a consistent 0 microseconds.
Maybe your stdout buffer was hung for 4 seconds. Sending text to the terminal is an extraordinarily slow process. The binary search is fast; O(log(n)), which for 100,000 is 6 comparisons, worst case. 0 microseconds makes a lot of sense. I bet it was your terminal buffers being wonky.
Now for kicks, I switched to the high_resolution_clock.
$ ./a.out
Searching...
Time Taken: 619 nanoseconds.
Position: 99999
Source:
int binarySearch(int array[], int numElems, int value)
{
cout << "Searching..."<< endl;
auto start =chrono::high_resolution_clock::now();
//variables
int first = 0,
last = numElems - 1,
middle,
position = -1;
bool found = false;
//Checks values for match
while (!found && first <= last)
{
//divides elements
middle = (first + last) / 2;
if (array[middle] == value)
{
found = true;
position = middle;
}
else if (array[middle] > value)
last = middle - 1;
else
first = middle + 1;
}
auto end = chrono::high_resolution_clock::now();
auto elasped = std::chrono::duration_cast<std::chrono::nanoseconds>(end-start);
cout << "Time Taken: " << elasped.count() << " nanoseconds." << endl;
return position;
}