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.
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
So I am sort of new to Java and have only been doing it for a couple of months. I'm trying to implement different types of sorting algorithms and I think everything is okay except when I run it I get a NullPointerException on the for loop. I have already read this post What is a NullPointerException, and how do I fix it?. But I still can not figure out how to fix the problem even though I think it is quite simple. Any help?
import java.lang.*;
import java.util.*;
public class SortApp {
public int[] generateRandomArray(int size) {
int[] output = new int[size];
for (int i = 0; i < size; i++) {
output[i] = (int) (Math.random() * Integer.MAX_VALUE);
}
return output;
}
public void printArray(int[] inarray) {
for (int i = 0; i < inarray.length; i++) {
System.out.println(inarray[i]);
}
}
public boolean isSorted(int[] inarray) {
for (int i = 0; i < inarray.length; i++) { //Error here
if (inarray[i] > inarray[i + 1]) {
return false;
}
}
return true;
}
public int[] insertionSort(int[] inarray) {
int[] data = Arrays.copyOf(inarray, inarray.length);
int temp;
int j;
for (int i = 0; i < inarray.length; i++) {
temp = inarray[i];
for (j = 0; (j > 1) && (temp < inarray[j - 1]); j--)
inarray[j] = inarray[j - 1];
inarray[j] = temp;
}
return data;
}
public int[] selectionSort(int[] inarray) {
int[] data = Arrays.copyOf(inarray, inarray.length);
int temp;
int n = inarray.length;
for (int i = 0; i < inarray.length; i++) {
int k = i;
for (int j = i + 1; j < n; j++)
if (inarray[j] < inarray[k])
k = j;
temp = inarray[i];
inarray[i] = inarray[k];
inarray[k] = temp;
}
return data;
}
public int[] mergeSort(int[] inarray, int temp[], int l, int r) {
int[] data = Arrays.copyOf(inarray, inarray.length);
if (l == r) return null;
int mid = (l + r) / 2;
mergeSort(inarray, temp, l, mid);
mergeSort(inarray, temp, mid + 1, r);
int i, j, k;
for (i = l; i <= r; i++)
temp[i] = inarray[i];
for (i = l, j = mid + 1, k = l; i <= mid && j <= r && k <= r; k++)
if (temp[i] < temp[j]) inarray[k] = temp[i];
i++;
inarray[k] = temp[j];
j++;
for (; i <= mid; i++, k++)
inarray[k] = temp[i];
for (; j <= r; j++, k++)
inarray[k] = temp[j];
return data;
}
public static void main(String[] args) {
SortApp myApp = new SortApp();
int[] data = myApp.generateRandomArray(10);
boolean isSortedA = myApp.isSorted(myApp.insertionSort(data));
boolean isSortedB = myApp.isSorted(myApp.selectionSort(data));
boolean isSortedC = myApp.isSorted(myApp.mergeSort(data, data, 0, 0)); //Error here
myApp.printArray(data);
}
}
Error I am getting is this:
Exception in thread "main" java.lang.NullPointerException
at SortApp.isSorted(SortApp.java:23)
at SortApp.main(SortApp.java:91)
It's because of this line:
if (l==r) return null;
You are passing in 0 for both l and r meaning they are equal. Therefore, you are getting a null value passed in to your isSorted() call.
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 was given an assignment to implement the following algorithm:
I am a little confused by reading the algorithm itself, I tried to follow the algorithm but, since I cannot understand it completely my code does not work. Can anyone, please, have a look at my code (this is the bit that I cannot understand what to fix):
public static void mergeSortNonRec(Comparable[] a) {
Comparable[] a1 = new Comparable[a.length];
Comparable[] b = new Comparable[a.length];
for (int i = 1; i < a.length; i *= 2) {
for (int j = 0; j < a.length; j += 2 * i) {
merge(a1, j, (Integer.min(j + i, a.length) - 1), a1, j + i, (Integer.min(j + 2 * i, a.length) - 1), b, 0);
}
}
for (int i = 0; i < a.length; i++) {
a[i] = a1[i];
}
}
This is my helper method that I have tested with my recursive mergeSort and I know it works:
private static void merge(Comparable[] a1, int left1, int right1, Comparable[] a2, int left2, int right2, Comparable[] a, int left) {
int i = left1;
int j = left2;
int k = left;
while (i <= right1 && j <= left2) {
int comp = a1[i].compareTo(a2[j]);
if (comp <= 0) {
a[k++] = a1[i++];
} else {
a[k++] = a2[j++];
}
}
while (i <= right1) {
a[k++] = a1[i++];
}
while (j <= right2) {
a[k++] = a2[j++];
}
}
I am currently trying to transcribe a mergesort algorithm from a pseudocode level to a working implementation in java. This is my code
public int[] merge(int a[], int b[]) {
int c[] = new int[a.length + b.length];
int i = 0, j = 0;
for (int k = 0; k < c.length; k++) {
if (a[i] <= b[j]) {
c[k] = a[i++];
} else {
c[k] = b[j++];
}
}
return c;
}
The pseudocode interpretation is correct to the best of my knowledge but it keeps returning an ArrayOutofBound Exception.
Where did I get it all wrong.
This would obviously give the out of bound exception because you are not keeping track of the length of a and b arrays . Since k = a + b , a and b will always be less than k . Hence the exception.
And when you apply this check, remember to copy the remaining of the items, whether they are of a[] or b[] , to copy them to c[]. See this -
for(;i<a.length;i++)
c[k++] = a[i++];
for(;j<b.length;b++)
c[k++] = b[j++];
The merge algorithm in the way you intend to implement it is a bit more elaborated, below you'll find a correct implementation:
public int[] merge(int a[], int b[]) {
int i = 0, j = 0, k = 0;
int m = a.length, n = b.length;
int[] c = new int[m + n];
// Merge to the end of one of the source arrays
while (i < m && j < n) {
if (a[i] <= b[j]) {
c[k] = a[i];
i++;
} else {
c[k] = b[j];
j++;
}
k++;
}
// Determine which source array has elements remaining and
// append those to the result array
if (i < m) {
for (int p = i; p < m; p++) {
c[k] = a[p];
k++;
}
} else {
for (int p = j; p < n; p++) {
c[k] = b[p];
k++;
}
}
return c;
}
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.