Java - Trying to print all of the coincidences of a binary search - java

This is my current search method:
public static int search(int[] array, int numero) {
int start = 0;
int end = array.length - 1;
int center;
while (start <= end) {
center = (start + end) / 2;
if (array[center] == numero) {
return center;
} else if (array[center] < numero) {
start = center + 1;
} else {
end = center - 1;
}
}
return -1;
}
It searches from user input numero into a previously bubble sorted Array that's found in the Main method.
What I'm trying to figure out is how to print ALL of the coincidences found in the array, and not just the first one found.
I was thinking about adding results to a List and then returning that to Main, but as I tried that an endless loop happened at the first result found, causing it to add itself to the List repeatedly until the program crashes.

Assuming that you know the basic theory behind binary searches, separate it into 3 steps.
Search using binary search methods.
once a match is found, scan up from that point, until you find a non matching element.
Scan down, adding to a result list, until you find a non
matching element.
If you don't need to care about occurrence order, you could combine steps 2 and 3 and just scan up adding to the list, and scan down adding to the list, since due to the sorting, everything you hit is guaranteed to match until it doesn't.
If you do care about occurrence order, step 2 could be optimised by jumping ahead and checking, and writing a modified binary search that searches for a transition of matching/notmatching instead of a match.
This could be further optimised by keeping statistics or profiling, to find the perfect jump distance, or basing it off of the last up-most check.

actually it's easy because the list is already sorted, the numbers you expect to find are adjacent.
just like Ryan's answer, I'll put some code
public static List<Integer> searchAll (int[] array, int numero){
int firstMatchIndex = search( array, numero);
List<Integer> results = new ArrayList<Integer>():
results.add(firstMatchIndex);
boolean left = true;
while( left){
int i = firstMatchIndex - 1;
if(i<0 || array[i] != numero){
left = false;
}else{
results.add(i);
}
}
boolean right = true;
while( right){
int i = firstMatchIndex + 1;
if(i>array.length || array[i] != numero){
right = false;
}else{
results.add(i);
}
}
}

Related

the output of my Interpolation search is wrong, why?

I have to write a Program which is called "Interpolation search". I came so far but now I am stuck and can´t find the error in my code.
The method split() makes a problem. This method should give me the index to split. I just typed the formula in this method. Now the big problem is, I every time get 1 as an output which is always the "leftBoundary". For example, I write in my terminal java Search 4 1 2 3 4 5 6 then I get every time 1. Why? what is wrong?
edit:
I was asked to explain what the split method does in Detail:
This method uses the formula (look at added picture) to determine where to split the (sorted) array and returns the corresponding index.
In the picture: v = wantedValue, l = leftBoundary, r = rightBoundary
enter image description here
import java.util.Scanner;
public class Search {
// This method uses the formula (look at added picture) to determine where to split the (sorted) array and returns the corresponding index.
private static int split(int[] haystack, int needle, int left, int right) {
if(haystack[right] == haystack[left]) {
return left;
}else {
needle = left + ((needle - haystack[left]) / (haystack[right] - haystack[left])) * (right - left);
return needle;
}
}
private static int search(int[] haystack, int needle) {
return -1;
}
public static void main(String[] args) {
int[] array = new int[args.length];
int leftBoundary = 1;
int rightBoundary = array.length - 1;
int wantedValue = Integer.parseInt(args[0]);
for(int i = 1; i < args.length; i++) {
array[i] = Integer.parseInt(args[i]);
}
int splitAtIndex = split(array, wantedValue, leftBoundary, rightBoundary);
System.out.println(splitAtIndex);
}
}
I tried to debug but with no success and also searched here on stackoverflow. Many have question to interpolation search, but the answers are complex and unfortunately do not explain the exact problem I have
Apart from the comment, by #user16320675, to your question, your initialization is wrong.
The first [command-line] argument is the value of wantedValue. The remaining [command-line] arguments are the elements of array.
Also, leftBoundary should be 0 (zero) and not 1 (one) since you probably want to search the whole array.
Consider the following code:
public class Search {
private static int split(int[] haystack, int needle, int left, int right) {
if (haystack[right] == haystack[left]) {
return left;
}
else {
return (int) (left + ((double) (needle - haystack[left]) / (haystack[right] - haystack[left])) * (right - left));
}
}
public static void main(String[] args) {
int[] array = new int[args.length - 1];
int leftBoundary = 0;
int rightBoundary = array.length - 1;
int wantedValue = Integer.parseInt(args[0]);
for (int i = 1; i < args.length; i++) {
array[i - 1] = Integer.parseInt(args[i]);
}
int splitAtIndex = split(array, wantedValue, leftBoundary, rightBoundary);
System.out.println(splitAtIndex);
}
}
I removed the import statement since Scanner is not used. I also removed method search since it is never called.
If I run the above code using your example [command-line] arguments, i.e.
4 1 2 3 4 5 6
then method search returns 3 — which is the index of the searched-for element in the array since 4 is the searched-for value and the array contains the numbers 1 to 6 (inclusive).
Of-course, the array being searched must be sorted.
Note that if the searched-for value is smaller than the first array element, i.e. the element at index 0 (zero), method search will return -1 (minus one) and if the searched-for value is greater than the last element in the array, method search will return the array length. Hence you can determine whether the searched-for value is not found in the array.
If the [command-line] arguments are:
4 1 2 3 5 6
then method search returns 2. Note that the searched-for value, i.e. 4, is not in the array.
It is probably also a good idea to check the parameters of method search, i.e. that right should not be less than left and that haystack contains at least one element.

Binary Search Java

Im working on a project in which it reads book titles in from a .txt file and puts them into an arraylist, then the arraylist is converted to an array, The user enters a number which is the books reference number, then it does a linear search and a binary search to find that book. Im just having a trouble with the code for the binary search,as i have almost no idea how to do it, heres what I have:
private void FindItActionPerformed(java.awt.event.ActionEvent evt) {
String input;
input = Input.getText();
for(int i=0; i<bookList.length; i++){
if (bookList[i].referenceNumber.equals(input)){
Output1.setText("The Book is " + bookList[i].title);
}
}
Above is the code for the linear search, which works fine. Below is what i think i need for the binary search but again, i am not sure and cannot figure it out.
int right = 0, left = bookList.length;
while(right<= left){
int middle = (right + left)/2;
if( bookList[middle].referenceNumber.equals(input)){
Output2.setText("The book is " + bookList[middle].title);
}
}
}
Here is the class and the arrays
public class Book{
String referenceNumber, title;
public Book(String _referenceNumber, String _title){
referenceNumber = _referenceNumber;
title = _title;
}
}
ArrayList <Book> Books = new ArrayList <Book> ();
Book [] bookList;
Thanks for any help you may be able to offer, This is a bit tricky for me.
I had problems when I was learning to code binary search aswell. The first thing you should know is that you do not have to do a binary search and a linear search, you only need to do one or the other. Also to do a binary search you need to sort your array ex int[] array = {1,2,3,4,5,6,7,8,9,10};
What a binary search does is it looks at the middle element in the array and tests to see if the element is greater or less than the key. If it is less everything less then the middle element is ignored (same for bigger just everything bigger is thrown away). Then a new middle element is selected and half is thrown away, and this is done until the key is found. Below is the code for sorting a int array, you would need to modify it to return books (string? or the class book you may have written)
public static boolean binarySearch(int[] array, int key){
int partition = 0;
int right = array.length - 1;
boolean found = false;
int left = 0;
while(! found && left <= right){
if(array[partition] == key){
found = true;
}
if(array[partition] > key){//key less
right = partition - 1;
partition = (right + left) / 2;
}
if(array[partition] < key){//key greater
left = partition + 1;
partition = (left + right) / 2;
}
}
return found;
}
Also here is some code for sorting an array of ints. This is a bubble sort so it is slow On^2
public int[] bubbleSort(int[] array){
int temp;
boolean keepGoing = true;
while(keepGoing == true){
keepGoing = false;
for(int i=0; i < array.length - 1; i++){
if(array[i] > array [i + 1]){ //if i < i + 1 means greatest to smallest if
// if i > i + 1 means smallest to greatest
swap(array, i, i + 1);
keepGoing = true;
}
}
}
return array;
}
The code is simple would have to modify it to sort your books the method swap is below
public int[] swap(int[] array, int i, int j){
int temp = 0;
temp = array[i];
array[i] = array[j];
array[j] = temp;
return array;
}
There is nice visualisation of binary search at
http://balance3e.com/Ch8/search.html
For example try to enter FL and watch the algorithm looking for it step by step.
You will get it quickly :)
It works like looking up a word in a dictionary... You are looking for "cat" for example,
so you open your dictionary in half and see word "man" this is lexicographicaly bigger than "cat", so you will be looking to the left from "man" = in first half of the dictionary...
Then you only repeat this process of dividing into smaller parts until you find what you were looking for.

JavaFX Binary Search - Issue with loop

I have 6 text fields (number1-6) in JavaFX and another textfield named "textfieldLF" that is the number that the user is searching for. I am trying to make a JavaFX program for searching between 6 different numbers using the binary search algorithm, but for some reason it's not working.
I used the algorithm from Wikipedia. I checked the indexes of arrays to make sure they are right, because the first if condition and statement works perfectly alone. It's only when it wants to determine what change it has to make to the midpoint that I think it has a problem in.
The code:
#FXML
private void handleButtonAction(ActionEvent event) {
// First and last indexes declaration
int imin = 1;
int imax = 6;
// Declare array for user inputs
String[] NumbersArray = {number1.getText(), number2.getText(), number3.getText(), number4.getText(), number5.getText(), number6.getText()};
// What to find? Get input from user
String ToFind = textfieldLF.getText();
// Match Index
String MatchID;
// Match Found? Boolean
boolean MatchFound = false;
// Find midpoint
int imid = (int) ceil((double)((imin + imax) / 2));
while (MatchFound = false)
{
// Try to find match in midpoint position
if (NumbersArray[imid].equals(ToFind))
{
System.out.println("Match #" + (imid + 1));
MatchFound = true;
} else if(Integer.parseInt(NumbersArray[imid]) < Integer.parseInt(ToFind)) {
imin = imid + 1;
MatchFound = false;
} else {
imax = imid - 1;
MatchFound = false;
}
}
}
I would appreciate any help
Thanks
It doesn't work, since you never change imid. It's also no binary search, since doesn't reduce the index range by half every step.
Move
int imid = (int) ceil((double)((imin + imax) / 2));
inside the loop(to the beginning of the loop body). You still have to add a way to exit the loop.
Also your start indices are wrong. The index range of your array is 0-5 and not 1-6.

Merge sort remove duplicates

I am trying to sort an array via merge sort, and while sorting, remove elements that I have deemed equal. I am recursively calling merge sort and then merging.
I get to this point and find that a and c are duplicates.
a b | c d
I determine which one I want based on certain criteria and I pick c. I increment the right hand counter and and the left hand counter and compare b and d. Say I pick d, then I pick b. I want my final list to only have the elements
c d b
However, what is happening is on the next recursive call, start and end are 0 and 3 so d is listed twice in the array on the next call. The array that the merge procedure works with is:
c d b d
Here is the code. Thanks in advance.
private static void merge(int[] data, int start, int mid, int end)
{
int firstCopied=0;
int secondCopied=0;
int index=0;
int length=end-start+1;
int[] temp = new int[end-start+1];
int firstSize=mid-start+1;
int secondSize=end-mid;
while(firstCopied < firstSize && secondCopied < secondSize)
{
if(data[start+firstCopied] < data[mid+1+secondCopied])
{
temp[index++] = data[start+firstCopied];
firstCopied++;
}
else if(data[start+firstCopied] > data[mid+1+secondCopied])
{
temp[index++] = data[mid+1+secondCopied];
secondCopied++;
}
else if(data[start+firstCopied]==data[mid+1+secondCopied])
{
boolean result = PickOne();
if(result)
{
temp[index++] = data[start+firstCopied];
}
else
{
temp[index++] = data[mid+1+secondCopied];
}
firstCopied++;
secondCopied++;
length--;
}
}
while(firstCopied < firstSize)
{
temp[index++] = data[start+firstCopied];
firstCopied++;
}
while(secondCopied < secondSize)
{
temp[index++] = data[mid+1+secondCopied];
secondCopied++;
}
for(int i=0; i<length; i++)
{
data[start+i]=temp[i];
}
}
The philosophy of the C++ Standard Library is to use algorithms that do one thing well. It's best to follow that approach since it will lead to more reusable code.
E.g. here's a mergesort sketch followed by a call to std::unique
template<typename BiDirIt>
void merge_sort(BiDirIt first, BiDirIt last)
{
auto const N = std::distance(first, last);
if (N < 2) return;
// sort each part individually, then merge back in-place
auto middle = first + N / 2;
merge_sort(first, middle);
merge_sort(middle, last);
std::inplace_merge(first, middle, last);
}
int data[] = { /* your data */ };
merge_sort(std::begin(data), std::end(data));
auto it = std::unique(std::begin(data), std::end(data));
for (auto ut = std::begin(data); ut != it; ++ut) {
// process unique data
}
If your data was in a std::vector instead of a C-array, you could call v.erase(v.begin(), it); to actually erase the non-unique data as well.
Your merge conceptually changes the length of the array. But there is no code to actually truncate data. I suggest you return length (instead of void) and use some final postprocessing step to either truncate the data to the final length, or at least avoid printing those past-the-end elements.
Make sure the elements in [start, mid] and [mid + 1, end] is sorted and unique, first.
Otherwise, duplicates will exists after your code run.

Binary Search Algorithm from a Sorted list

My algorithm is suppose to tell me if 'x'(which has the value 5) is in the sorted array. However, I keep getting a 0. Well since my condition states that if 'x' is not in the array show 0. Where am I going wrong?
import java.util.Arrays;
public class binarySeacg {
public static void main (String[]args)
{
int[] array = {10,7,11,5,13,8};
exchangesort(array);
binsearch(array,5);
System.out.println(Arrays.toString(array));
}
public static void exchangesort(int[] S)
{
int i,j,temp;
for(i=0;i<S.length;i++)
for(j=i+1;j<S.length;j++)
if(S[i]>S[j])
{
temp = S[i];
S[i] = S[j];
S[j] = temp;
}
}
public static int binsearch(int[] S, int x)
{
int location, low, high, mid;
low = 1; high = S.length;
location = 0;
while(low<=high && location==0)
{
mid =(low + high)/2;
if(x== S[mid])
location = mid;
else if(x < S[mid])
high = mid -1;
else
low = mid + 1;
}
System.out.println(location);
return location;
}
}
You set low = 1;, and 5 is the minimal element - so it is in index 0 - so in the sublist of [1,S.length] - it is indeed not there.
You should set low = 0;, and start from the first element - not the second. (Remember that index in java starts from 0, not 1).
(PS, note that in this specific case - the algorithm is correct, since in the sorted list - 5 is in the index 0).
Here you are sorting an array and then the sorted array is used for searching the element.
And if the search is successful, then you do the below assignment
location = mid; which means you are assigning the matching element's index to the location variable.
In this case, element 5 is in 0th index.
Hence you are always getting 0 on your STDOUT
Because, you are trying to find x value, which you are passing 3 and in your list. It is not present. So, change it to other value like 5 and then try.
Also, you should start low=0 instead of low=1. Because, it will miss the first element all the time.
public static int binsearch(int[] S, int x)
{
int location, low, high, mid;
low = 0; high = S.length;
location = 0;
while(low<=high && location==0)
{
mid =(low + high)/2;
if(x == S[mid])
{
location = mid;break;
}
else if (x < S[mid])
{
high = mid - 1;
} else
{
low = mid + 1;
}
}
System.out.println(location);
return location;
}
Note : For the different output, change the value binsearch(array,5); here, which is called from main() method. Remember, change the value, which are present in your list.
in java and most languages, the index starts from 0, not 1, and ends at n-1, not n
for binary search, check carefully about when exiting the while loop, and always remember the meaning of your low and high variables, whether it is [low, high], or [low, high)
for this specific problem, u should also consider what if there r duplicates in the array. whether to return the first element or anyone in the array

Categories

Resources