c++ binary search with array of char arrays - c++

binary search is sorta working if it finds the value it will correctly return the pos at which the value was found at in array the issue is its only looping through first half of array its never hitting the else statement to increase the start index and always hits the if statement regardless of if the searchingFor word is before or after alphabetically. the players array list has been sorted alphabetically. Any help would be amazing :)
cout << "type name youd like to search for" << endl;
char playerChoice[10] = "len";
databaseFunctions.SelectionSort(databaseFunctions.players, databaseFunctions.size);
int result = databaseFunctions.BinarySearch(databaseFunctions.players, 0, databaseFunctions.size, playerChoice);
int DataBaseFunctions::BinarySearch(Player* players, int start_index, int end_index, char searchingFor[])
{
while (start_index <= end_index)
{
int middlePoint = (start_index + end_index) / 2;
if (strcmp(players[middlePoint].playerName, searchingFor) == 0)
return middlePoint;
if (searchingFor < players[middlePoint].playerName)
end_index = middlePoint - 1;
else
start_index = middlePoint + 1; // need to fix thiss never hitting else regardless always just -1 instead of adding 1
}
return -1;
}

Related

recursive binarySearch with array of strings

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

How would I write an algorithm to find the greatest jump from number to number in a sequence?

If your sequence is 4 2 1, the largest jump is from 4 to 2. If your sequence is 3 10 5 16 8 4 2 1, the largest jump is from 5 to 16.
I've made an algorithm however I'm not completely sure what I have done wrong (whever I haven't made the loop properly, set my variables correctly, or something else). I'm not sure what I need to set my index, BiggestDiff, or CurrentDiff too. I tried using a while loop to compare each number in my vector but I get zero (I'm assuming because I set BiggestDiff to zero)
If anyone can point me in the right direction, show me an example, or something else, that will be greatly appreciated.
Here is my code below
int findBiggestDiff(std::vector<int> sequence)
{
int index = 0;
int BiggestDiff = 0 ;
int CurrentDiff = BiggestDiff;
CurrentDiff = std::abs(sequence[index] - sequence[index + 1]);
while (index < sequence.size())
{
if (CurrentDiff > BiggestDiff)
{
BiggestDiff = CurrentDiff;
}
return index;
}
}
Try this:
{
int indexOfBiggestJump = 0;
int BiggestDiff = 0 ;
int CurrentDiff = BiggestDiff;
for(int i = 0; i < sequence.size() - 1; i++) {
CurrentDiff = std::abs(sequence[i] - sequence[i + 1]);
if (CurrentDiff > BiggestDiff)
{
BiggestDiff = CurrentDiff;
indexOfBiggestJump = i;
}
}
return indexOfBiggestJump;
}
There are several errors in your code.
your return index literally does nothing, only returns index (which will be 0) always.
you are not saving the index of the biggest jump anywhere.
if you are looking positions i and i + 1, you must go until sequence.size() - 1, otherwise you will look out of the bounds of sequence.
You aren't recalculating CurrentDiff at all. Also, your return statement in the in the wrong spot. You can do something like this (not tested)
int findLargest( const std::vector<int> &sequence ) {
if ( sequence.size() < 2 ) return -1; // if there's not at least two elements, there's nothing valid.
int index = 0;
int biggestIndex = -1;
int biggestDiff = -1;
while (index < sequence.size() - 1) // -1 so that the +1 below doesn't go out of range
{
// get the current difference
int currentDiff = std::abs(sequence[index] - sequence[index + 1]);
if (currentDiff > biggestDiff)
{
// update stats
biggestIndex = index;
biggestDiff = currentDiff;
}
++index;
}
return biggestIndex
}
int main() {
//…
int index = findLargest( sequence );
if ( index != -1 ) {
std::cout << "Biggest difference was between " << sequence[index] << " and " << sequence[index+1];
}
}

Binary search not working for n = 1, 2

This is my code for binary search, and n = no of elements in array
// Binary Search
// BUG: not working for n = 2
#include <iostream>
int main() {
const int n = 1;
int newlist[n];
std::cout << "Enter " << n;
std::cout << " elements in increasing order:\n";
for( int i = 0; i < n; ++i ) {
std::cin >> newlist[i];
}
int pos = 0, num;
std::cout << "Enter number:\n";
std::cin >> num;
std::cout << '\n';
int imin = 0, imax = n-1;
int imid = (n - 1)/2;
for( int i = 0; i < n; ++i ) {
imid = (imin + imax) / 2;
if( newlist[imid] == num ) {
pos = imid;
}
else if( newlist[imid] < num ) {
imin = imid+1;
}
else {
imax = imid-1;
}
}
if( pos != 0 ) {
std::cout << "Found at " << pos+1;
}
else {
std::cout << "Not found!\n";
}
return 0;
}
It does work for n > 2, but fails to give correct output for n <= 2, ie, gives Not found! output even for elements that were found.
I think one way would be to have a separate implementation for n <= 2, but that will become cumbersome! Please help.
Set your pos operator to -1 rather than 0. 0 represents your first index and since you output that the element has not been found for pos == 0 condition, your code is failing. You should set pos to -1 initially and check that itself for not found condition, if an element is found at pos = 0, that means the element exists at the first index.
First pos equal to 0 is correct value. Therefore set pos to -1 at the beginning and compare to -1 (or more commonly >= 0) when checking whether it was found.
Secondly, there are few items that should be changed because right now it's not that much binary search:
There is no reason to initialize mid before the loop, it's just temporary variable with the scope in loop block.
The condition for exiting the search is min > max, you don't need any additional counter, as it would run the loop always n times even if the value didn't exist. So change to while (min <= max) { ...
Last but not least, once you find the item, exit the loop immediately by break statement.
I don't think a for-loop is the control structure to go for here, because you want to finish when you've either found the correct item or when imin and imax are non-sensical.
In the implementation given, you don't even stop the loop when you have found the item and just confirm the found item "n-(number of iterations until item was found)" times.
Furthermore, with C++ arrays and vectors being 0-based, having position == 0 as the marker for "not found" is a bad idea; you could instead use an item from http://en.cppreference.com/w/cpp/types/numeric_limits, or n (since the indices go from 0 to n-1).
In theory, you could use pointer arithmetic to make your array 1-based, and I am assuming you haven't; I wouldn't recommend it. However, you're code snipped is missing the actual definition of the list.

Binary Search in 2D Array 3

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

C++: Binary Search Part of a String

I am now on part 4 of my homework, I am trying to figure out how to Binary Search just the first 14 characters from an array of strings. We were given two .csv files:
The 01110011100110 is a simulated barcode.
Inventory.csv: Inventory items separated by a comma - Barcode, product, price
First Five Lines:
01001010100011,Air freshener,12.43
01101000111101,Alfredo sauce,10.71
10000010100101,All spice,4.14
00011011001111,Allergy medication,20.06
00101010111011,Aluminum foil,8.92
Carts.csv: A 'cart' containing barcodes of purchases
First Five Lines:
01000011010100,00010011010100
00110111100000
00100110100000,01011000110111,01011101000110,01011101000000,01001110000010
01110101100101,00100111110101,00101101110110,00100110000000,00100000001100,00101101011100
00101100111110,01000110110000,01010110111110,00100111111001,01011101101010,01011011010011,00010011010100,01010111101001
I am working on Part4 of the homework:
Part 4: Write a function to read in the Carts.csv file. Read in one line at a time and process it. The process steps are:
a. Separate the barcodes in each cart based on the comma delimiter.
b. For each barcode, lookup the barcode in the product list.
c. Extract the price from the product string data line and add it to a running total for the cart.
d. After processing the line, output the total price for the cart.
e. Repeat from step (a) until end-of-file.
When I try to lookup it's returning -1, it is comparing the whole line rather than just part of it. How do Binary Search just part of a string. Here is the excerpt of my code:
int binarySearch(string* list, int size, string value){
int first = 0,
last = size - 1, middle,
position = -1;
bool found = false;
while (!found && first <= last){
middle = (first + last) / 2;
if (list[middle].compare(value) == 0){
found = true;
position = middle;
}
else if (list[middle].compare(value) > 0)
last = middle - 1;
else
first = middle + 1;
}
return position;
}
void processFile(string filename, string* list, int size){
ifstream file(filename);
string line;
int count = 1;
if (file.is_open()){
while (!file.eof()){
int ctr = 0;
int start = 0;
getline(file, line);
string substring = "";
int find = line.find(COMMA);
cout << "Cart " << count << ": ";
while (find != string::npos){
substring = line.substr(start, find - start);
int position = binarySearch(list, size, substring);
cout << position << " ";
start = find + 1;
ctr++;
find = line.find(COMMA, start);
}
if (ctr > 0 || find == -1){
substring = line.substr(start, line.length() - start);
int position = binarySearch(list, size, substring);
cout << position << endl;
count++;
}
}
}
file.close();
}
try the following function realization
int binarySearch( const std::string* list, int size, std::string value )
{
int position = -1;
int first = 0, last = size - 1;
while ( first <= last )
{
int middle = ( first + last ) / 2;
int result = list[middle].substr( 0, value.size() ).compare( value );
if ( result == 0 )
{
position = middle;
break;
}
else if ( result > 0 )
{
last = middle - 1;
}
else
{
first = middle + 1;
}
}
return position;
}
Of course array list must be sorted according to barcodes in the ascending order.