Here's my implementation of Merge Sort in java
import java.io.*;
import java.util.Arrays;
public class MergeSort
{
private static int [] LeftSubArray(int [] Array)
{
int [] leftHalf = Arrays.copyOfRange(Array, 0, Array.length / 2);
return leftHalf;
}
private static int [] RightSubArray(int [] Array)
{
int [] rightHalf = Arrays.copyOfRange(Array, Array.length / 2 + 1, Array.length);
return rightHalf;
}
private static int [] Sort(int [] A)
{
if(A.length > 1)
{
return Merge( Sort( LeftSubArray(A) ) , Sort( RightSubArray(A) ) );
}
else
{
return A;
}
}
private static int [] Merge(int [] B, int [] C)
{
int [] D = new int[B.length + C.length];
int i,j,k;
i = j = k = 0;
while(k < D.length)
{
if(i == B.length)
{
//Copy the remainder of C into D
while(k < D.length){ D[k++] = C[j++]; }
}
if(j == C.length)
{
//Copy the remainder of B into D
while(k < D.length){ D[k++] = B[i++]; }
}
if(i<B.length && j<C.length)
{
if(B[i] > C[j]){ D[k++] = B[i++]; }
else { D[k++] = C[j++]; }
}
}
return D;
}
public static void main(String [] args)
{
int [] array = {1,3,5,2,4};
int [] sorted = MergeSort.Sort(array);
for(int i = 0;i < sorted.length; ++i)
{
System.out.print(sorted[i] + " ");
}
}
}
The output I get is
2 1
From what I can tell there seems a problem with my division of the right sub array.
What am I doing wrong?
Here is the javadoc of copyOfRange:
Parameters:
original - the array from which a range is to be copied
from - the initial index of the range to be copied, **inclusive**
to - the final index of the range to be copied, **exclusive**. (This index may lie outside the array.)
I highlighted two words you should pay special attention to ;-)
If your array has 10 elements, then LeftSubArray copies elements 0..5, and RightSubArray copies elements 6..10. But if the first element is at index 0, then there is no element w/ an index 10. And if copyOfRange(a,b) gives elements indexed a..b-1, then LeftSA is yielding 0..4 and RightSA is yielding 6..9. Either way, your assumption about division seems to be accurate.
With your code [1,3,5,2,4] is split into [1,3] and [2,4]. Good luck
This piece of code works: you had couple of errors:
see next diffs:
rightSubArray method
copy the remainder of B
copy the remainder of C
The code that works follows:
public class MergeSort
{
private static int [] LeftSubArray(int [] Array)
{
int [] leftHalf = Arrays.copyOfRange(Array, 0, Array.length / 2);
return leftHalf;
}
private static int [] RightSubArray(int [] Array)
{
int[] rightHalf = Arrays.copyOfRange(Array, Array.length / 2,
Array.length);
return rightHalf;
}
private static int [] Sort(int [] A)
{
if(A.length > 1)
{
return Merge( Sort( LeftSubArray(A) ) , Sort( RightSubArray(A) ) );
}
else
{
return A;
}
}
private static int [] Merge(int [] B, int [] C)
{
int [] D = new int[B.length + C.length];
int i,j,k;
i = j = k = 0;
while(k < D.length)
{
if(i == B.length)
{
//Copy the remainder of C into D
while (j < C.length) {
D[k++] = C[j++];
}
}
if(j == C.length)
{
//Copy the remainder of B into D
while (i < B.length) {
D[k++] = B[i++];
}
}
if (i < B.length && j < C.length)
{
if (B[i] > C[j]) {
D[k++] = B[i++];
} else {
D[k++] = C[j++];
}
}
}
return D;
}
public static void main(String [] args)
{
int [] array = {1,3,5,2,4};
int [] sorted = MergeSort.Sort(array);
for(int i = 0;i < sorted.length; ++i)
{
System.out.print(sorted[i] + " ");
}
}
}
I found a rigth solution in Robert Sedgewick book "Algorithms on java language"
Read here about merge
Related
I want to implement Merge Sort using one a mergeSort method that splits the sequences of an int array up until it's a single element and using a method merge to put them together.
With my code as it is I get a Stackoverflow Error.
Anyone has an idea why?
public static int[] mergeSort(int[] seq) {
return mergeSort(seq, 0, seq.length - 1);
}
private static int[] mergeSort(int[] seq, int l, int r) {
if (seq.length < 2) {
return seq;
}
int s = (l + r) / 2;
int[] a = new int[s];
int[] b = new int[seq.length - s];
for (int i : a) {
a[i] = seq[i];
}
for (int j : b) {
b[j] = seq[s + j];
}
mergeSort(a);
mergeSort(b);
return merge(a, b);
}
public static int[] merge(int[] ls, int[] rs) {
// Store the result in this array
int[] result = new int[ls.length + rs.length];
int i, l, r;
i = l = r = 0;
while (i < result.length) {
if (l < ls.length && r < rs.length) {
if (ls[l] < rs[r]) {
result[i] = ls[l];
++i;
++l;
} else {
result[i] = rs[r];
++i;
++r;
}
} else if (l >= ls.length) {
while (r < rs.length) {
result[i] = rs[r];
++i;
++r;
}
} else if (r >= rs.length) {
while (l < ls.length) {
result[i] = ls[l];
++i;
++l;
}
}
}
return result;
}
The stack overflow is caused by calling the method recursively too many times, possibly infinitely.
private static int[] mergeSort(int[] seq, int l, int r) this will always be called with l=0 and r=seq.length-1, so it's not really necessary to overload.
Here: int s = (l + r) / 2; if the array has 2 elements, this will return 0 (l=0, r=1), so the array will be split to a length 0, and a length 2 (and here is what causes the infinite recursive calls). Add one to the result, and the splitting of the array will work correctly.
To copy the parts of the original array, it's easier to use Arrays.copyOfRange() than writing your own for loop. And you're trying to use the existing elements of arrays a and b, which will all be 0, for indexing.
There are two small issues with your code.
First one is here:
public static int[] mergeSort(int[] seq) {
return mergeSort(seq, 0, seq.length - 1);
}
You need to call it as return mergeSort(seq, 0, seq.length);
The reason behind that is that for example when you have 2 elements and you call it like that with -1 you pass an array with 2 elements but s=1+0/2 =0 and you don't actually split it. Each subsequent recursion call is done with one empty array and one array with the same 2 elements causing an infinite loop and a stackoverflow exception
The second problem is this one:
for (int i : a) { and for (int i : b) {
You can't do the for loop like because you want to iterate on indexes not values of the array. You need to change it to:
for (int i=0;i<a.length;i++) {
a[i] = seq[i];
}
for (int i=0;i<b.length;i++) {
b[i] = seq[s + i];
}
And the last problem with your code is that you don't assign the values of the resulting sorted array and when you do the recursive calls it returns the sorted sub part but you don't get the result. It should become:
a=mergeSort(a);
b=mergeSort(b);
And here is the final code:
public static void main(String... args) {
int[] array={3,9,4,5,1} ;
array=mergeSort(array);
for(int i:array) {
System.out.print(i+",");
}
}
private static int[] mergeSort(int[] seq) {
if (seq.length < 2) {
return seq;
}
int s = seq.length / 2; //You always use that value. no need for 2 methods
int[] a = new int[s];
int[] b = new int[seq.length - s];
for (int i=0;i<a.length;i++) {
a[i] = seq[i];
}
for (int i=0;i<b.length;i++) {
b[i] = seq[s + i];
}
a=mergeSort(a);
b=mergeSort(b);
return merge(a, b);
}
public static int[] merge(int[] ls, int[] rs) {
// Store the result in this array
int[] result = new int[ls.length + rs.length];
int i, l, r;
i = l = r = 0;
while (i < result.length) {
if (l < ls.length && r < rs.length) {
if (ls[l] < rs[r]) {
result[i] = ls[l];
++i;
++l;
} else {
result[i] = rs[r];
++i;
++r;
}
} else if (l >= ls.length) {
while (r < rs.length) {
result[i] = rs[r];
++i;
++r;
}
} else if (r >= rs.length) {
while (l < ls.length) {
result[i] = ls[l];
++i;
++l;
}
}
}
return result;
}
first time post here.
I am trying to create a class which compares quick sort, merge sort, bubble sort, and selection sort. I have implemented all of the sort methods and created a random array method which populates a random array with 1000 random ints. However when I run my program my main method stops after the initial welcome message and allows for user input. Any help would be greatly appreciated, I'm sure its some simple mistake I am missing.
import java.util.Random;
public class TestSort {
private static int selectCount;
private static int bubbleCount;
private static int mergeCount;
private static int quickCount;
public static void main(String[] args){
System.out.println("Welcome to the search tester. "
+ "We are going to see which algorithm performs the best out of 20 tests");
int testSelection = 0;
int testBubble = 0;
int testQuick = 0;
int testMerge = 0;
//Check tests
int[] a = new int[1000];
populateArray(a);
int[] select = a;
int[] bubble = a;
int[] quick = a;
int[] merge = a;
testSelection = selectionSort(select);
testBubble = bubbleSort(bubble);
testQuick = quickSort(quick,0,0);
testMerge = mergeSort(merge);
System.out.println("Selection sort number of checks: " + testSelection);
System.out.println("Bubble sort number of checks: " + testBubble);
System.out.println("Quick sort number of checks: " + testQuick);
System.out.println("Merge sort number of checks: " + testMerge);
System.out.println("");
}
public static int[] populateArray(int[] a)
{
Random r = new Random();
a = new int[1000];
for(int i=0; i < a.length; i++)
{
int num = r.nextInt(1000);
a[i] = num;
}
return a;
}
//Sorting methods
public static int selectionSort(int[] a)
{
for (int i = 0; i < a.length; i++)
{
int smallestIndex = i;
for (int j=i; j<a.length; j++)
{
if(a[j]<a[smallestIndex])
{
smallestIndex = j;
}
}
if(smallestIndex != i) //Swap
{
int temp = a[i];
a[i] = a[smallestIndex];
a[smallestIndex] = temp;
selectCount++;
}
}
return selectCount;
}
public static int bubbleSort (int[] a)
{
boolean hasSwapped = true;
while (hasSwapped == true)
{
hasSwapped = true;
for(int i = 0; i<a.length-1; i++)
{
if(a[i] > a[i+1]) //Needs to swap
{
int temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
hasSwapped = true;
bubbleCount++;
}
}
}
return bubbleCount;
}
public static int mergeSort(int [] a)
{
int size = a.length;
if(size<2)//recursive halting point
{
return 0;
}
int mid = size/2;
int leftSize = mid;
int rightSize = size-mid;
int [] left = new int[leftSize];
int [] right = new int[rightSize];
for(int i = 0; i<mid; i++)
{
mergeCount++;
left[i] = a[i];
}
for(int i = mid; i<size; i++)
{
mergeCount++;
right[i-mid]=a[i];
}
mergeSort(left);
mergeSort(right);
//merge
merge(left,right,a);
return mergeCount;
}
private static void merge(int [] left, int [] right, int [] a)
{
int leftSize = left.length;
int rightSize = right.length;
int i = 0;//index of the left array
int j = 0; //index of right array
int k = 0; //index of the sorted array [a]
while(i<leftSize && j<rightSize)
{
if(left[i]<=right[j])
{
a[k] = left[i];
i++;
k++;
}
else
{
a[k] = right[j];
j++;
k++;
}
}
while(i<leftSize)
{
a[k] =left[i];
i++;
k++;
}
while(j<rightSize)
{
a[k] =right[j];
j++;
k++;
}
}
public static int quickSort(int[] a, int left, int right)
{
//partition, where pivot is picked
int index = partition(a,left,right);
if(left<index-1)//Still elements on left to be sorted
quickSort(a,left,index-1);
if(index<right) //Still elements on right to be sorted
quickSort(a,index+1,right);
quickCount++;
return quickCount;
}
private static int partition(int[] a, int left, int right)
{
int i = left;
int j = right; //Left and right are indexes
int pivot = a[(left+right/2)]; //Midpoint, pivot
while(i<j)
{
while(a[i]<pivot)
{
i++;
}
while(a[j]>pivot)
{
j--;
}
if(i<=j) //Swap
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
i++;
j--;
}
}
return i;
}
}
Your infinite loop is in bubbleSort:
public static int bubbleSort(int[] a)
{
boolean hasSwapped = true;
while (hasSwapped == true)
{
hasSwapped = false; // Need to set this to false
for (int i = 0; i < a.length - 1; i++)
{
if (a[i] > a[i + 1]) // Needs to swap
{
int temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
hasSwapped = true;
bubbleCount++;
}
}
}
return bubbleCount;
}
The problem is in your bubbleSort() method. The hasSwapped boolean is never set to false, so the while loops infinite times.
There is another problem in your code. In the main method, you will have to assign the array that the populateArray() method returns back to a. And the such assignments as int[] select = a; you do in the main method do not do what you want to do. Instead, just send the array a to your sorting methods.
Like this:
int[] a = new int[1000];
a=populateArray(a);
testSelection = selectionSort(a);
testBubble = bubbleSort(a);
testQuick = quickSort(a,0,0);
testMerge = mergeSort(a);
I'm having trouble with trying to generate all possible combinations of a n*n grid. The code below shows how I would go about it using nested loops and a 2*2 grid. However, if I wanted to do the same thing for, say a 6*6 grid, it would be too annoying to make such an extensive list of loops.
Can anyone help me convert the bruteSolve() method into a recursive method so that I can choose how big the grid is?
Thanks in advance :) This has been a problem I've been stuck on for ages :(
static ArrayList<Integer> numbers;
static int n;
static int [] [] grid;
static int count;
public static void main (String [] args){
n = 2;
grid = new int [n] [n] ;
bruteSolve(n);
}
public static void bruteSolve(int n){
for (int i=1; i<n+1; i++){
grid [0][0] = i;
for (int j=1; j<n+1; j++){
grid [0][1] = j;
for (int k=1; k<n+1; k++){
grid [1][0] = k;
for (int l=1; l<n+1; l++){
grid [1][1] = l;
System.out.println(Arrays.deepToString(grid));
}
}
}
}
}
public static void main (String [] args){
int[][] arr = new int[2][2];
int from = 1, to = 2; // counter range
doit(0, arr, from, to);
// or
doit2(0, 0, arr, from, to);
}
// single iterator - process the data as unidimensional array, computing real indexes
public static void doit(int index, int[][] arr, int from, int to) {
if(arr == null || arr.length == 0 || arr[0] == null || arr[0].length == 0) {
System.err.println("Matrix inconsistent");
return;
}
if(index >= arr.length * arr[0].length) {
System.out.println(Arrays.deepToString(arr));
} else {
int x = index % arr[0].length;
int y = index / arr[0].length;
for(int n = from;n <= to;n++) {
arr[y][x] = n;
doit(index+1, arr, from, to);
}
}
}
// less complex but more comparisons
public static void doit2(int x, int y, int[][] arr, int from, int to) {
if(arr == null || arr.length == 0 || arr[0] == null || arr[0].length == 0) {
System.err.println("Matrix inconsistent");
return;
}
if(y >= arr.length) {
System.out.println(Arrays.deepToString(arr));
} else if(x >= arr[0].length) {
doit2(0, y+1, arr, from, to);
} else {
for(int n = from;n <= to;n++) {
arr[y][x] = n;
doit2(x + 1, y, arr, from, to);
}
}
}
After many times to try to solve this issue, I can't seem to solve my dilemma. When trying to run my program, the unsorted array will not sort when printing "Sorted Array". Is there something that I'm doing wrong?
public class RecursiveSorter {
private int[] sortedArray;
private int[] array;
public RecursiveSorter() {
array = new int[1];
}
public RecursiveSorter(int[] a) {
array = a;
}
public void setArray(int[] a) {
array = a;
}
public int[] getSortedArray() {
return sortedArray;
}
public int[] getOriginalArray() {
return array;
}
public int[] sort() {
sortedArray = array;
recursiveSort(sortedArray.length - 1);
return sortedArray;
}
public int[] recursiveSort(int endIndex) {
if (endIndex > 0) {
int m = getMaxIndex(endIndex, sortedArray);
swap(m, endIndex, sortedArray);
recursiveSort(endIndex-1);
}
return sortedArray;
}
public int getMaxIndex(int endIndex, int[] a) {
int max = a[0];
int maxIndex = 0;
for (int i = 1; i < endIndex; i++) {
if (a[i] < max) {
max = a[i];
maxIndex = i;
}
}
return maxIndex;
}
//Changed it to make sure that it is swapping the elements correctly
public void swap(int src, int dest, int[] a) {
if(dest <= src)
{
int temp = a[dest];
a[dest] = a[src];
a[src] = temp;
dest++;
src++;
}
}
public String toString() {
return "Original: " + prettyPrint(getOriginalArray()) + "\n" +
"Sorted: " + prettyPrint(getSortedArray());
}
private String prettyPrint(int[] a) {
String s = "";
for (int i : a)
s += i + " ";
return s;
}
public static void main(String[] args) {
// Automate running, but not testing
int[] array = {5, 67, 12, 20};
RecursiveSorter s = new RecursiveSorter(array);
s.sort();
System.out.println(s); // uses Sorter.toString
}
}
You have 3 problems. 2 are in getMaxIndex(): you were not including the last element in the test for the max, and the test for max is not the right. You are computing the min.
public int getMaxIndex(int endIndex, int[] a) {
int max = a[0];
int maxIndex = 0;
for (int i = 1; i <= endIndex; i++) { // use <= instead of <
if (a[i] > max) { // change < in >
max = a[i];
maxIndex = i;
}
}
return maxIndex;
}
And one problem in swap()
public void swap(int src, int dest, int[] a) {
if(src <= dest) // reverse src and dest
{
int temp = a[dest];
a[dest] = a[src];
a[src] = temp;
dest++; // no use, dest is local
src++; // idem
}
}
Then you will have:
Original: 5 12 20 67
Sorted: 5 12 20 67
Actually the orginal array is modified because array and sortedArray reference the same array of int. There is no copy in Java. When you do
public int[] sort() {
sortedArray = array;
recursiveSort(sortedArray.length - 1);
return sortedArray;
}
sortedArray points to the same int[] as array. If you want to keep the orginal one, you need to explicitly do a copy, for instance with System.arrayCopy(...).
I traced the problem down to two points:
first, you have an unnecessary if in swap(...):
public void swap(int src, int dest, int[] a)
{
// if(dest <= src)
// {
int temp = a[dest];
a[dest] = a[src];
a[src] = temp;
// dest++;
// src++;
// }
}
Second, you have a little bug in the for loop of getMaxIndex(...):
public int getMaxIndex(int endIndex, int[] a)
{
int max = a[0];
int maxIndex = 0;
for (int i = 1; i <= endIndex; i++) // substituted < with <=
{
if (a[i] < max)
{
max = a[i];
maxIndex = i;
}
}
return maxIndex;
}
With these changes (and mentionded System.arraycopy), the algorithm should work as intended.
Why you are not sing
// sorting array in #java.util.Arrays;
Arrays.sort(array);
And dont need to recusive call and all
If you need to write your own code, then Choose any sorting algorthim, implement that one by your own.
private static void sort(int[] array){
boolean swapped = true;
int j = 0;
int tmp;
while (swapped) {
swapped = false;
j++;
for (int i = 0; i < array.length - j; i++) {
if (array[i] > array[i + 1]) {
tmp = array[i];
array[i] = array[i + 1];
array[i + 1] = tmp;
swapped = true;
}
}
}
}
So I am trying to make the following code into a recursive method, insertion sort, but for as much as I try I cannot. Can anyone help me?
public static void insertionSort(int[] array){
for (int i = 1; i < array.length; i++){
int j = i;
int B = array[i];
while ((j > 0) && (array[j-1] > B)){
array[j] = array[j-1];
j--;
}
array[j] = B;
}
}
EDIT:
I was thinking of something like this, but it doesn't look very recursive to me...
public static void insertionSort(int[] array, int index){
if(index < array.length){
int j = index;
int B = array[index];
while ((j > 0) && (array[j-1] > B)){
array[j] = array[j-1];
j--;
}
array[j] = B;
insertionSort(array, index + 1);
}
}
Try this:
public class RecursiveInsertionSort {
static int[] arr = {5, 2, 4, 6, 1, 3};
int maxIndex = arr.length;
public static void main(String[] args) {
print(arr);
new RecursiveInsertionSort().sort(arr.length);
}
/*
The sorting function uses 'index' instead of 'copying the array' in each
recursive call to conserve memory and improve efficiency.
*/
private int sort(int maxIndex) {
if (maxIndex <= 1) {
// at this point maxIndex points to the second element in the array.
return maxIndex;
}
maxIndex = sort(maxIndex - 1); // recursive call
// save a copy of the value in variable 'key'.
// This value will be placed in the correct position
// after the while loop below ends.
int key = arr[maxIndex];
int i = maxIndex - 1;
// compare value in 'key' with all the elements in array
// that come before the element key.
while ((i >= 0) && (arr[i] > key)) {
arr[i+1] = arr[i];
i--;
}
arr[i+1] = key;
print(arr);
return maxIndex + 1;
}
// code to print the array on the console.
private static void print(int[] arr) {
System.out.println();
for (int i : arr) {
System.out.print(i + ", ");
}
}
}
public static void insertionSort(int[] array, int index) {
if(array.length == index + 1) return;
insertionSort(array, index + 1);
// insert array[index] into the array
}
You can try this code. It works correctly.
public static int[] InsertionSort(int[] dizi, int n)
{
int i;
if (n < 1) {
InsertionSort(dizi, n - 1);
}
else {
int key = dizi[n];
i = n - 1;
while (i >= 0 && dizi[i] > key) {
dizi[i + 1] = dizi[i];
i = i - 1;
}
dizi[i + 1] = key;
}
return dizi;
}
for the recursion algorithm, we start with the whole array A[1..n], we sort A[1..n-1] and then insert A[n] into the correct position.
public int[] insertionSort(int[] array)
{
//base case
if(array.length==1) return new int[]{ array[0] };
//get array[0..n-1] and sort it
int[] arrayToSort = new int[array.length - 1]{ };
System.arraycopy(array, 0, arrayToSort, 0, array.length -1);
int[] B = insertionSort(arrayToSort);
//now, insert array[n] into its correct position
int[] C = merge(B, array[array.length - 1]);
return C;
}
private int[] merge(int[] array, int n)
{
int[] arrayToReturn = new int[array.length + 1] {};
int j = array.length-1;
while(j>=0 && n <= array[j])
{
arrayToReturn[j+1]=array[j;
j--;
}
arrayToReturn[j] =
}
Try below code by providing ele as an integer array, sortedIndex=index of first element and index=index of second element:
public static void insertionSort(int[] ele, int sortedIndex, int index) {
if (sortedIndex < ele.length) {
if (index < ele.length) {
if (ele[sortedIndex] > ele[index]) {
ele[sortedIndex] += ele[index];
ele[index] = ele[sortedIndex] - ele[index];
ele[sortedIndex] = ele[sortedIndex] - ele[index];
}
insertionSort(ele, sortedIndex, index + 1);
return;
}
if (index == ele.length) {
sortedIndex++;
}
insertionSort(ele, sortedIndex, sortedIndex + 1);
}
}
public static void sort(int[] A, int p, int r) {
if (p < r) {
int q = r - 1;
sort(A, p, q);
combine(A, p, q, r);
}
}
private static void combine(int[] A, int p, int q, int r) {
int i = q - p;
int val = A[r];
while (i >= 0 && val < A[p + i]) {
A[p + i + 1] = A[p + i];
A[p + i] = val;
i--;
}
}
public static void main(String... strings) {
int[] A = { 2, 5, 3, 1, 7 };
sort(A, 0, A.length - 1);
Arrays.stream(A).sequential().forEach(i -> System.out.print(i + ", "));
}
public class test
{
public static void main(String[] args){
test h = new test();
int a[] = { 5, 8, 9, 13, 65, 74, 25, 44, 67, 2, 1 };
h.ins_rec(a, a.length-1);
for(int i=0; i<a.length; i++)
log(a[i]);
}
void ins_rec(int a[], int j){
if( j == 0 ) return;
ins_rec(a, j - 1);
int key = a[ j ];
sort(a, key, j - 1);
}
void sort(int a[], int key, int i){
if( (i < 0) || (a[i] < key) ) {
a[ i + 1 ] = key;
return;
}
a[ i + 1 ] = a[ i ];
sort(a, key, i - 1);
}
private static void log(int aMessage){
System.out.println("\t\t"+aMessage);
}
}