I need to write a algorithm to sort a collection, more than 10, 000, 000 elements.
So I write a forkjoin quick sort...
But when the input become bigger, the code collapses.
Firstly, I use the test cases is a random list, implements can handle.
Then, I just try some extremely cases, just as a ordered numbers. Code fails.
I check the code, but have no idea of why.
This is code below:
public class ForkJoinSort {
private static int THRESHOLD = 1000;
private static ForkJoinPool pool = new ForkJoinPool();
public static <T extends Comparable<T>> void quickSortFJ(List<T> rawList) {
pool.invoke(new QuickSort<>(rawList));
}
static class QuickSort<T extends Comparable<T>> extends RecursiveAction {
List<T> rawList;
int lo;
int hi;
QuickSort(List<T> rawList) {
this.rawList = rawList;
this.lo = 0;
this.hi = rawList.size() - 1;
}
QuickSort(List<T> rawList, int lo, int hi) {
this.rawList = rawList;
this.lo = lo;
this.hi = hi;
}
#Override
protected void compute() {
if (hi > lo && hi - lo >= THRESHOLD) {
int pivot = partition(rawList, lo, hi);
invokeAll(new QuickSort<>(rawList, lo, pivot - 1),
new QuickSort<>(rawList, pivot + 1, hi));
} else {
quickSort(rawList, lo, hi);
}
}
}
private static <T extends Comparable<T>> int partition(List<T> rawList, int lo, int hi) {
T key = rawList.get(hi);
int index = lo;
for (int i=lo; i<hi; i++) {
if (rawList.get(i).compareTo(key) > 0) {
swap(rawList, index, i);
index ++;
}
}
swap(rawList, index, hi);
return index;
}
private static <T extends Comparable<T>> void swap(List<T> rawList, int left, int right) {
if (left != right) {
T temp = rawList.get(left);
rawList.set(left, rawList.get(right));
rawList.set(right, temp);
}
}
public static <T extends Comparable<T>> void quickSort(List<T> rawList, int lo, int hi) {
if (lo < hi) {
int pivot = partition(rawList, lo, hi);
quickSort(rawList, lo, pivot-1);
quickSort(rawList, pivot+1, hi);
}
}
}
Test case failed:
List<Long> longTwoList = new ArrayList<>();
for (long i=0; i!=17000; i++) {
longTwoList.add(i);
}
ForkJoinSort.quickSortFJ(longTwoList);//failed
ForkJoinSort.quickSort(longTwoList, 0, longTwoList.size()-1);//falied
Quite confused with this problem. Thank you for replying.
Related
I am trying to do Array sort/merg using two threads. But somehow it is not working (Still the array is not sorted) probably due to some misunderstanding of threading or something else. Would appreciate to have your help. ps: I do have to use two threads as it is required for the assignment.
Original Code
public void sort(int[] data, int lo, int hi)
{
if (lo < hi) {
// divide into two halves
int mid = (lo + hi) / 2;
// sort the two half recursively
sort(data, lo, mid);
sort(data, mid+1, hi);
//Combine the two halves
merge(data, lo, hi, mid);
}
}
private static void merge(int[] data, int lo, int hi, int m)
{
.....
This is what I do
public class Sort
{
public void sort(int[] data, int lo, int hi)
{
if (lo < hi) {
int mid = (lo + hi) / 2;
Thread t1=new Thread(new Runnable() {
public void run() {
sort(data, lo, mid);
}
});
Thread t2=new Thread(new Runnable(){
public void run() {
sort(data, mid+1, hi);
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Combining two halves
merge(data, lo, hi, mid);
}
}
private static void merge(int[] data, int lo, int hi, int m)
{
int[] temp = new int[hi - lo + 1];
int i = lo;
int j = m+1;
int k = 0;
while(k < temp.length) {
if (i <= m) {
if (j <= hi) {
if (data[i] < data[j])
temp[k++] = data[i++];
else
temp[k++] = data[j++];
} else
temp[k++] = data[i++];
} else
temp[k++] = data[j++];
}
for (k = lo; k<=hi; k++)
data[k] = temp[k - lo];
}
edit: not sure if this is a correct fix but for some reason adding extends Comparable gets rid of the errors
I keep getting this same error. Why?
The error I receive is:
The method maxHeapify(T[], int) in the type HeapSort is not applicable for the arguments (T[], int)
Here's my code:
public class HeapSort {
private static int parent(int i)
{
if(i % 2 == 0)
{
return((i-1)/2);
}
else
{
return(i/2);
}
}
private static int leftChild(int i)
{
return(2*i + 1);
}
private static int rightChild(int i)
{
return(2*i + 2);
}
private static <T> void buildMaxHeap(T[] array)
{
int heapSize = array.length;
for(int i = (heapSize/2 - 1); i >= 0; i--)
{
maxHeapify(array, i);
}
}
private static <T extends Comparable<T>> void maxHeapify(T[] array, int i)
{
int L = leftChild(i);
int R = rightChild(i);
int Largest = (int) array[0];
T temp;
if(L <= array.length && array[R].compareTo(array[i]) > 0)
{
Largest = L;
}
else
{
Largest = i;
}
if(R <= array.length && array[R].compareTo(array[Largest]) > 0)
{
Largest = R;
}
if(Largest != i)
{
Swap(array[i], array[Largest]);
maxHeapify(array, Largest);
}
}
public static <T> void heapSort(T[] array)
{
buildMaxHeap(array);
int heapSize = array.length;
for(int i = array.length - 1; i >= 0; i--)
{
Swap(array[0], array[i]);
heapSize = heapSize-1;
maxHeapify(array, 0);
}
}
}
The reason for the error is because this line defines T differently
private static <T extends Comparable<T>> void maxHeapify(T[] array, int i)
to this
private static <T> void buildMaxHeap(T[] array)
and this
public static <T> void heapSort(T[] array)
Its
<T>
vs
<T extends Comparable<T>>
because buildMaxHeap and heapSort both call maxHeapify so you get a generics type mismatch
If you convert all the types to
<T extends Comparable<T>>
Then this will fix that error
You will also have another error when you fix this
int Largest = (int) array[0];
because your array doesn't contain int's, it contains your generic type objects
I am having problems with my merge sort code. Each time I run it I encounter a problem with a IndexOutOfBounds Exception, but I can't seem to figure out why... this is the code produced by our professor (who has been known to make mistakes)... anyone spot the problem
public static <T extends Comparable<T>> void mergeSort(T[] array, int first, int last)
{
if(first<last)
{
int mid = (first+last)/2;
mergeSort(array, first, mid);
mergeSort(array, mid+1, last);
merge(array, first, mid, last);
}
}
public static <T extends Comparable<T>> void mergeSort(T[] array, int last)
{
int first = 0;
if(first<last)
{
int mid = (first+last)/2;
mergeSort(array, first, mid);
mergeSort(array, mid+1, last);
merge(array, first, mid, last);
}
}
public static <T extends Comparable<T>> void merge(T[] array, int first, int mid, int last)
{
int maxSize = array.length;
T[] tempA = (T[]) new Comparable[maxSize];
int first1 = first;
int last1 = mid;
int first2 = mid+1;
int last2 = last;
int index = first1;
while((first1<=last1) && (first2<=last2))
{
if(array[first1].compareTo(array[first2])<0)
{
tempA[index] = array[first1];
first1++;
}
else
{
tempA[index] = array[first2];
first2++;
}
index++;
}
while(first1<=last1)
{
tempA[index]=array[first1];
first1++;
index++;
}
while(first2<=last2)
{
tempA[index]=array[first2];
first2++;
index++;
}
for(index=first; index<=last;++index)
{
array[index]=tempA[index];
}
}
Reading your code, its seems that the last variable is used as an index in your code.
That's why you can't pass it as a size to your mergeSort method, you have to pass array.length - 1.
array.length is the size of the array
array.length - 1 is the last index of the array
I have my lovely little quick sort method ready to go, but I am unsure how to incorporate into a GUI (this will be my first GUI) and GUI do not like public statics and what-not...
So any ideas/know-how one to do a quick sort in a GUI without the publics etc would be amazing!
private void sortNumbersButtonActionPerformed(java.awt.event.ActionEvent evt) {
public static void main(String[] args) {
int a[]={23,44,1,2009,2,88,123,7,999,1040,88};
quickSort(a, 0, a.length - 1);
System.out.println(a);
ArrayList al = new ArrayList();
}
public static void quickSort(int[] a, int p, int r)
{
if(p<r)
{
int q=partition(a,p,r);
quickSort(a,p,q);
quickSort(a,q+1,r);
}
}
private static int partition(int[] a, int p, int r) {
int x = a[p];
int i = p-1 ;
int j = r+1 ;
while (true) {
i++;
while ( i< r && a[i] < x)
i++;
j--;
while (j>p && a[j] > x)
j--;
if (i < j)
swap(a, i, j);
else
return j;
}
}
private static void swap(int[] a, int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
One simple option is to present your items in a JList. Here's a tutorial.
Nothing prevents you from using a static method in a GUI application.
I am implementing a quicksort algorithm and have succesfully partitioned the input array around a pivot. The problem is, I am confused in how to recursively sort the 1st part and 2nd part of the array (i.e specifying the range) using the same input array.
Below is my implementation
class QuickSort {
int i;
int l = 0;
public void quicksort(int A[], int n) {
if (n == 1) {
return;
} else {
partition(A, 0, n);
//----Confused as from this point
quicksort(A, A[i]);
//Recursively sort both parts of the array
}
}
public int partition(int A[], int l, int r) {
int p = A[l];//Choose pivot
i = l + 1;
//Partition around A through P
for (int j = i; j < r; j++) {
if (A[j] < p) {
swap(A, i, j);
++i;
}
}
swap(A, l, i - 1 );
return i;
}
public void swap(int A[], int i, int j) {
int temp = A[i];
A[i] = A[j];
A[j] = temp;
}
public void display(int A[]){
for (int i = 0; i < A.length; i ++){
System.out.print(A[i] + " ");
}
}
}
class QuickSortApp{
public static void main(String args[]){
QuickSort quick = new QuickSort();
int A[] = {6,2,7,8,4,3,5};
quick.quicksort(A, A.length);
quick.display(A);
}
}
Please, I would also appreciate being corrected on any other inefficencies in my algorithm. Thanks
Change your quicksort() signature to quicksort(int[] A, int begin, int end)
Since, you actually did the sorting inside partition(). What I would do is this:
if (end-begin <= 1) {
return;
} else {
int pivot = partition(A, begin, end);
quicksort(A, begin, pivot);
quicksort(A, pivot, end);
}
Create a wrapper for the quicksort call with the signature you have which calls another one like quicksort(A, i, j) and your call from the wrapper will be quicksort(A, 0, n).