Generic multi threaded quicksort java - java

I have been given an assignment to modify quicksort program in such a way so it uses generics and its multi threaded. The problem i have with the code is that it takes longer for the Multi threaded Integer quicksort call to finish, compared to the non-threaded one.
This is my implementation of both - non threaded and multi threaded and I have a problem finding the mistake I have done.
class GenericQuicksort {
private static void swap(Comparable[] array, int i, int j) {
Comparable temp = array[i];
array[i] = array[j];
array[j] = temp;
}
public static Comparable[] quickSort(Comparable[] array) {
return qs(array, 0, array.length - 1);
}
private static Comparable[] qs(Comparable[] array, int left, int righ) {
int i = left;
int j = righ;
Comparable pivot = array[(left + righ) / 2];
do {
while ((array[i].compareTo(pivot) == -1) && (i < righ)) i++;
while ((pivot.compareTo(array[j]) == -1) && (j > left)) j--;
if (i <= j) {
swap(array, i++, j--);
}
} while (i <= j);
if (left < j) qs(array, left, j);
if (i < righ) qs(array, i, righ);
return array;
}
public static Comparable[] quickSortMulti(Comparable[] array) {
GsMultiThread gsMultiThread = new GsMultiThread(array, 0, array.length - 1, 0);
gsMultiThread.start(); //Not needed to start a new thread.
try {
gsMultiThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
return array;
}
static class GsMultiThread extends Thread {
Comparable[] array;
int left;
int right;
int ii;
public GsMultiThread(Comparable[] array, int left, int right, int i) {
this.array = array;
this.left = left;
this.right = right;
this.ii = ++i;
}
#Override
public void run() {
int i = left;
int j = right;
Comparable pivot = array[(left + right) / 2];
do {
while ((array[i].compareTo(pivot) == -1) && (i < right)) i++;
while ((pivot.compareTo(array[j]) == -1) && (j > left)) j--;
if (i <= j) {
swap(array, i++, j--);
}
} while (i <= j);
GsMultiThread threada = null;
GsMultiThread threadb = null;
if (left < j) {
if (i > 2) {
qs(array, left, j);
} else {
threada = new GsMultiThread(array, left, j, ii);
threada.start();
}
}
if (i < right) {
if (i > 2) {
qs(array, i, right);
} else {
threadb = new GsMultiThread(array, i, right, ii);
threadb.run();
}
}
try {
if (threada != null)
threada.join();
if (threadb != null)
threadb.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

Related

how to count Quicksort comparisons accurately

I'm trying to make a program where I count the amount of comparisons quicksort makes but its not 100% accurate. how would I make this comparison counter accurate?
The quicksort takes in an array of n random integers.
Code I have so far:
public int QuickSort(int[] list, int from, int to) {
int icount = 0;
if (from >= to) {
return icount;
}
int p = from;
int i = from;
int j = to;
while (i <= j) {
if (list[i] <= list[p]) {
i++;
icount++;
} else if (list[j] >= list[p]) {
j--;
icount++;
} else {
swap(list, i, j);
i++;
j--;
icount++;
}
}
if (p < j) { // place the pivot in its correct position
swap(list, j, p);
p = j;
icount++;
} else if (p > i) {
swap(list, i, p);
p = i;
icount++;
}
icount += QuickSort(list, from, p - 1);
icount += QuickSort(list, p + 1, to);
return icount;
}
Is there anything wrong with the current code? or is it not possible to be completely accurate with random integers?

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);
}

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.

quick sort list in java

I'm trying to practice quick sort list using java, I think this is correct but it shows "Exception in thread main..."
public class QuickSort {
public static void sort(List<Integer> list) {
sort(list, 0, list.size() - 1);
}
public static void sort(List<Integer> list, int from, int to) {
if (list.size() <= 1) {
return;
}
int pivot = from;
int left = from + 1;
int right = to;
while (left < right) {
while (list.get(pivot) >= list.get(left)) {
left++;
}
while (list.get(pivot) <= list.get(right)) {
right--;
}
if (left < right) {
Collections.swap(list, left, right);
}
}
Collections.swap(list, pivot, left - 1);
sort(list, from, pivot - 1);
sort(list, pivot + 1, to);
}
}
Your problem is here:
while (list.get(pivot) <= list.get(right)) {
right--;
}
As, In the worst case, say an already sorted list, your right-- will be negative.
Take a look the following code, this will give you idea:
public static void quicksort(List<Integer> list, int left, int right) {
int q;
if (right > left) {
q = partition(list, left, right);
// after ‘partition’
// list[left..q-1] ≤ list[q] ≤ list[q+1..right]
quicksort(list, left, q - 1);
quicksort(list, q + 1, right);
}
}
static int partition(List<Integer> list, int left, int right) {
int P = list.get(left);
int i = left;
int j = right + 1;
for (;;) { // infinite for-loop, break to exit
while (list.get(++i) < P)
if (i >= right)
break;
// Now, list[i]≥P
while (list.get(--j) > P)
if (j <= left)
break;
// Now, list[j]≤P
if (i >= j)
break; // break the for-loop
else
// swap(list[i],list[j]);
Collections.swap(list, i, j);
}
if (j == left)
return j;
// swap (list[left],list[j]);
Collections.swap(list, left, j);
return j;
}
See a demo run here.
Try with this:
public static void sort(List<Integer> list) {
sort(list, 0, list.size() - 1);
}
public static void sort(List<Integer> list, int from, int to) {
if (from < to) {
int pivot = from;
int left = from + 1;
int right = to;
int pivotValue = list.get(pivot);
while (left <= right) {
// left <= to -> limit protection
while (left <= to && pivotValue >= list.get(left)) {
left++;
}
// right > from -> limit protection
while (right > from && pivotValue < list.get(right)) {
right--;
}
if (left < right) {
Collections.swap(list, left, right);
}
}
Collections.swap(list, pivot, left - 1);
sort(list, from, right - 1); // <-- pivot was wrong!
sort(list, right + 1, to); // <-- pivot was wrong!
}
}

Stuck in a simple quick sort implementation with random pivot

I'm reviewing algorithm stuff and stuck in a simple quick sort algorithm implementation in java
import java.util.Arrays;
import java.util.Random;
public class QuickSort {
int arr[];
boolean randomPick;
Random rand = null;
public QuickSort(int[] inputArray) {
arr = inputArray;
randomPick = false;
}
public QuickSort(int[] inputArray, boolean random) {
arr = inputArray;
if (random) {
randomPick = true;
rand = new Random(System.currentTimeMillis());
}
else {
randomPick = false;
}
}
public int[] sort() {
int start = 0;
int end = arr.length - 1;
try {
_sort(start, end);
}
catch (StackOverflowError e) {
System.out.println("StackOverflow: " + Arrays.toString(arr));
}
return arr;
}
private void _sort(int start, int end) {
int i = start;
int j = end;
int pivotLoc;
if (!randomPick) {
pivotLoc = (j + i) / 2;
}
else {
pivotLoc = rand.nextInt(j - i) + i;
}
int pivot = arr[pivotLoc];
while (i < j) { // swapping numbers around the pivot
while (arr[i] < pivot) {
i++;
}
while (arr[j] > pivot) {
j--;
}
if (i < j) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
i++;
j--;
}
}
if (i - start > 1) {
_sort(start, i);
}
if (end - i > 1) {
_sort(i, end);
}
}
}
The code can either pick the middle number as the pivot or randomly pick a number as the pivot and it sorts the array by calling _sort recurrently. It works in the first case but fails in the second.
The situation is: when it reaches a subarray as this {3,5,5}, i==start==0 and j==end==2. Finally 5 and 5 are swapped, i becomes 2 and j becomes 1 (i++ and j--). Then since i - start>1 it will call _sort over and over and eventually evoke the stackoverflow error. However the error is supposed to happen in the first case (fixed pivot), which hasn't happened so far...
I don't know what's wrong with my code. I know it's not a pleasure to read code written by others but any help?
You've made a small mistake in your recursion condition, both the start and end compares are against i, the start should be against j
You have:
if (i - start > 1) {
_sort(start, i);
}
if (end - i > 1) {
_sort(i, end);
}
Needs to be:
if (j > start) {
_sort(start, j);
}
if (end > i) {
_sort(i, end);
}
And your i and j comparison needs to allow equals:
// here ----v
if (i <= j) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
i++;
j--;
}

Categories