Making a binary search function - java

I am working on a homework task where I am supposed to make a function that will do a binary insertion sort, but my function does not seem to work properly.
Here I have tried to combine a binary search function with a insertion sort function (it is specified in the homework task that it needs to be in the form of a function: insertionSort(int[] array, int lo, int hi))
public static void insertionSort(int[] array, int lo, int hi){
int mid;
int pos;
for (int i = 1; i < array.length; i++) {
int x= array[i];
while (lo < hi) {
mid = lo + (hi -lo)/2;
if (x == array[mid]) {
pos = mid;
}
if (x > array[mid]) {
lo = mid+1;
}
else if (x < array[mid]) {
hi = mid-1;
}
}
pos = lo;
for (int j = i; j > pos; j--) {
array[j] = array[j-1];
}
array[pos] = x;
}
}
If I try to run it with the list {2,5,1,8,3}, the output will be
2 5 1 3 1 (if lo < hi and if lo > hi)
2 5 3 8 5 (if lo==hi)
What I am expecting though, is a sorted list...
Any idea of what I am doing wrong?

Just to give you a possible idea:
public static void insertionSort(int[] array) {
if (array.length <= 1) {
return;
}
// Start with an initially sorted part.
int loSorted = array.length - 1;
//int hiSorted = array.length;
while (loSorted > 0) {
// Take one from the array
int x = array[0];
// Where in the sorted part to insert?
int insertI = insertPosition(array, loSorted);
// Insert x at insertI
...
--loSorted;
}
}

whenever I need binary search, my function looks the following way:
public static void binarySearch(int arr[], int first, int last, int key){
int mid = (first + last)/2;
while( first <= last ){
if ( arr[mid] < key ){
first = mid + 1;
}else if ( arr[mid] == key ){
System.out.println("Element is found at index: " + mid);
break;
}else{
last = mid - 1;
}
mid = (first + last)/2;
}
if ( first > last ){
System.out.println("Element is not found!");
}
}
In your main method the call looks like:
public static void main(String[] args) {
int arr[] = {10,20,30,40,50};
int key = 30;
int last=arr.length-1;
binarySearch(arr,0,last,key);
}
I hope I was able to help you!

Thank you for your input. I changed the function a little bit, and it seems to be working now
` public static void insertionSort(int[] array, int lo, int hi){
int mid;
int pos;
for (int i = 1; i < array.length; i++) {
int j = i -1;
int x = array[i];
while (lo <= hi) {
mid = lo + (hi -lo)/2;
if (x == array[mid]) {
pos = mid;
break;
}
if (x > array[mid]) {
lo = mid+1;
}
else if (x < array[mid]) {
hi = mid-1;
}
}
while (j >= 0 && array[j] > x) {
array[j + 1] = array[j];
j = j - 1;
}
array[j + 1] = x;
}
}
the problem seemed to lay in the last part, where I was trying to move the elements into their right positions. The function is probably not perfect tho, so constructive criticism is welcome :)

Related

How can I show the value of array with the Binary Search Tree of Comparison?

I going to do searching the value in the array, did I need to create a method to handle it? For example, the array logged 32,21,13,44,22, and I going to find 22 of the comparison. How can I implement this?
public class binarySearch {
public static void main(String [] args) {
int i = binarySearch(0, new int[]{32,21,13,44,22});
System.out.println("Iterations: " + i);
}
public static int binarySearch(int key, int[] array) {
int left = 0;
int mid;
int right = array.length - 1;
int i = 0;
while (left <= right) {
mid = (left + right) / 2;
int comp = Integer.compare(key, array[mid]);
i++;
if (comp < 0) {
right = mid - 1;
} else if (comp > 0) {
left = mid + 1;
} else {
break; // success
}
}
return i;
}
}
My final answer is here. May help you all in the future.
public static int binarySearch(int key, int[] array) {
int left = 0;
int mid;
int right = array.length - 1;
int i = 0;
while (left <= right) {
mid = (left + right) / 2;
int comp = Integer.compare(key, array[mid]);
i++;
if (comp < 0) {
right = mid - 1;
} else if (comp > 0) {
left = mid + 1;
} else {
break; // success
}
}
return i;
}
If you have shuffled array, all you can do is go through an array and find your number.
BinarySearch works only with sorted array. I think your solution could look like this:
public static int binarySearch(int[] arr, int key) {
Arrays.sort(arr);
return Arrays.binarySearch(arr, key);
}

Tim sort implementation working at low array size but crashing at high

Basically i built this rudementary tim sort built for a simple project and it works with a sub of 32 all the way up to 1000 integers (the next thing i tried was 5000) and then it crashes with a index out of bounds exeception i tried increasing the sub to 64 but it just dosent seem to work i was wondering if anyone could tell me what im doing wrong here.
public static void timSort(List<Comparable> nums) {
int sub = 32;
for (int i = 0; i < nums.size(); i += sub)
{
if((nums.size() -1) < (i + 31)) {
inPlaceInsertion(nums, i, (nums.size() - 1));
}else {
inPlaceInsertion(nums, i, (i + 31));
}
}
for (int size = sub; size < nums.size(); size = 2 * size)
{
for (int left = 0; left < nums.size(); left += 2 * size)
{
int mid = left + size - 1;
int right;
if((nums.size() - 1) < (left + 2 * size - 1)) {
right = nums.size() -1;
}else {
right = left + 2 * size -1;
}
merge(nums, left, mid, right);
}
}
}
public static void inPlaceInsertion(List<Comparable> nums, int first, int last){
for(int i = first; i <= last; i++){
Comparable hold = nums.get(i);
int j;
steps++;
for(j = i; j > first && hold.compareTo(nums.get(j - 1)) < 0; j--) {
nums.set(j, nums.get(j - 1));
steps+=4;
}
nums.set(j, hold);
steps++;
}
}
private static void merge(List<Comparable> nums, int first, int mid, int last){
List<Comparable> newList = new ArrayList<Comparable>();
int loopCountA = 0;
int loopCountB = 0;
while(true) {
if(loopCountB == (last - mid)) {
while(first + loopCountA <= mid) {
newList.add(nums.get(first + loopCountA)); loopCountA++;
steps++;
}
break;
}else if(first + loopCountA > mid) {
while(loopCountB < (last - mid)) {
newList.add(nums.get(mid + (loopCountB + 1))); loopCountB++;
steps++;
}
break;
}else {
if(nums.get(mid + (loopCountB + 1)).compareTo(nums.get(first + loopCountA)) < 0) {
// here is where error is (line above)
newList.add(nums.get(mid + (loopCountB + 1)));
steps += 5;
loopCountB++;
}else {
newList.add(nums.get(first + loopCountA));
steps += 5;
loopCountA++;
}
}
}
for(int i = 0; (i - 1) < (last - first); i++) {
nums.set(first + i, newList.get(i));
steps+=2;
}
}
Here's the error...
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 5024 out of bounds for length 5000
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:372)
at java.base/java.util.ArrayList.get(ArrayList.java:458)
at Sorts.merge(Sorts.java:772)
at Sorts.timSort(Sorts.java:1193)
at Sorts.sortMenu(Sorts.java:255)
at Sorts.main(Sorts.java:33)
Simple main method which demonstrates it not working
int depthLimit
= (int)(2 * Math.floor(Math.log(nums.size()) /
Math.log(2)));
introSort(nums, 0, nums.size() -1, depthLimit);

Find the largest index occurrence of a number using binary search

This code, generates a random number, sorts it in ascending order and does the binary search to find a target value. MY QUESTION IS HOW DO I MODIFY THIS CODE TO FIND THE LARGEST INDEX OF THE GIVEN TARGET. For example the array has { 1, 2 , 3, 5, 5, 5, 5}, the target is 5, so the output should be 6 instead of 3. Thankyou.
import java.util.*;
public class Sort
{
public static void main(String args[])
{
Scanner in = new Scanner(System.in);
System.out.print("How many numbers do you want? ");
int howMany = in.nextInt();
int [] myArray = getSortedRandomArray(howMany);
System.out.print("\nFor what value would you like to search? ");
int target = in.nextInt();
int index = bsearch ( myArray, target);
if (index >= 0)
{
System.out.println("The value " + target + " occurs at index " + index);
}
else
{
System.out.println("The value " + target + " does not occur in the array. ");
}
}
public static int bsearch(int[] arr, int key)
{
int lo = 0, hi = arr.length - 1;
{
while (lo < hi)
{
int mid = (lo + hi) / 2;
if (arr[mid] <= key)
lo = mid + 1;
if (arr[mid] > key)
hi = mid;
}
if (arr[lo] == key) {
return lo;
}
else if ((arr[lo] != key) && (arr[lo-1] == key)){
return lo - 1;
}
else{
System.out.print("The value " + key + " does not occur in the array. ");
}
return -1 ;
}
public static int[] getSortedRandomArray (int howMany)
{
int[] returnMe = new int [howMany];
Random rand = new Random();
for (int i = 0; i < howMany ; i++)
returnMe[i] = rand.nextInt(Integer.MAX_VALUE) + 1;
for (int i = 1; i <= (howMany - 1); i++)
{
for (int j = 0; j <= howMany - i -1; j++)
{
int tmp = 0;
if (returnMe[j] > returnMe[j+1])
{
tmp = returnMe[j];
returnMe[j] = returnMe[j + 1];
returnMe[j + 1] = tmp;
}
}
}
System.out.print("Here is a random sorted array: ");
for ( int i = 0; i < howMany; i++)
System.out.print(returnMe[i] + " ");
return returnMe;
}
You can do this by modifying the binary search algorithms code like this:
public static int bsearch(int[] arr, int key) {
int lo = 0, hi = arr.length - 1;
while (lo < hi) {
int mid = (lo + hi) / 2;
if (arr[mid] <= key)
lo = mid + 1;
if (arr[mid] > key)
hi = mid;
}
if (arr[lo] == key) {
return lo;
}
else {
return lo - 1;
}
}
This code instead searches for the first number larger than key. That can be any number, 6 or 10000, it doesn't matter. As you can see, if arr[mid] is equal to key, the code will still run on the interval [mid, hi]. Why those two returns at the end? Well if input array is like the one you gave, lo will end being the index of the last 5, but if we add another number at the end of input array, lo will be index of the number behind the last 5. Therefore, we have 2 different cases.
Also, you can't do it with a linear loop like other answers, because that reduces the algorithm to O(n) and it ends just being a linear search on a reduced array.
If you update your bsearch algorithm a little you can ask it to seek higher matches recursively. However whether this is more efficient than a linear loop would depend on what the input array looked like.
public static int bsearch(int[] arr, int key, int lo, int hi) {
while (lo <= hi) {
int mid = (lo + hi) / 2;
if (arr[mid] == key) {
System.out.println("The value " + key + " is found at " + mid);
int higherResult = bsearch(arr, key, mid + 1, hi);
if (higherResult < 0) {
return mid;
}
return higherResult;
}
if (arr[mid] < key) {
lo = mid + 1;
} else {
hi = mid - 1;
}
}
return -1;
}

Quicksort with duplicate values

I have this java code for QuickSort that works if there are no duplicates, however if there are any duplicates, the QuickSort fails. For example, if I want to QuickSort {5,3,3,1,7} my code will output {1,3,3,7,5}, and I can't seem to figure out why this is the case.
public static void quickSort(Integer[] nums) {
quickSort(nums, 0, nums.length-1);
}
private static void quickSort(Integer[] ary, int lo, int hi) {
//pick num # lo to be pivot
int pivot = lo;
int i = lo+1;
int j = hi;
if( lo==hi) {
return;
}
while(i <j) {
if(ary[i].compareTo(ary[pivot]) <=0 ) {
i++;
}
else if(ary[j].compareTo(ary[pivot]) >=0 ) {
j--;
}
else {
int temp = ary[i];
ary[i] = ary[j];
ary[j] = temp;
}
}
if(i == hi && j == hi) {
if(ary[pivot].compareTo(hi) > 0) {
int temp = ary[pivot];
ary[pivot] = ary[hi];
ary[hi] = temp;
pivot = hi;
}
else {
int temp1 = ary[pivot];
ary[pivot] = ary[i-1];
ary[i-1] = temp1;
pivot = i-1;
}
}
if(lo < pivot -1) {
quickSort(ary, lo, pivot-1);
}
if(pivot +1 < hi) {
quickSort(ary, pivot+1, hi);
}
}
If anyone could tell me what I'm doing wrong, that would be greatly appreciated!
Hi i have modified your code, please check corresponding comments
private static void quickSort(Integer[] ary, int lo, int hi) {
//pick num # lo to be pivot
int pivot = lo;
int i = lo+1;
int j = hi;
if( lo==hi) {
return;
}
//while(i <j) {
for(;;){//change from while to infinite for
while(ary[i].compareTo(ary[pivot]) <=0 && i<hi ) {//changed from if to while with boundary conditions
i++;
}
while(ary[j].compareTo(ary[pivot]) >0 && j>lo) { //change from if to while with boundary conditions and it is not >=0 only >
j--;
}
if(i<j){ //changed from else to if
int temp = ary[i];
ary[i] = ary[j];
ary[j] = temp;
}else{//added else block
break;
}
}
//you didn't handled i>j condition properly i.e when i>j you need to swap pivot and i-1
int temp1 = ary[pivot];
ary[pivot] = ary[i-1];
ary[i-1] = temp1;
pivot = i-1;
//Not required
/*if(i == hi && j == hi) {
if(ary[pivot].compareTo(hi) > 0) {
int temp = ary[pivot];
ary[pivot] = ary[hi];
ary[hi] = temp;
pivot = hi;
}
else {
int temp1 = ary[pivot];
ary[pivot] = ary[i-1];
ary[i-1] = temp1;
pivot = i-1;
}
}*/
if(lo < pivot -1) {
quickSort(ary, lo, pivot-1);
}
if(pivot +1 < hi) {
quickSort(ary, pivot+1, hi);
}
}
Thanks
if you want to quicksort use the algorithm from this site.
Quicksort
It works for me and the explanation is quite good I think.

Java BinarySearch

Can I get some help please? I have tried many methods to get this to work i got the array sorted and to print but after that my binary search function doesnt want to run and give me right results. It always gives me -1. Any help?
public class BinarySearch {
public static final int NOT_FOUND = -1;
public static int binarySearch(double[] a, double key) {
int low = 0;
int high = a.length -1;
int mid;
while (low<=high) {
mid = (low+high) /2;
if (mid > key)
high = mid -1;
else if (mid < key)
low = mid +1;
else
return mid;
}
return NOT_FOUND;
}
public static void main(String[] args) {
double key = 10.5, index;
double a[] ={10,5,4,10.5,30.5};
int i;
int l = a.length;
int j;
System.out.println("The array currently looks like");
for (i=0; i<a.length; i++)
System.out.println(a[i]);
System.out.println("The array after sorting looks like");
for (j=1; j < l; j++) {
for (i=0; i < l-j; i++) {
if (a[i] > a[i+1]) {
double temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
}
}
}
for (i=0;i < l;i++) {
System.out.println(a[i]);
}
System.out.println("Found " + key + " at " + binarySearch(double a[], key));
}
}
you are not actually comparing with the array values. in
while (low <= high) {
mid = (low + high) / 2;
if (mid > key) {
high = mid - 1;
} else if (mid < key) {
low = mid + 1;
} else {
return mid;
}
}
Instead use this section
while (low <= high) {
mid = (low + high) / 2;
if (a[mid] > key) {
high = mid - 1;
} else if (a[mid] < key) {
low = mid + 1;
} else {
return mid;
}
}
You were correct to find the indexes, but what you were doing is that you were just comparing index number with your key, which is obviously incorrect. When you write a[mid] you will actually compare your key with the number which is at index mid.
Also the last line of code is giving compile error, it should be
System.out.println("Found " + key + " at " + binarySearch(a, key));
Here
if (mid > key)
high = mid -1;
else if (mid < key)
low = mid +1;
else
return mid;
You're comparing index to a value (key) in array. You should instead compare it to a[mid]
And,
System.out.println("Found " + key + " at " + binarySearch(double a[], key));
Should be
System.out.println("Found " + key + " at " + binarySearch(a, key));
public static double binarySearch(double[] a, double key) {
if (a.length == 0) {
return -1;
}
int low = 0;
int high = a.length-1;
while(low <= high) {
int middle = (low+high) /2;
if (b> a[middle]){
low = middle +1;
} else if (b< a[middle]){
high = middle -1;
} else { // The element has been found
return a[middle];
}
}
return -1;
}
int binarySearch(int list[], int lowIndex, int highIndex, int find)
{
if (highIndex>=lowIndex)
{
int mid = lowIndex + (highIndex - lowIndex)/2;
// If the element is present at the
// middle itself
if (list[mid] == find)
return mid;
// If element is smaller than mid, then
// it can only be present in left subarray
if (list[mid] > find)
return binarySearch(list, lowIndex, mid-1, find);
// Else the element can only be present
// in right subarray
return binarySearch(list, mid+1, highIndex, find);
}
// We reach here when element is not present
// in array
return -1;
}
I somehow find the iterative version not quite easy to read, recursion makes it nice and easy :-)
public class BinarySearch {
private static int binarySearchMain(int key, int[] arr, int start, int end) {
int middle = (end-start+1)/2 + start; //get index of the middle element of a particular array portion
if (arr[middle] == key) {
return middle;
}
if (key < arr[middle] && middle > 0) {
return binarySearchMain(key, arr, start, middle-1); //recurse lower half
}
if (key > arr[middle] && middle < arr.length-1) {
return binarySearchMain(key, arr, middle+1, end); //recurse higher half
}
return Integer.MAX_VALUE;
}
public static int binarySearch(int key, int[] arr) { //entry point here
return binarySearchMain(key, arr, 0, arr.length-1);
}
}
Here is a solution without heap. The same thing can be done in an array.
If we need to find 'k' largest numbers, we take an array of size 'k' populated with first k items from the main data source. Now, keep on reading an item, and place it in the result array, if it has a place.
public static void largestkNumbers() {
int k = 4; // find 4 largest numbers
int[] arr = {4,90,7,10,-5,34,98,1,2};
int[] result = new int[k];
//initial formation of elems
for (int i = 0; i < k; ++i) {
result[i] = arr[i];
}
Arrays.sort(result);
for ( int i = k; i < arr.length; ++i ) {
int index = binarySearch(result, arr[i]);
if (index > 0) {
// insert arr[i] at result[index] and remove result[0]
insertInBetweenArray(result, index, arr[i]);
}
}
}
public static void insertInBetweenArray(int[] arr, int index, int num) {
// insert num at arr[index] and remove arr[0]
for ( int i = 0 ; i < index; ++i ) {
arr[i] = arr[i+1];
}
arr[index-1] = num;
}
public static int binarySearch(int[] arr, int num) {
int lo = 0;
int hi = arr.length - 1;
int mid = -1;
while( lo <= hi ) {
mid = (lo+hi)/2;
if ( arr[mid] > num ) {
hi = mid-1;
} else if ( arr[mid] < num ) {
lo = mid+1;
} else {
return mid;
}
}
return mid;
}
int BinSearch(int[] array, int size, int value)
{
if(size == 0) return -1;
if(array[size-1] == value) return size-1;
if(array[0] == value) return 0;
if(size % 2 == 0) {
if(array[size-1] == value) return size-1;
BinSearch(array,size-1,value);
}
else
{
if(array[size/2] == value) return (size/2);
else if(array[size/2] > value) return BinSearch(array, (size/2)+1, value);
else if(array[size/2] < value) return (size/2)+BinSearch(array+size/2, size/2, value);
}
}
or
Binary Search in Array
/**
* Find whether 67 is a prime no
* Domain consists 25 of prime numbers
* Binary Search
*/
int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
int min = 0,
mid,
max = primes.length,
key = 67,
count= 0;
boolean isFound = false;
while (!isFound) {
if (count < 6) {
mid = (min + max) / 2;
if (primes[mid] == key) {
isFound = true;
System.out.println("Found prime at: " + mid);
} else if (primes[mid] < key) {
min = mid + 1;
isFound = false;
} else if (primes[mid] > key) {
max = mid - 1;
isFound = false;
}
count++;
} else {
System.out.println("No such number");
isFound = true;
}
}
/**
HOPE YOU LIKE IT
A.K.A Binary Search
Take number array of 10 elements, input a number a check whether the number
is present:
**/
package array;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;
class BinaryS
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter a number: ");
int n=Integer.parseInt(br.readLine());
int a[]={10,20,30,40,50,60,70,80,90,100};
int upper=a.length-1,lower=0,mid;
boolean found=false;
int pos=0;
while(lower<=upper)
{
mid=(upper+lower)/2;
if(n<a[mid])upper=mid-1;
else if(n>a[mid])lower=mid+1;
else
{
found=true;
pos=mid;
break;
}
}
if(found)System.out.println(n+" found at index "+pos);
else System.out.println(n+" not found in array");
}
}
Well I know I am posting this answer much later.
But according to me its always better to check boundary condition at first.
That will make your algorithm more efficient.
public static int binarySearch(int[] array, int element){
if(array == null || array.length == 0){ // validate array
return -1;
}else if(element<array[0] || element > array[array.length-1]){ // validate value our of range that to be search
return -1;
}else if(element == array[0]){ // if element present at very first element of array
return 0;
}else if(element == array[array.length-1]){ // if element present at very last element of array
return array.length-1;
}
int start = 0;
int end = array.length-1;
while (start<=end){
int midIndex = start + ((end-start)/2); // calculate midIndex
if(element < array[midIndex]){ // focus on left side of midIndex
end = midIndex-1;
}else if(element > array[midIndex]){// focus on right side of midIndex
start = midIndex+1;
}else {
return midIndex; // You are in luck :)
}
}
return -1; // better luck next time :(
}
static int binarySearchAlgorithm() {
// Array should be in sorted order. Mandatory requirement
int[] a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int lowIndex = 0;
int valueToFind = 8;
int highIndex = a.length - 1;
while (lowIndex <= highIndex) {
//Finding the midIndex;
int midIndex = (highIndex + lowIndex) / 2;
// Checking if midIndex value of array contains the value to be find.
if (a[midIndex] == valueToFind) {
return midIndex;
}
// Checking the mid Index value is less than the value to be find.
else if (a[midIndex] < valueToFind) {
// If Yes, changing the lowIndex value to midIndex value + 1;
lowIndex = midIndex + 1;
} else if (a[midIndex] > valueToFind) {
// If Yes, changing the highIndex value to midIndex value - 1;
highIndex = midIndex - 1;
} else {
return -1;
}
}
return -1;
}

Categories