I am new to Java and I have tried writing a Merge Sort Program .
MergeSort.java program is below :-
public class MergeSort {
public static int b[] = {6,2,3,1,9};
public void MergeSort(int a[],int left[], int right[]) {
int i = 0,j = 0,k = 0;
int l = left.length;
int r = right.length;
int v = a.length;
while ( i < l && j < r) {
if( left[i] < right[j]) {
a[k] = left[i] ;
i++;
} else {
a[k] = right [j];
j++;
}
k++;
}
while ( i < l ) {
a[k] = left[i];
k++;
i++;
}
while ( j < r ) {
a[k] = right[j];
k++;
j++;
}
}
public void Merge(int a[], int length) {
int n = length;
if(n < 2) return;
int mid = n/2;
int left[] = new int[mid];
int right[] = new int[n-mid];
for (int i = 0 ; i <mid ; i++) {
left[i] = a[i];
}
for (int i = mid ; i <n ; i++) {
right[i-mid] = a[i];
}
Merge(right,n-mid);
Merge(left,mid);
MergeSort(b, left, right);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
MergeSort ms = new MergeSort();
ms.Merge(b,b.length);
for(int i=0 ; i < b.length ; i++)
System.out.println(b[i]);
}
}
When I run this program , the output I get is
3
1
6
2
9
But , the expected output is 1 2 3 6 9
Can anyone please help me point out the mistake I am doing and try to help me fix it please .I have tried debugging it on Eclipse but could not spot the bug .
Thanks
Are you sure you meant this in function Merge:
MergeSort(b, left, right);
It seems it should be:
MergeSort(a, left, right);
Related
Here is my code for a mergesort in java:
public class MergeSort {
public static void mergesort(int[] input) {
int inputSize = input.length;
if(inputSize < 2) {
return;
}
int[] left = new int[inputSize/2];
int[] right = new int[inputSize/2];
int count = 0;
for(int i=0; i < inputSize/2; i++) {
left[i] = input[i];
}
for(int i=inputSize/2; i<inputSize; i++) {
right[count] = input[i];
count++;
}
mergesort(left);
mergesort(right);
merge(left, right, input);
}
public static int[] merge(int[] returnArr, int[] left, int[] right) {
int leftSize = left.length;
int rightSize = right.length;
int i = 0;
int j =0;
int k = 0;
int count = 0;
while(i < leftSize && j < rightSize) {
if(left[i] <= right[j]) {
returnArr[k] = left[i];
i++;
}
else {
returnArr[k] = right[j];
j++;
}
k++;
}
while(i<leftSize) {
returnArr[k] = left[i];
i++;
k++;
}
while(j < rightSize) {
returnArr[k] = right[j];
j++;
k++;
}
for(int x=0; x<returnArr.length; x++) {
System.out.print(returnArr[x]);
}
return returnArr;
}
public static void main(String[] args) {
int[] array = {3,4,6,2,7,1,8,6};
mergesort(array);
}
}
My issue is that I'm getting an out of bounds exception.
I'm using the debugger and have found that after mergesort(left) and mergesort(right) have finished recursively running.
The arrays left and right, which go into the merge function, have the values [3] and [4] respectively, which is correct.
But when the debugger jumps into the merge function, left has value [3] and right, for some reason is length 2 and has the value [3,4].
This is the source of my out of bounds exception, though I'm not sure why when the merge function runs for its first time, it changes the value of "right".
One problem that is readily visible is that the you shouldn't make 2 arrays of size inputSize/2. Make two arrays of inputSize/2 and inputsize-inputSize/2. Otherwise the algorithm would fail for odd length array.
Also call the function with proper order of the arguments. merge( input, left, right);
I fixed your code and merged them to 1 method, left.length and right.length are limited by input.length so you only need to loop by input.length:
public static void mergeSort(int[] input)
{
if (input.length < 2)
{
return;
}
int[] left = new int[input.length / 2];
int[] right = new int[input.length - input.length / 2];
for (int i = 0; i < input.length; i++)
{
if (i < input.length / 2)
left[i] = input[i];
else
right[i - input.length / 2] = input[i];
}
mergeSort(left);
mergeSort(right);
for (int i = 0, l = 0, r = 0; i < input.length; i++)
{
if (l >= left.length)
{
input[i] = right[r];
r++;
}
else if (r >= right.length)
{
input[i] = left[l];
l++;
}
else
{
if (left[l] >= right[r])
{
input[i] = right[r];
r++;
}
else
{
input[i] = left[l];
l++;
}
}
}
}
you had two problems with your code:
1- as #coderredoc said: your left and right array sizes are wrong:
exemple: if you had an array of 7 elements, your left and right arrays would have a size of 7/2 = 3 so you would have a total of 6 elements in left and right arrays and not 7.
2- you are calling merge function in the mergeSort function with wrong parameters order:
it should be returnArr, left, right and not left,right, returnArr.
Explanation:
if you pass the left array as the first parameter, it would merge the right and the returnArr in the left array. But your left array has a size of 3 and the sum of the sizes of the others is 7 + 3 = 10 that's why you got an OutOfBoundsException.
you need to call merge(input,left,right);
here is the final version:
public class MergeSort {
public static void mergesort(int[] input) {
int inputSize = input.length;
if(inputSize < 2) {
return;
}
int[] left = new int[inputSize/2];
int[] right = new int[inputSize-inputSize/2];
int count = 0;
for(int i=0; i < inputSize/2; i++) {
left[i] = input[i];
}
for(int i=inputSize/2; i<inputSize; i++) {
right[count] = input[i];
count++;
}
mergesort(left);
mergesort(right);
merge(input,left, right);
}
public static int[] merge(int[] returnArr, int[] left, int[] right) {
int leftSize = left.length;
int rightSize = right.length;
int i = 0;
int j =0;
int k = 0;
int count = 0;
while(i < leftSize && j < rightSize) {
if(left[i] <= right[j]) {
returnArr[k] = left[i];
i++;
}
else {
returnArr[k] = right[j];
j++;
}
k++;
}
while(i<leftSize) {
returnArr[k] = left[i];
i++;
k++;
}
while(j < rightSize) {
returnArr[k] = right[j];
j++;
k++;
}
for(int x=0; x<returnArr.length; x++) {
System.out.print(returnArr[x]);
}
return returnArr;
}
public static void main(String[] args) {
int[] array = {3,4,6,2,7,1,8,6};
mergesort(array);
}
}
I have this array: array[2][7][2].
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 7; j++) {
syso(array[i][j][0] + " ");
}
syso("/n");
}
Currently the above code prints out:
4 1 2 5 9 0 1
2 3 1 9 9 3 1
Is there a way to have these sorted somehow? I don't really care about array[i][j][1], only about array[i][j][0].
I wrote myself a QuickSort function but obviously this random piece of code doesn't work:
for (int i = 0; i < array.length; i++) {
quickSort(array[i][0], 0, array[i].length - 1);
}
EDIT:
Here's my QuickSort function as well:
static int partition(int a[], int l, int r) {
int pivot = a[r];
int k=l-1;
for(int i=l; i <= r; i++) {
if (a[i] <= pivot) {
k++;
int w = a[i];
a[i] = a[k];
a[k] = w;
}
}
return k;
}
static void quickSort(int [] a, int l, int r) {
if (l>=r) {
return ;
}
int k = partition(a, l, r);
quickSort(a, l, k-1);
quickSort(a, k+1, r);
}
int[][] another = int[2][7];
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length; j++) {
anotner[i][j] = array[i][j][0];
}
}
for (int[] a : anotner) {
Arrays.sort(a);
}
then print anotner as you do using syso().
I am writing code for a bottom-up mergeSort in Java. Right now, I think there may be an indexing issue with the call to merge, but I am having trouble figuring out exactly what my problem is. Any assistance would be greatly appreciated!
public static int[] merge(int[]a, int lo1, int hi1, int lo2, int hi2) {
int[]b = new int[hi2-lo1+1];
int i = lo1;
int j = lo2;
int k = 0;
while (i <= hi1 && j <= hi2) {
if(a[i] < a[j])
b[k++] = a[i++];
else
b[k++]=a[j++];
}
while (i <= hi1)
b[k++] = a[i++];
while (j <= hi2)
b[k++] = a[j++];
for (int l = 0; l < k; l++)
a[lo1 + l] = b[l];
return a; //added
}
public static int[] betterMergeSort(int[]a, int lo, int hi){
for (int comparesize=1; comparesize < (hi-lo+1); comparesize*=2) {
for (int k=lo; k < hi; k+=2*comparesize) {
int[]holder = new int[Math.min(k+2*comparesize-1,hi)-lo+1];
holder = merge(a, k, k+comparesize-1, k+comparesize, Math.min(k+2*comparesize-1, hi));
if (holder.length == (hi-lo+1)){
for (int j=0; j<(hi-lo+1); j++)
a[lo+j] = holder[j];
}
}
}
return a;
}
Note that I need this code to return int[] for now in order to check its accuracy.
Question: Where are comparisons being made in each separate sorting method?
Also if you know please tell me which method count numbers are wrong and where to place my counters instead.trying to understand where and how many times sorting methods make comparisons.
Method A B
Selection 4950 4950
Bubble 99 9900
Insertion 99 5049
Merge 712 1028
Shell 413 649
Quick 543 1041
Okay so to explain some parts, basically Array A is an array from 1-100 in ascending order. So this should be the minimum number of comparisons.
Array B is 100-1 in descending order. So I believe it should be the maximum number of comparisons. Array C is just randomly generated numbers, so it changes every time.
I feel like my selection and bubble sorts were counted correctly. Feel free to let me know where comparisons are being made that I haven't counted, or if I'm counting wrong comparisons.
Side note: Made some global variable to count the methods that were recursive in multiple sections.
class Sorting
{
static int[] X = new int[100];
static int mergecount = 0;
static int quickcount = 0;
public static void selectionSort(int list[])
{
int count = 0;
int position = 0, n = list.length;
for(int j = 0; j < n-1; j++)
{
position = j;
for(int k = j+1; k < n; k++)
{
count++;
if(list[k] < list[position])
position = k;
}
Swap(list, j, position);
}
System.out.println("counter" + count);
}
public static void Swap(int list[], int j, int k)
{
int temp = list[j];
list[j] = list[k];
list[k] = temp;
}
public static void bubbleSort(int list[])
{
int count = 0;
boolean changed = false;
do
{
changed = false;
for(int j = 0; j < list.length - 1; j++)
{
count++;
if(list[j] > list[j + 1])
{
Swap(list, j, j+1);
changed = true;
}
}
} while(changed);
System.out.println("counter" + count);
}
public static void insertionSort(int list[])
{
int count = 0;
for(int p = 1; p < list.length; p++)
{
int temp = list[p];
int j = p;
count++;
for( ; j > 0 && temp < list[j - 1]; j = j-1)
{
list[j] = list[j - 1];
count++;
}
list[j] = temp;
}
System.out.println("counter" + count);
}
public static void mergeSort(int list[])
{
mergeSort(list, 0, list.length - 1);
System.out.println("counter" + mergecount);
}
public static void mergeSort(int list[], int first, int last)
{
if(first < last)
{
int mid = (first + last) / 2;
mergeSort(list, first, mid);
mergeSort(list, mid + 1, last);
Merge(list, first, mid, last);
}
}
public static void Merge(int list[], int first, int mid, int last)
{
int count = 0;
int first1 = first, last1 = mid;
int first2 = mid + 1, last2 = last;
int temp[] = new int[list.length];
int index = first1;
while(first1 <= last1 && first2 <= last2)
{
if(list[first1] < list[first2])
{
temp[index] = list[first1++];
mergecount++;
}
else
temp[index] = list[first2++];
index++;
mergecount++;
}
while(first1 <= last1)
temp[index++] = list[first1++];
while(first2 <= last2)
temp[index++] = list[first2++];
for(index = first; index <= last; index++)
list[index] = temp[index];
}
public static void shellSort(int list[])
{
int count = 0;
int n = list.length;
for(int gap = n / 2; gap > 0; gap = gap == 2 ? 1: (int) (gap/2.2))
for(int i = gap; i < n; i++)
{
int temp = list[i];
int j = i;
count++;
for( ; j >= gap && (temp < (list[j - gap])); j -= gap)
{
list[j] = list[j - gap];
count++;
}
list[j] = temp;
}
System.out.println("counter" + count);
}
public static void quickSort(int start, int finish, int list[])
{
int count = 0;
int left = start, right = finish, pivot, temp;
pivot = list[(start + finish) / 2];
do
{
while(list[left] < pivot)
{
left++;
quickcount++;
}
while(pivot < list[right])
{
right--;
quickcount++;
}
if(left <= right)
{
temp = list[left];
list[left++] = list[right];
list[right--] = temp;
quickcount++;
}
} while(left < right);
if(start < right)
quickSort(start, right, list);
if(left < finish)
quickSort(left, finish, list);
}
public static void copy(int list[])
{
for(int i = 0; i < list.length; i++)
X[i] = list[i];
}
public static void restore(int list[])
{
for(int i = 0; i < list.length; i++)
list[i] = X[i];
}
public static void displayArray(int list[])
{
for(int k = 0; k < list.length; k++)
System.out.print(list[k] + " ");
System.out.println();
}
public static void main(String args[])
{
int[] A = new int[100];
for(int i = 0; i < A.length; i++)
A[i] = i + 1;
int[] B = new int[100];
int q = 100;
for(int i = 0; i < B.length; i++)
B[i] = q--;
int[] C = new int[100];
for(int i = 0; i < C.length; i++)
C[i] = (int)(Math.random() * 100 + 1);
displayArray(A);
copy(A);
selectionSort(A);
displayArray(A);
restore(A);
}
Note that QuickSort performance is greatly influenced by your choice of the pivot. With both of your test arrays sorted (ascending / descending) and because you are picking pivot as array[length/2] you are actually always picking the best pivot. So your test case B won't generate maximum number of comparisons for quicksort. If you were picking array[0] as pivot you'd get maximum number of comparisons for test case A and B.
The easiest way to count comparisons is to use a compare function and do it in there.
static int compareCount = 0;
int compareInt(int a, int b) {
compareCount++;
return a - b; // if 0 they are equal, if negative a is smaller, if positive b is smaller
}
Now just use compareInt in all your algorithms and you'll get an accurate count. You'll have to reset compareCount between each run though.
Can anyone give me example about shell sort? I'm a new person in here who must learn about shell sort, but first I must find a Java shell sort example. I found one example in Google but it's too difficult.
Here, this code is very simple :
/**
* Shellsort, using Shell’s (poor) increments.
* #param a an array of Comparable items.
*/
public static <T extends Comparable<? super T>>
void shellsort( T [ ] a )
{
int j;
for( int gap = a.length / 2; gap > 0; gap /= 2 )
{
for( int i = gap; i < a.length; i++ )
{
T tmp = a[ i ];
for( j = i; j >= gap && tmp.compareTo( a[ j - gap ] ) < 0; j -= gap )
{
a[ j ] = a[ j - gap ];
}
a[ j ] = tmp;
}
}
}
I stole it from a book called Data Structures and Algorithm Analysis in Java. It is very good book easy to understand. I advise you to read it.
May be, this java code will help you.
public class ShellSort {
private long[] data;
private int len;
public ShellSort(int max) {
data = new long[max];
len = 0;
}
public void insert(long value){
data[len] = value;
len++;
}
public void display() {
System.out.print("Data:");
for (int j = 0; j < len; j++)
System.out.print(data[j] + " ");
System.out.println("");
}
public void shellSort() {
int inner, outer;
long temp;
//find initial value of h
int h = 1;
while (h <= len / 3)
h = h * 3 + 1; // (1, 4, 13, 40, 121, ...)
while (h > 0) // decreasing h, until h=1
{
// h-sort the file
for (outer = h; outer < len; outer++) {
temp = data[outer];
inner = outer;
// one subpass (eg 0, 4, 8)
while (inner > h - 1 && data[inner - h] >= temp) {
data[inner] = data[inner - h];
inner -= h;
}
data[inner] = temp;
}
h = (h - 1) / 3; // decrease h
}
}
public static void main(String[] args) {
int maxSize = 10;
ShellSort arr = new ShellSort(maxSize);
for (int j = 0; j < maxSize; j++) {
long n = (int) (java.lang.Math.random() * 99);
arr.insert(n);
}
arr.display();
arr.shellSort();
arr.display();
}
}
Shell sort improves insertion sort by comparing elements separated by a gap of several positions.
This lets an element take "bigger steps" toward its expected position. Multiple passes over the data are taken with smaller and smaller gap sizes. The last step of Shell sort is a plain insertion sort, but by then, the array of data is guaranteed to be almost sorted.
This code might help you in understanding the logic better.
package Sorts;
public class ShellSort extends Sorter{
#Override
public <T extends Comparable<? super T>> void sort(T[] a) {
int h = 1;
while((h*3+1) < a.length)
h = 3*h+1;
while(h > 0){
for(int i = h-1; i < a.length; i++){
T s = a[i];
int j = i;
for(j = i; (j>=h) && (a[j-h].compareTo(s) > 0); j-=h)
a[j] = a[j-h];
a[j] = s;
}
h /= 3;
}
}
}
Here is a visualization of shell sort for a python implementation:
def exch(a,i,j):
t = a[i]
a[i] = a[j]
a[j] = t
def shellsort(string):
print string
a = list(string)
N = len(a)
h = 1
i = 0
j = 0
k = 0
#determine starting stride length
while ( h < N/3 ):
h = 3*h + 1
print "STRIDE LENGTH: " + str(h)
while (h >=1):
i = h
while i < N:
j = i
k = j - h
while j >= h and a[j] < a[j-h]:
k = j - h
exch(a,j,k)
j -= h
i += 1
h = h/3
print "STRIDE LENGTH: " + str(h)
print ''.join(a)·
if __name__ == '__main__':
shellsort("astringtosortwithshellsort")
Here's an example:
public static void shellsort( Comparable [ ] a )
{
for( int gap = a.length / 2; gap > 0;
gap = gap == 2 ? 1 : (int) ( gap / 2.2 ) )
for( int i = gap; i < a.length; i++ )
{
Comparable tmp = a[ i ];
int j = i;
for( ; j >= gap && tmp.compareTo( a[ j - gap ] ) < 0; j -= gap )
a[ j ] = a[ j - gap ];
a[ j ] = tmp;
}
}
I find the easiest way to understand shell sort is to break it down into segments:
private static void shellsort() {
int[] theArray = {44,5,33,22,765,43,53,12,57,97};
//first section gets the Knuth's interval sequence (very efficient)
int h=1;
while(h<= theArray.length/3){
h = 3*h + 1; //h is equal to highest sequence of h<=length/3 (1,4,13,40...)
}
//next section
while(h>0){ //for array of length 10, h=4
//similar to insertion sort below
for(int i=0; i<theArray.length; i++){
int temp = theArray[i];
int j;
for(j=i; j>h-1 && theArray[j-h] >= temp; j=j-h){
a[j] = a[j-h];
}
a[j] = temp;
}
h = (h-1)/3;
}
}
Output: 5, 12, 22, 33, 43, 44, 53, 57, 97, 765
Classic primitive type implementation:
package math;
import java.util.Arrays;
public class Sorter{
public static void main(String []args){
int[] a = {9,8,7,6,5,4,3,2,1};//plz use sophisticated random number generator
System.out.println( Arrays.toString(a) );
System.out.println( Arrays.toString(shellSort(a)) );
}
//Performs a shell sort on an array of ints.
public static int[] shellSort(int[] array){
int h = 1;
while (h < array.length) h = 3*h + 1;
while (h > 0){
h = h/3;
for (int k = 0; k < h; k++){
for (int i = h+k; i < array.length; i+=h){
int key = array[i];
int j = i-h;
while (j>=0 && array[j] > key){
array[j+h] = array[j];
j-=h;
}
array[j+h] = key;
//-> invariant: array[0,h,2*h..j] is sorted
}
}
//->invariant: each h-sub-array is sorted
}
return array;
};
}
P.S.: Check this link for other sorting algorithms (they are in c++, though, easily portable to java).
package sort_tester;
public class ShellSorter extends Sorter {
private final int[] gapArray = {1750,701,301,132,57,23,10,4,1};
#Override
public void makeSort (boolean trace) {
int size = list.length;
int i,j, temp;
for ( int gap : gapArray ) {
i = gap;
while ( i < size ) {
temp = list[i];
j = i-gap;
while ( j >= 0 && list[j] > temp ) {
list[j + gap] = list[j];
j -= gap;
}
list[j + gap] = temp;
i ++;
}
}
}
}
list - is int[];
GapArray taken from arcticle of Marcin Ciura
http://sun.aei.polsl.pl/~mciura/publikacje/shellsort.pdf
Here is a video link: https://youtu.be/SCBf7aqKQEY
The guy has made a good video of shell sort!!
And a simple code:
int sort(int arr[])
{
int n = arr.length;
int gap = n/2;
int i,j;
while(gap>0)
{ for (i=0,j=i+gap; j<n; i++,++j)
{
if(arr[i]>arr[j]) //swap
{ int temp = arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
gap=gap/2;
}
return 0;
}
Use this
public void shellSort(Integer[] arr) {
int interval = arr.length / 2;
while (interval != 0) {
for (int i = 0; i < interval; i++) {
for (int p = i + interval; p < arr.length; p += interval) {
int key = arr[p];
int j = p - interval;
while (j >= 0) {
if (key < arr[j]) {
arr[j + interval] = arr[j];
} else
break;
j -= interval;
}
arr[j + interval] = key;
}
}
interval /= 2;
}
}
Snippet with 3k+1 gap.
public void shellSort(Comparable arr[], int size, int h, int x) {
while (h >= 1) {
for (int i = 0; i <= size - h; i++) {
for (int j = i; j < size-h && (arr[j].compareTo(arr[j+h]) > 0); j += h)
swap(arr, j, j+h);
}
h = 3*(--x) + 1;
}
}