Multithreaded merge sort, adding additional threads - java

I am facing one problem in multithreaded merge sort algorithm in java.
I should modify the code into 3,4,5,6,7,8 threaded merge sorting by dividing original array into subArrays. Currently it has 2 subArrays.
How can I split original array into 3, 4 ,5,6,7,8 subArrays to achive my goal?
Moreover, I should write some more methods because mergeSort method calls lefthalf and righthalf methods at the moment. So for 3,4,5,6,7,8 threads I should write additional methods.
How can i handle this?
two_threaded_merge_sort.java
public class two_threaded_merge_sort {
public static void finalMerge(int[] a, int[] b) {
int[] result = new int[a.length + b.length];
int i=0;
int j=0;
int r=0;
while (i < a.length && j < b.length) {
if (a[i] <= b[j]) {
result[r]=a[i];
i++;
r++;
} else {
result[r]=b[j];
j++;
r++;
}
if (i==a.length) {
while (j<b.length) {
result[r]=b[j];
r++;
j++;
}
}
if (j==b.length) {
while (i<a.length) {
result[r]=a[i];
r++;
i++;
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Random rand = new Random();
int[] original = new int[9000000];
for (int i=0; i<original.length; i++) {
original[i] = rand.nextInt(1000);
}
long startTime = System.currentTimeMillis();
int[] subArr1 = new int[original.length/2];
int[] subArr2 = new int[original.length - original.length/2];
System.arraycopy(original, 0, subArr1, 0, original.length/2);
System.arraycopy(original, original.length/2, subArr2, 0, original.length - original.length/2);
Worker runner1 = new Worker(subArr1);
Worker runner2 = new Worker(subArr2);
runner1.start();
runner2.start();
runner1.join();
runner2.join();
finalMerge (runner1.getInternal(), runner2.getInternal());
long stopTime = System.currentTimeMillis();
long elapsedTime = stopTime - startTime;
System.out.println("2-thread MergeSort takes: " + (float)elapsedTime/1000 + " seconds");
}
}
Worker.java
class Worker extends Thread {
private int[] internal;
public int[] getInternal() {
return internal;
}
public void mergeSort(int[] array) {
if (array.length > 1) {
int[] left = leftHalf(array);
int[] right = rightHalf(array);
mergeSort(left);
mergeSort(right);
merge(array, left, right);
}
}
public int[] leftHalf(int[] array) {
int size1 = array.length / 2;
int[] left = new int[size1];
for (int i = 0; i < size1; i++) {
left[i] = array[i];
}
return left;
}
public int[] rightHalf(int[] array) {
int size1 = array.length / 2;
int size2 = array.length - size1;
int[] right = new int[size2];
for (int i = 0; i < size2; i++) {
right[i] = array[i + size1];
}
return right;
}
public void merge(int[] result, int[] left, int[] right) {
int i1 = 0;
int i2 = 0;
for (int i = 0; i < result.length; i++) {
if (i2 >= right.length || (i1 < left.length && left[i1] <= right[i2])) {
result[i] = left[i1];
i1++;
} else {
result[i] = right[i2];
i2++;
}
}
}
Worker(int[] arr) {
internal = arr;
}
public void run() {
mergeSort(internal);
}
}
Thanks very much!

There needs to be a sort function that separates the array into k parts, then create k threads to sort each part, using either top down or bottom up approach, (bottom up would slightly faster), and wait for all threads to complete.
At this point there are k sorted parts. These could be merged all at once using a k-way merge (complicated), or merged a pair of parts at a time (2 way merge), perhaps using multiple threads, but at this point the process is probably memory bandwidth limited, so multi-threading may not help much.
When separating the array into k parts, something like this can be used to keep the sizes similar:
int r = n % k;
int s = n / k;
int t;
for each part{
t = r ? 1 : 0;
r -= t;
size = s + t;
}
or
int r = n % k;
int s = n / k + 1;
while(r--){
next part size = s; // n / k + 1
}
s -= 1;
while not done{
next part size = s; // n / k
}

From my point of view, your hard work is done. now you must parametrize the algorithm with number of threads.
Your algorithm has two parts
split the work.
merge the k-parts.
And two components:
Main algorithm
Workers.
About the threads
In my opinion, Start/join method aren't useful in this case, because last merging can't start until all threads are finish. I prefer '2 way merge' (#rcgldr answer) and a thread pool (ExecutorService).
You must be careful with threads synchronization and shared memory.
To sum up, I propose a little different solution:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
public class MultithreadedMergeSort {
private int[] array;
private int numThreads;
private List<int[]> sortedFragments;
private MultithreadedMergeSort(int numThreads, int[] array) {
this.numThreads = numThreads;
this.array = array;
}
// Basic algorithm: it sort recursively a fragment
private static void recursiveMergeSort(int[] array, int begin, int end) {
if (end - begin > 1) {
int middle = (begin + end) / 2;
recursiveMergeSort(array, begin, middle);
recursiveMergeSort(array, middle, end);
merge(array, begin, middle, end);
}
}
// Basic algorithm: it merges two consecutives sorted fragments
private static void merge(int[] array, int begin, int middle, int end) {
int[] firstPart = Arrays.copyOfRange(array, begin, middle);
int i = 0;
int j = middle;
int k = begin;
while (i < firstPart.length && j < end) {
if (firstPart[i] <= array[j]) {
array[k++] = firstPart[i++];
} else {
array[k++] = array[j++];
}
}
if (i < firstPart.length) {
System.arraycopy(firstPart, i, array, k, firstPart.length - i);
}
}
public static void sort(int[] array, int numThreads) throws InterruptedException {
if (array != null && array.length > 1) {
if (numThreads > 1) {
new MultithreadedMergeSort(numThreads, array).mergeSort();
} else {
recursiveMergeSort(array, 0, array.length);
}
}
}
private synchronized void mergeSort() throws InterruptedException {
// A thread pool
ExecutorService executors = Executors.newFixedThreadPool(numThreads);
this.sortedFragments = new ArrayList<>(numThreads - 1);
int begin = 0;
int end = 0;
// it split the work
for (int i = 1; i <= (numThreads - 1); i++) {
begin = end;
end = (array.length * i) / (numThreads - 1);
// sending the work to worker
executors.execute(new MergeSortWorker(begin, end));
}
// this is waiting until work is done
wait();
// shutdown the thread pool.
executors.shutdown();
}
private synchronized int[] notifyFragmentSorted(int begin, int end) {
if (begin > 0 || end < array.length) {
// the array is not completely sorted
Iterator<int[]> it = sortedFragments.iterator();
// searching a previous or next fragment
while (it.hasNext()) {
int[] f = it.next();
if (f[1] == begin || f[0] == end) {
// It found a previous/next fragment
it.remove();
return f;
}
}
sortedFragments.add(new int[]{begin, end});
} else {
// the array is sorted
notify();
}
return null;
}
private class MergeSortWorker implements Runnable {
int begin;
int end;
public MergeSortWorker(int begin, int end) {
this.begin = begin;
this.end = end;
}
#Override
public void run() {
// Sort a fragment
recursiveMergeSort(array, begin, end);
// notify the sorted fragment
int[] nearFragment = notifyFragmentSorted(begin, end);
while (nearFragment != null) {
// there's more work: merge two consecutives sorted fragments, (begin, end) and nearFragment
int middle;
if (nearFragment[0] < begin) {
middle = begin;
begin = nearFragment[0];
} else {
middle = nearFragment[0];
end = nearFragment[1];
}
merge(array, begin, middle, end);
nearFragment = notifyFragmentSorted(begin, end);
}
}
}
public static void main(String[] args) throws InterruptedException {
int numThreads = 5;
Random rand = new Random();
int[] original = new int[9000000];
for (int i = 0; i < original.length; i++) {
original[i] = rand.nextInt(1000);
}
long startTime = System.currentTimeMillis();
MultithreadedMergeSort.sort(original, numThreads);
long stopTime = System.currentTimeMillis();
long elapsedTime = stopTime - startTime;
// warning: Take care with microbenchmarks
System.out.println(numThreads + "-thread MergeSort takes: " + (float) elapsedTime / 1000 + " seconds");
}
}

Related

Hybrid sorting using insertion sort and merge sort

I wish to implement a hybrid algorithm that switches from insertion sort to merge sort once the input array size becomes too big.
This is my main function (I fixed my input array size at 30 currently as I wish to test my merge sort function) :
public static void main(String[] args) {
int[] a = genrandarray(30);
long bgn, end;
bgn = System.currentTimeMillis();
imsort(a, 0, a.length, 30);
end = System.currentTimeMillis();
for(int i = 1; i < a.length; i++){
if(a[i-1] > a[i]){
System.out.println("failed");
break;
}
}
System.out.println("milliseconds " + (end-bgn));
}
Insertion sort is called when the array size is <20, else merge sort is called:
public static void imsort(int [] slot, int b, int e, int size) {
//if smaller than 20, use insertion sort
if (e-b<=20) {
insertionSort(slot, e); //e is the length of slot[]
System.out.println("imsort entered!");
}
else {
mergesort(b, e, slot);
System.out.println("mergesort entered!");
}
}
There is a Index 30 out of bounds error for my merge sort function currently.
public static int merge(int n, int m, int[] slot) {
int mid = (n+m)/2;
int a = n, b = mid+1, i, tmp, cmp=0, comp=0;
//sanity check
if (m-n <= 0) return -1000;
while (a <= mid && b <= m) {
cmp = compare(slot[a], slot[b]);
comp++;
if (cmp > 0) { //slot[a] > slot[b]
tmp = slot[b++];
for (i = ++mid; i > a; i--)
slot[i] = slot[i-1];
slot[a++] = tmp;
}
else if (cmp < 0) //slot[a] < slot[b]
a++;
else {
//slot[a] == slot[b]
if (a == mid && b == m) break;
tmp = slot[b++];
a++;
for (i = ++mid; i > a; i--)
slot[i] = slot[i-1]; slot[a++] = tmp;
}
} // end of while loop;
return comp;
} // end of merge
public static int mergesort(int s, int e, int[] slot) {
//int comp =0;
int mid = (s+e)/2;
int right=0, left=0;
if(e-s>0) {
//comp++;
left = mergesort(s,mid, slot);
//comp++;
right = mergesort(mid+1,e, slot);
}
return right + left + merge(s,e,slot);
}
I am unsure of the error in my merge / mergesort function. Can I get some further advice?
a.length returns you 30 which is the length of your random array from the genrandarray method i believe. And your array is indexed 0 through 29. Try changing the main method like this and it will work out
public static void main(String[] args) {
int[] a = genrandarray(30);
long bgn, end;
bgn = System.currentTimeMillis();
imsort(a, 0, a.length-1, 30);
end = System.currentTimeMillis();
for(int i = 1; i < a.length; i++){
if(a[i-1] > a[i]){
System.out.println("failed");
break;
}
}
System.out.println("milliseconds " + (end-bgn));
}
First, let me congratulate on a very good post for someone new. You didn't post the line of code where the error is happening and code isn't complete, so I filled in some blanks and executed it:
import java.util.Arrays;
import java.util.Random;
public class Test {
public static int[] genrandarray(int n)
{
int[] a = new int[n];
Random r = new Random();
for(int i=0;i<n;i++) a[i] = r.nextInt();
return a;
}
public static void main(String[] args) {
int[] a = genrandarray(30);
long bgn, end;
bgn = System.currentTimeMillis();
imsort(a, 0, a.length, 30);
end = System.currentTimeMillis();
for(int i = 1; i < a.length; i++){
if(a[i-1] > a[i]){
System.out.println("failed");
break;
}
}
System.out.println("milliseconds " + (end-bgn));
}
public static void imsort(int [] slot, int b, int e, int size) {
//if smaller than 20, use insertion sort
if (e-b<=20) {
Arrays.sort(slot, 0, e);
System.out.println("imsort entered!");
}
else {
mergesort(b, e, slot);
System.out.println("mergesort entered!");
}
}
public static int merge(int n, int m, int[] slot) {
int mid = (n+m)/2;
int a = n, b = mid+1, i, tmp, cmp=0, comp=0;
//sanity check
if (m-n <= 0) return -1000;
while (a <= mid && b <= m) {
cmp = slot[a] - slot[b];
comp++;
if (cmp > 0) { //slot[a] > slot[b]
tmp = slot[b++];
for (i = ++mid; i > a; i--)
slot[i] = slot[i-1];
slot[a++] = tmp;
}
else if (cmp < 0) //slot[a] < slot[b]
a++;
else {
//slot[a] == slot[b]
if (a == mid && b == m) break;
tmp = slot[b++];
a++;
for (i = ++mid; i > a; i--)
slot[i] = slot[i-1]; slot[a++] = tmp;
}
} // end of while loop;
return comp;
} // end of merge
public static int mergesort(int s, int e, int[] slot) {
//int comp =0;
int mid = (s+e)/2;
int right=0, left=0;
if(e-s>0) {
//comp++;
left = mergesort(s,mid, slot);
//comp++;
right = mergesort(mid+1,e, slot);
}
return right + left + merge(s,e,slot);
}
}
The error is caused by setting variable a to n in your merge function and then in the line cmp = slot[a] - slot[b]. Because arrays go from 0 to n-1, n will cause an out of bounds exception.

'MergeSort Algorithm' - What's the better implementation in JAVA? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I know quick sort algorithm, but I am concerned with merge sort algorithm only.
I found out on internet two types of merge sort algorithm implementation.
But when I compare them with insertion algorithm, they seem less efficient and this is not expected for a large number of items.
Enter the number of elements you want to sort:
300000
Time spent to executing BubbleSort: 362123 milliseconds
Time spent to executing Selection: 108285 milliseconds
Time spent to executing Insertion: 18046 milliseconds
Time spent to executing MergeSort: 35968 milliseconds
Time spent to executing MergeSort2: 35823 milliseconds
Is there another way to implement the merge sort algorithm to make it more efficient than the insertion algorithm?
Take a look at my code...
package br.com.test.test1;
import java.util.Random;
import java.util.Scanner;
/**
*
* #author Joao
*/
public class Main {
// generate an int array with random numbers between 0 and 500
public static int[] generateRand(int n){
int[] randArray = new int[n];
Random number = new Random();
// random numbers between 0 and 500
for (int i = 0; i < n; i++){
randArray[i] = number.nextInt(501);
}
return randArray;
}
public static void main(String[] args) {
long startTime;
Scanner input = new Scanner(System.in);
int n;
System.out.println("Enter the number of elements you want to sort:");
n = input.nextInt();
MyArray array = new MyArray(n);
int[] aux = new int[n];
aux = generateRand(n);
array.copy(aux);
startTime = System.currentTimeMillis();
array.bubblesort();
// Time spent to executing BUBBLESORT
System.out.println("\nTime spent to executing BubbleSort: "+(System.currentTimeMillis() - startTime)+" milliseconds");
array.copy(aux);
startTime = System.currentTimeMillis();
array.selection();
// Time spent to executing SELECTION
System.out.println("Time spent to executing Selection: "+(System.currentTimeMillis() - startTime)+" milliseconds");
array.copy(aux);
startTime = System.currentTimeMillis();
array.insertion();
// Time spent to executing INSERTION
System.out.println("Time spent to executing Insertion: "+(System.currentTimeMillis() - startTime)+" milliseconds");
array.copy(aux);
startTime = System.currentTimeMillis();
array.mergeSort(0, n-1);
// Time spent to executing MERGESORT
System.out.println("Time spent to executing MergeSort: "+(System.currentTimeMillis() - startTime)+" milliseconds");
array.copy(aux);
startTime = System.currentTimeMillis();
array.mergeSort2(0, n-1);
// Time spent to executing MERGESORT 2
System.out.println("Time spent to executing MergeSort2: "+(System.currentTimeMillis() - startTime)+" milliseconds");
}
}
---- and ------
package br.com.test.test1;
/**
*
* #author Joao Paulo
*/
class MyArray {
private int[] v;
private int n; // array index
private int len;
public MyArray(int length) {
len = length;
v = new int[len];
n = 0;
}
public void copy(int[] k){
n = 0;
for (int i = 0; i < len; i++) {
v[i] = k[i];
n++;
}
}
public void show(){
for (int i = 0; i < n; i++) {
System.out.print(" " + v[i]);
}
System.out.println("\n");
}
// ******* START OF ALGORITHMS TO SORT *******
// ---------- Start of BubbleSort and Selection --------------
public void bubblesort(){
for (int i = 0; i < n; i++){
for (int j = 0; j < n-1; j++) {
if (v[j] > v[j+1]) {
change(j, j+1);
}
}
}
}
public void selection() {
int min;
for (int i = 0; i < n-1; i++) {
min = i;
for (int j = i+1; j < n; j++){
if (v[j] < v[min]){
min = j;
}
}
change(i, min);
}
}
private void change(int one, int two) {
int temp = v[one];
v[one] = v[two];
v[two] = temp;
}
// ---------- End of BubbleSort and Selection ----------------
// ---------- Start of Insertion -----------------------------
public void insertion() {
int i, j;
int temp;
for (i=1; i < n; i++) {
temp = v[i]; // marked variable
j = i;
while ((j > 0) && (v[j-1] > temp)) {
v[j] = v[j-1];
j = j - 1;
}
v[j] = temp;
}
}
// ---------- End of Insertion -------------------------------
// ---------- Start of MergeSort -----------------------------
public void mergeSort (int start, int end){
if(start == end) return;
int middle = (start+end)/2;
mergeSort(start,middle);
mergeSort(middle+1,end);
merge(start,middle,end);
}
public void merge(int start, int middle, int end) {
int[] aux = new int[v.length];
for (int x = start; x <= end; x++) {
aux[x] = v[x];
}
int i = start;
int j = middle+1;
int k = start;
//emptying out array 'v' inserting items neatly in array 'aux'
while (i <= middle && j <= end) {
if (aux[i] < aux[j]){
v[k++] = aux[i++];
} else {
v[k++] = aux[j++];
}
}
//copying values from 'aux' to 'v'
while (i <= middle){
v[k++] = aux[i++];
}
while (j <= end){
v[k++] = aux[j++];
}
}
// ---------- End of MergeSort -------------------------------
// ---------- Start of MergeSort 2 ----------------------------
public void mergeSort2 (int start, int end) {
if(start >= end) return;
int middle = (start+end)/2;
mergeSort2(start,middle);
mergeSort2(middle+1,end);
merge2(start,middle,end);
}
public void merge2(int start, int middle, int end) {
int[] helper = new int[v.length];
// Copy both parts into the helper array
for (int i = start; i <= end; i++) {
helper[i] = v[i];
}
int i = start;
int j = middle + 1;
int k = start;
// Copy the smallest values from either the left or the right side back to the original array
while (i <= middle && j <= end) {
if (helper[i] <= helper[j]) {
v[k] = helper[i];
i++;
} else {
v[k] = helper[j];
j++;
}
k++;
}
// Copy the rest of the left side of the array into the target array
while (i <= middle) {
v[k] = helper[i];
k++;
i++;
}
// Since we are sorting in-place any leftover elements from the right side
// are already at the right position.
}
// ---------- End of MergeSort 2 ------------------------------
}
Do a single allocation of the working/temp array and avoid copying of data during merge (unless moving a single remaining run from one array to the other).
Bottom up merge sort example.
package jsortbu;
import java.util.Random;
public class jsortbu {
static void MergeSort(int[] a) // entry function
{
if(a.length < 2) // if size < 2 return
return;
int[] b = new int[a.length];
BottomUpMergeSort(a, b);
}
static void BottomUpMergeSort(int[] a, int[] b)
{
int n = a.length;
int s = 1; // run size
if(1 == (GetPassCount(n)&1)){ // if odd number of passes
for(s = 1; s < n; s += 2) // swap in place for 1st pass
if(a[s] < a[s-1]){
int t = a[s];
a[s] = a[s-1];
a[s-1] = t;
}
s = 2;
}
while(s < n){ // while not done
int ee = 0; // reset end index
while(ee < n){ // merge pairs of runs
int ll = ee; // ll = start of left run
int rr = ll+s; // rr = start of right run
if(rr >= n){ // if only left run
do{ // copy it
b[ll] = a[ll];
ll++;
}while(ll < n);
break; // end of pass
}
ee = rr+s; // ee = end of right run
if(ee > n)
ee = n;
Merge(a, b, ll, rr, ee);
}
{ // swap references
int[] t = a;
a = b;
b = t;
}
s <<= 1; // double the run size
}
}
static void Merge(int[] a, int[] b, int ll, int rr, int ee) {
int o = ll; // b[] index
int l = ll; // a[] left index
int r = rr; // a[] right index
while(true){ // merge data
if(a[l] <= a[r]){ // if a[l] <= a[r]
b[o++] = a[l++]; // copy a[l]
if(l < rr) // if not end of left run
continue; // continue (back to while)
while(r < ee){ // else copy rest of right run
b[o++] = a[r++];
}
break; // and return
} else { // else a[l] > a[r]
b[o++] = a[r++]; // copy a[r]
if(r < ee) // if not end of right run
continue; // continue (back to while)
while(l < rr){ // else copy rest of left run
b[o++] = a[l++];
}
break; // and return
}
}
}
static int GetPassCount(int n) // return # passes
{
int i = 0;
for(int s = 1; s < n; s <<= 1)
i += 1;
return(i);
}
public static void main(String[] args) {
int[] a = new int[10000000];
Random r = new Random();
for(int i = 0; i < a.length; i++)
a[i] = r.nextInt();
long bgn, end;
bgn = System.currentTimeMillis();
MergeSort(a);
end = System.currentTimeMillis();
for(int i = 1; i < a.length; i++){
if(a[i-1] > a[i]){
System.out.println("failed");
break;
}
}
System.out.println("milliseconds " + (end-bgn));
}
}
Top down merge sort example. A pair of mutually recursive functions are used to avoid copy back operations. The direction of merge is based on the level of recursion. Merge() is the same for both bottom up and top down.
package jsorttd;
import java.util.Random;
public class jsorttd {
static void MergeSort(int[] a) // entry function
{
if(a.length < 2) // if size < 2 return
return;
int[] b = new int[a.length];
MergeSortAtoA(a, b, 0, a.length);
}
static void MergeSortAtoA(int[] a, int[] b, int ll, int ee)
{
if(ee - ll > 1) {
int rr = (ll + ee)>>1; // midpoint, start of right half
MergeSortAtoB(a, b, ll, rr);
MergeSortAtoB(a, b, rr, ee);
Merge(b, a, ll, rr, ee); // merge b to a
}
}
static void MergeSortAtoB(int[] a, int[] b, int ll, int ee)
{
if(ee - ll > 1) {
int rr = (ll + ee)>>1; //midpoint, start of right half
MergeSortAtoA(a, b, ll, rr);
MergeSortAtoA(a, b, rr, ee);
Merge(a, b, ll, rr, ee); // merge a to b
} else if((ee - ll) == 1) { // if just one element
b[ll] = a[ll]; // copy a to b
}
}
static void Merge(int[] a, int[] b, int ll, int rr, int ee) {
int o = ll; // b[] index
int l = ll; // a[] left index
int r = rr; // a[] right index
while(true){ // merge data
if(a[l] <= a[r]){ // if a[l] <= a[r]
b[o++] = a[l++]; // copy a[l]
if(l < rr) // if not end of left run
continue; // continue (back to while)
while(r < ee){ // else copy rest of right run
b[o++] = a[r++];
}
break; // and return
} else { // else a[l] > a[r]
b[o++] = a[r++]; // copy a[r]
if(r < ee) // if not end of right run
continue; // continue (back to while)
while(l < rr){ // else copy rest of left run
b[o++] = a[l++];
}
break; // and return
}
}
}
public static void main(String[] args) {
int[] a = new int[10000000];
Random r = new Random();
for(int i = 0; i < a.length; i++)
a[i] = r.nextInt();
long bgn, end;
bgn = System.currentTimeMillis();
MergeSort(a);
end = System.currentTimeMillis();
for(int i = 1; i < a.length; i++){
if(a[i-1] > a[i]){
System.out.println("failed");
break;
}
}
System.out.println("milliseconds " + (end-bgn));
}
}
Both methods take about 1 second to sort 10 million integers on my system (Win 7, Intel 3770K 3.5 ghz, NetBeans 8.1, Java 1.8.0_65-b17).

Java MergeSort speedup using Multi Threading

I'm trying to implement a version of Mergesort using Multi Threading. First off, I know there's a billion threads (give or take...) on here, and I've read a few to no avail! I'm trying to show that using threads in parallel speeds the process up. The issue I'm having however is that my code does not display and speed up whatsoever, in fact, rather the opposite.
With one thread, my times is in the 10's of thousands. With two, my time increases to a few hundred thousand, then with 4 threads my time borders on 7 figures. My initial thoughts were to play around with the join() method and ensure that was in the right place, and have done so, but to no success.
Any help would be greatly appreciated, and an example command line argument is something like;
java working 16 4 (For 4 threads).
Apologies for the lack of comments too throughout!
import java.util.*;
class working
{
private static int sizeVector;
private static int noThreads;
static void sort(int[] input)
{
mergeSort(input, 0, input.length - 1, noThreads);
}
static void mergeSort(int[] array, int low, int high, int noThreadsUp)
{
//private int noThreadsUp;
if (low < high)
{
int mid = (low+high)/2;
if (noThreadsUp > 1)
{
NewThread td = new NewThread(array, low, mid, noThreadsUp/2);
td.start();
/*try{
td.join();
}catch(Exception e){}*/
mergeSort(array, mid+1, high, noThreadsUp/2);
try{
td.join();//UNSURE WHERE THIS SHOULD BE
}catch(Exception e){}
merge(array, low, mid, high);
}
else
{
mergeSort(array, low, mid, noThreadsUp/2);
mergeSort(array, mid+1, high, noThreadsUp/2);
merge(array, low, mid, high);
}
}
}
static void merge(int[] array, int low, int mid, int high)
{
int[] temp = new int[high - low + 1];
int left = low;
int right = mid+1;
int k = 0;
while (left <= mid && right <= high)
{
if(array[left] < array[right])
{
temp[k] = array[left];
left = left+1;
}
else
{
temp[k] = array[right];
right = right + 1;
}
k = k + 1;
}
if (left <= mid)
{
while(left <= mid)
{
temp[k] = array[left];
left = left + 1;
k = k + 1;
}
}
else if (right <= high)
{
while(right <= high)
{
temp[k] = array[right];
right = right + 1;
k = k + 1;
}
}
for (int m = 0; m < temp.length; m++)
{
array[low+m] = temp[m];
}
}
static int[] readInputArray()
{
int[] a = new int[sizeVector];
for (int i = 0; i < sizeVector; i++)
{
Random generator = new Random();
a[i] = generator.nextInt();
}
return a;
}
static void printArray(int[] array)
{
for(int i = 0; i<array.length; i++)
System.out.println(array[i]);
}
public static void main(String[] args)
{
sizeVector = Integer.parseInt(args[0]);
noThreads = Integer.parseInt(args[1]);
int[] inputArray = readInputArray();
System.out.println("INPUT ARRAY: ");
printArray(inputArray);
long startTime = System.nanoTime();
sort(inputArray);
long endTime = System.nanoTime();
long finalTime = endTime - startTime;
System.out.println("SORTED ARRAY: ");
printArray(inputArray);
System.out.println("Time: " + finalTime);
}
static class NewThread extends Thread
{
private int low;
private int mid;
private int[] array;
private int noThreadsDown;
//private int threads;
public NewThread(int[] array, int low, int mid, int noThreadsDown)
{
this.low = low;//Ensure using the right start
this.mid = mid;//Ensure using the right end
this.array = array;
this.noThreadsDown = noThreadsDown;
//this.threads = threads;
}
public void run()
{
mergeSort(array, low, mid, noThreadsDown/2);
System.out.println(noThreadsDown);
}
}//End NewThread
}
It could be best using RecurssionAcition class in java 7, which split up into two parts left and right.
Sum left = new Sum(array, low, mid);
Sum right = new Sum(array, mid, high);
left.fork();
long rightAns = right.compute();
long leftAns = left.join();
return leftAns + rightAns;
Here some code that works.
public class TestMergeSort{
public static void main(String[] args){
// Threaded merge sort (and printing)
int[] toSort = {191,2,3,5,6,7,5,3,21,3,4};
printArr(toSort);
concurrentMergeSort(toSort);
printArr(toSort);
}
public static void concurrentMergeSort(int[] toSort){
int[] tmpArray = new int[toSort.length];
try{
// Start the mergesort
ConcurrentMergeSort sort = new ConcurrentMergeSort(toSort, tmpArray, 0, toSort.length - 1);
sort.start();
sort.join();
} catch(InterruptedException e){
e.printStackTrace();
}
}
public static void printArr(int[] a){
for(int i = 0; i < a.length; i++){
System.out.print(a[i] + " ,");
}
System.out.println();
}
}
public class ConcurrentMerge extends Thread{
private int[] a;
private int[] tmpArray;
private int leftPos;
private int rightPos;
private int rightEnd;
public ConcurrentMerge(int[] a, int[] tmpArray, int leftPos, int rightPos, int rightEnd){
this.a = a;
this.tmpArray = tmpArray;
this.leftPos = leftPos;
this.rightPos = rightPos;
this.rightEnd = rightEnd;
}
public void run(){
int leftEnd = rightPos - 1;
int tmpPos = leftPos;
int numElements = rightEnd - leftPos + 1;
// Main loop
while( leftPos <= leftEnd && rightPos <= rightEnd )
if( a[ leftPos ] <= a[ rightPos ] )
tmpArray[ tmpPos++ ] = a[ leftPos++ ];
else
tmpArray[ tmpPos++ ] = a[ rightPos++ ];
// Copy rest of the left half
while( leftPos <= leftEnd )
tmpArray[ tmpPos++ ] = a[ leftPos++ ];
// Copy rest of the right half
while( rightPos <= rightEnd )
tmpArray[ tmpPos++ ] = a[ rightPos++ ];
// Copy tmpArray back
for( int i = 0; i < numElements; i++){
a[ rightEnd ] = tmpArray[ rightEnd-- ];
}
}
}
import java.util.Arrays;
public class ConcurrentMergeSort extends Thread{
private int[] a;
private int[] tmpArray;
private int left;
private int right;
public ConcurrentMergeSort(int[] a, int[] tmpArray, int left, int right){
this.a = a;
this.tmpArray = tmpArray;
this.left = left;
this.right = right;
}
public void run(){
if(this.left < this.right){
try{
int center = ( this.left + this.right ) / 2;
ConcurrentMergeSort p = new ConcurrentMergeSort(this.a, this.tmpArray, this.left, center);
ConcurrentMergeSort q = new ConcurrentMergeSort(this.a, this.tmpArray, center + 1, this.right);
ConcurrentMerge r = new ConcurrentMerge(this.a, this.tmpArray, this.left, center + 1, this.right);
// Sort
p.start();
q.start();
p.join();
q.join();
// Merge
r.start();
r.join();
}
catch(InterruptedException e){
e.printStackTrace();
}
}
}
public int[] getA(){
return this.a;
}
}

Algorithm comparison in java: test program does not work

I'm trying to compare the execution of the java implementation of QuickSort and its hybrid version (using InsertionSort for those partitions which are smaller than an integer k). I wrote a test class to analyze the behaviour of the algorithms for some values ok k (1 <= k <= 25). For each value of k the class compares for different sizes of the input array the two algorithms.
I can't run the program for some values of the size of the array, for instance for values greater than 4000. The execution reach some different values and then freeze, after a while it will finish but I have no output of the computation. (I'm using eclipse).
What could be the problem? I wish to perform the comparation of the two algoritms for an array size from 10 to 10000 (at least). The code is listed below:
public class Main {
private static final int MAX_K = 25;
private static final int MAX_SIZE = 4500;
private static final int ADD_SIZE = 100;
private static int size = 10;
private static QuickSort qSort;
private static HybridSort hSort;
private static void initArray(int[] A) {
Random rand = new Random();
for (int i = 0; i < A.length; i++) {
// A[i] = (int)(Math.random()*100000);
A[i] = rand.nextInt();
}
}
private static int[] A = new int[10];
private static int[] B = new int[10];
public static void main(String[] args) {
try {
FileWriter fstream = new FileWriter("out.txt");
BufferedWriter out = new BufferedWriter(fstream);
out.write("Init file");
qSort = new QuickSort();
hSort = new HybridSort();
/************************************************/
/* Comparison */
/************************************************/
for (int i = 1; i <= MAX_K; i++) {
hSort.setK(i);
int p = 0;
for (int j = size; j <= MAX_SIZE; j = j + ADD_SIZE) {
A = new int[j];
B = new int[j];
initArray(A);
initArray(B);
long sTime = System.nanoTime();
qSort.quickSort(A, 0, A.length - 1);
long qDuration = System.nanoTime() - sTime;
sTime = System.nanoTime();
hSort.hybridSort(B, 0, B.length - 1);
long hDuration = System.nanoTime() - sTime;
out.append(/* "\nA: " +printArray(A)+ */"K: " + i + " A["
+ j + "]\tQ = " + qDuration + " H = " + hDuration
+ "\n");
String h = Long.toString(hDuration);
String q = Long.toString(qDuration);
if (h.length() < q.length()) {
p++;
out.append("\t#OUTPERM for K: "
+ i
+ "\t\t"
+ hDuration
+ "\t\t < \t\t "
+ qDuration
+ "\t\t\t\t| A[]\t\t"
+ A.length
+ ((q.length() - h.length()) == 2 ? "\t Magn. 2"
: "") + "\n");
}
}
if (p > 0)
out.append("#P= " + p + " for K= " + i + "\n\n");
}
out.append("Close file");
out.close();
} catch (IOException e) {
}
}
}
The algorithm classes:
public class QuickSort {
public void quickSort(int[] A, int left, int right){
if (left < right) {
int m = Partition(A, left, right);
quickSort(A, left, m-1);
quickSort(A, m, right);
}
}
private int Partition(int[] A, int left, int right){
int pivot = A[right];
int i = left;
int j = right;
while (true) {
while ( (A[j] > pivot)) {
j--;
}
while ((A[i] < pivot)) {
i++;
}
if (i < j){
int swap = A[j];
A[j] = A[i];
A[i] = swap;
}else{
return i;
}
}
}
}
public class HybridSort {
int k;
int m;
InsertionSort iSort;
public HybridSort() {
k = 3;
iSort = new InsertionSort();
}
public void hybridSort(int[] A, int left, int right) {
if (left < right) {
if ((right - left) < k) {
iSort.sort(A,left,right);
} else {
m = Partition(A, left, right);
hybridSort(A, left, m - 1);
hybridSort(A, m, right);
}
}
}
private int Partition(int[] A, int left, int right) {
int pivot = A[right];
int i = left;
int j = right;
while (true) {
while ((A[j] > pivot) && (j >= 0)) {
j--;
}
while ((A[i] < pivot) && (i < A.length)) {
i++;
}
if (i < j) {
int swap = A[j];
A[j] = A[i];
A[i] = swap;
} else {
return i;
}
}
}
public void setK(int k) {
this.k = k;
}
}
Your implementation of Partition is not correct. Consider the small test below (I made Partition static for my convenience).
Both while loops won't be executed, because A[i] == A[j] == pivot. Moreover, i<j, so the two elements will be swapped, resulting in exactly the same array. Therefore, the outer while loop becomes infinite.
The same problem occurs for any array for which the first and last element are the same.
public class Test {
public static void main(String[] args) {
int[] A = {1, 1};
Partition(A, 0, 1);
}
private static int Partition(int[] A, int left, int right){
int pivot = A[right];
int i = left;
int j = right;
while (true) {
while ( (A[j] > pivot)) {
j--;
}
while ((A[i] < pivot)) {
i++;
}
if (i < j){
int swap = A[j];
A[j] = A[i];
A[i] = swap;
}else{
return i;
}
}
}
}
Have you tried increasing memory settings for your code to run in eclipse.
You may find this Setting memory of Java programs that runs from Eclipse helpful.
Some tips / possible solution?:
I haven't read your implementation of QuickSort or HybridSort but I am assuming they are correct.
If you are comparing the performance of two algorithms you should most definitely compare their performance to indentical inputs. Currently you are generating two random arrys (albeit of the same size). This isn't necessarily going to be an accurate test as I can easily find a test case where one algorithm will outperform the other if the random generator is out to troll you.
Your logic for comparing the two algorithms is a bit weird and incorrect according to me. Why do you compare the lengths of the strings of the times? according to your logic 1 is the same as 9 and 1,000,000,000 is the same as 9,999,999,999 which is clearly incorrect. One algorithm is almost 10 times faster than the other.
Moreover, one reason for no output might be the reason that you are only outputing when hybridsort is better than quicksort and not the other way around. I am sure there are other reasons as well but this could be one easily noticable reason (if your implementations are incorrect).
I do notice that you close your outputstream which is good as that is a very common reason why there is no output. You should however, close steams in the finally section of the try-catch as then they are guaranteed to close. You could be getting an IOException and in your case this would also not close the outputsteam and consequently lead to no ouput in your file.
Here is a sample structure that I would follow for doing any comparitive testing. It is easy to read and easy to debug with enough output for you to figure out which algorithm performs better. This is merely a suggestion.
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.Random;
public class Tester {
private static int[] initArray(int size) {
Random rand = new Random();
int[] arr = new int[size];
for (int i = 0; i < arr.length; i++) {
arr[i] = rand.nextInt();
}
return arr;
}
public static void main(String[] args) {
final int MAX_ITERATIONS = 25;
final int INITIAL_ARRAY_SIZE = 10;
final int MAX_ARRAY_SIZE = 4500;
final int ARRAY_SIZE_INCREMENT = 100;
long start;
int[] score = null;
PrintWriter out = null;
try {
out = new PrintWriter(new FileOutputStream("out.txt"));
for (int arraySize = INITIAL_ARRAY_SIZE; arraySize <= MAX_ARRAY_SIZE; arraySize += ARRAY_SIZE_INCREMENT) {
// score[0] is for quickSort and score[1] is for hybridSort
score = new int[2];
for (int iteration = 0; iteration < MAX_ITERATIONS; iteration++) {
int[] testArray = initArray(arraySize);
int[] testArrayCopy = new int[arraySize];
System.arraycopy(testArray, 0, testArrayCopy, 0, arraySize);
start = System.nanoTime();
// Do quicksort here using testArray
long qSortfinish = System.nanoTime() - start;
System.arraycopy(testArray, 0, testArrayCopy, 0, arraySize);
start = System.nanoTime();
// Do hybridsort here using testArrayCopy
long hybridSortfinish = System.nanoTime() - start;
// Keep score
if (qSortfinish < hybridSortfinish)
score[0]++;
else if (qSortfinish > hybridSortfinish) {
score[1]++;
} else {
score[0]++;
score[1]++;
}
}
out.println("Array Size: " + arraySize + " QuickSort: " + score[0] + " HybridSort: " + score[1]);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (out != null)
out.close();
}
}
}

Is this a new sorting algorithm? [with Java and Pseudo-code implementation]

I know this may be a stupid question, maybe the most stupid question today, but I have to ask it: Have I invented this sorting algorithm?
Yesterday, I had a little inspiration about an exchange-based sorting algorithm. Today, I implemented it, and it worked.
It probably already exists, since there are many not-so-popular sorting algorithms out there that has little or none information about, and almost no implementation of them exist.
Description: Basically, this algorithm takes an item, them a pair, then an item again... until the end of the list. For each item/pair, compare EVERY two items at the same radius distance from pair space or item, until a border of the array is reached, and then exchange those items if needed. Repeat this for each pair/item of the list.
An English-based pseudo-code:
FOR i index to last index of Array (starting from 0)
L index is i - 1
R index is i + 1
//Odd case, where i is the center
WHILE (L is in array range and R is in array range)
IF item Array[L] is greater than Array[R]
EXCHANGE item Array[L] with Array[R]
END-IF
ADD 1 to R
REST 1 to L
END-WHILE
//Even case, where i is not the center
L index is now i
R index in now i + 1
WHILE (L is in array range and R is in array range)
IF item Array[L] is greater than Array[R]
EXCHANGE Array[L] with Array[R]
END-IF
ADD 1 to R
REST 1 to L
END-WHILE
END FOR
This is the implementation in Java:
//package sorting;
public class OrbitSort {
public static void main(String[] args) {
int[] numbers ={ 15, 8, 6, 3, 11, 1, 2, 0, 14, 13, 7, 9, 4, 10, 5, 12 };
System.out.println("Original list:");
display(numbers);
sort(numbers);
System.out.println("\nSorted list:");
display(numbers);
}
//Sorting algorithm
public static void sort(int[] array) {
for(int i = 0; i < array.length; i++){
int L = i - 1;
int R = i + 1;
//Odd case (with a central item)
while(L >= 0 && R < array.length){
if(array[L] > array[R])
swap(array, L, R);
L--;
R++;
}
//Even case (with no central item)
L = i;
R = i + 1;
while(L >= 0 && R < array.length) {
if(array[L] > array[R])
swap(array, L, R);
L--;
R++;
}
}
}
//Swap two items in array.
public static void swap(int[] array, int x, int y) {
int temp = array[x];
array[x] = array[y];
array[y] = temp;
}
//Display items
public static void display(int[] numbers){
for(int i: numbers)
System.out.print(" " + i);
System.out.println();
}
}
I know can be shorter, but it's just an early implementation.
It probably runs in O(n^2), but I'm not sure.
So, what do you think? Does it already exists?
To me, it looks like a modified bubble sort algo, which may perform better for certain arrangements of input elements.
Altough not necessarily fair, I did a benchmark with warmup cycles using your input array, for comparison of:
java.util.Arrays.sort(), which is a merge quick sort implementation
BubbleSort.sort(), a java implementation of the bubble sort algo
OrbitSort.sort(), your algo
Results:
input size: 8192
warmup iterations: 32
Arrays.sort()
iterations : 10000
total time : 4940.0ms
avg time : 0.494ms
BubbleSort.sort()
iterations : 100
total time : 8360.0ms
avg time : 83.6ms
OrbitSort.sort()
iterations : 100
total time : 8820.0ms
avg time : 88.2ms
Of course, the performance depends on input size and arrangement
Straightforward code:
package com.sam.tests;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.Callable;
public class SortBenchmark {
public static class OrbitSort {
// Sorting algorithm
public static void sort(int[] array) {
for (int i = 0; i < array.length; i++) {
int L = i - 1;
int R = i + 1;
// Odd case (with a central item)
while (L >= 0 && R < array.length) {
if (array[L] > array[R])
swap(array, L, R);
L--;
R++;
}
// Even case (with no central item)
L = i;
R = i + 1;
while (L >= 0 && R < array.length) {
if (array[L] > array[R])
swap(array, L, R);
L--;
R++;
}
}
}
// Swap two items in array.
public static void swap(int[] array, int x, int y) {
int temp = array[x];
array[x] = array[y];
array[y] = temp;
}
}
public static class BubbleSort {
public static void sort(int[] numbers) {
boolean swapped = true;
for (int i = numbers.length - 1; i > 0 && swapped; i--) {
swapped = false;
for (int j = 0; j < i; j++) {
if (numbers[j] > numbers[j + 1]) {
int temp = numbers[j];
numbers[j] = numbers[j + 1];
numbers[j + 1] = temp;
swapped = true;
}
}
}
}
}
public static class TestDataFactory {
public static enum ElementOrder {
Ascending, Descending, Random
}
public static int[] createIntArray(final int size, final ElementOrder elementOrder) {
int[] array = new int[size];
switch (elementOrder) {
case Ascending:
for (int i = 0; i < size; ++i)
array[i] = i;
break;
case Descending:
for (int i = 0; i < size; ++i)
array[i] = size - i - 1;
break;
case Random:
default:
Random rg = new Random(System.nanoTime());
for (int i = 0; i < size; ++i)
array[i] = rg.nextInt(size);
break;
}
return array;
}
}
public static class Benchmark {
// misc constants
public static final int NANOS_PER_MSEC = 1000000;
// config constants
public static final int BIGDECIMAL_PRECISION = 6;
// constant defaults
public static final long AUTOTUNING_MIN_ITERATIONS_DEFAULT = 1;
public static final long AUTOTUNING_MIN_DURATION_DEFAULT = 125;
public static final long BENCHMARK_MIN_ITERATIONS_DEFAULT = 1;
public static final long BENCHMARK_MAX_ITERATIONS_DEFAULT = Integer.MAX_VALUE;
public static final long BENCHMARK_TARGET_DURATION_DEFAULT = 125;
// private static final ThreadMXBean threadBean =
// ManagementFactory.getThreadMXBean();
public static final long getNanoTime() {
// return threadBean.getCurrentThreadCpuTime();// not good, runs at
// some time slice resolution
return System.nanoTime();
}
public static class Result {
public String name;
public long iterations;
public long totalTime; // nanoseconds
public Result(String name, long iterations, long startTime, long endTime) {
this.name = name;
this.iterations = iterations;
this.totalTime = endTime - startTime;
}
#Override
public String toString() {
final double totalTimeMSecs = ((double) totalTime) / NANOS_PER_MSEC;
final BigDecimal avgTimeMsecs = new BigDecimal(this.totalTime).divide(new BigDecimal(this.iterations).multiply(new BigDecimal(NANOS_PER_MSEC)),
BIGDECIMAL_PRECISION, RoundingMode.HALF_UP);
final String newLine = System.getProperty("line.separator");
StringBuilder sb = new StringBuilder();
sb.append(name).append(newLine);
sb.append(" ").append("iterations : ").append(iterations).append(newLine);
sb.append(" ").append("total time : ").append(totalTimeMSecs).append(" ms").append(newLine);
sb.append(" ").append("avg time : ").append(avgTimeMsecs).append(" ms").append(newLine);
return sb.toString();
}
}
public static <T> Result executionTime(final String name, final long iterations, final long warmupIterations, final Callable<T> test) throws Exception {
// vars
#SuppressWarnings("unused")
T ret;
long startTime;
long endTime;
// warmup
for (long i = 0; i < warmupIterations; ++i)
ret = test.call();
// actual benchmark iterations
{
startTime = getNanoTime();
for (long i = 0; i < iterations; ++i)
ret = test.call();
endTime = getNanoTime();
}
// return result
return new Result(name, iterations, startTime, endTime);
}
/**
* Auto tuned execution time measurement for test callbacks with steady
* execution time
*
* #param name
* #param test
* #return
* #throws Exception
*/
public static <T> Result executionTimeAutotuned(final String name, final Callable<T> test) throws Exception {
final long autoTuningMinIterations = AUTOTUNING_MIN_ITERATIONS_DEFAULT;
final long autoTuningMinDuration = AUTOTUNING_MIN_DURATION_DEFAULT;
final long benchmarkTargetDuration = BENCHMARK_TARGET_DURATION_DEFAULT;
final long benchmarkMinIterations = BENCHMARK_MIN_ITERATIONS_DEFAULT;
final long benchmarkMaxIterations = BENCHMARK_MAX_ITERATIONS_DEFAULT;
// vars
#SuppressWarnings("unused")
T ret;
final int prevThreadPriority;
long warmupIterations = 0;
long autoTuningDuration = 0;
long iterations = benchmarkMinIterations;
long startTime;
long endTime;
// store current thread priority and set it to max
prevThreadPriority = Thread.currentThread().getPriority();
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
// warmup and iteration count tuning
{
final long autoTuningMinTimeNanos = autoTuningMinDuration * NANOS_PER_MSEC;
long autoTuningConsecutiveLoops = 1;
double avgExecutionTime = 0;
do {
{
startTime = getNanoTime();
for (long i = 0; i < autoTuningConsecutiveLoops; ++i, ++warmupIterations) {
ret = test.call();
}
endTime = getNanoTime();
autoTuningDuration += (endTime - startTime);
}
avgExecutionTime = ((double) autoTuningDuration) / ((double) (warmupIterations));
if ((autoTuningDuration >= autoTuningMinTimeNanos) && (warmupIterations >= autoTuningMinIterations)) {
break;
} else {
final double remainingAutotuningIterations = ((double) (autoTuningMinTimeNanos - autoTuningDuration)) / avgExecutionTime;
autoTuningConsecutiveLoops = Math.max(1, Math.min(Integer.MAX_VALUE, (long) Math.ceil(remainingAutotuningIterations)));
}
} while (warmupIterations < Integer.MAX_VALUE);
final double requiredIterations = ((double) benchmarkTargetDuration * NANOS_PER_MSEC) / avgExecutionTime;
iterations = Math.max(1, Math.min(benchmarkMaxIterations, (long) Math.ceil(requiredIterations)));
}
// actual benchmark iterations
{
startTime = getNanoTime();
for (long i = 0; i < iterations; ++i)
ret = test.call();
endTime = getNanoTime();
}
// restore previous thread priority
Thread.currentThread().setPriority(prevThreadPriority);
// return result
return new Result(name, iterations, startTime, endTime);
}
}
public static void executeBenchmark(int inputSize, ArrayList<Benchmark.Result> results) {
// final int[] inputArray = { 15, 8, 6, 3, 11, 1, 2, 0, 14, 13, 7, 9, 4,
// 10, 5, 12 };
final int[] inputArray = TestDataFactory.createIntArray(inputSize, TestDataFactory.ElementOrder.Random);
try {
// compare against Arrays.sort()
{
final int[] ref = inputArray.clone();
Arrays.sort(ref);
{
int[] temp = inputArray.clone();
BubbleSort.sort(temp);
if (!Arrays.equals(temp, ref))
throw new Exception("BubbleSort.sort() failed");
}
{
int[] temp = inputArray.clone();
OrbitSort.sort(temp);
if (!Arrays.equals(temp, ref))
throw new Exception("OrbitSort.sort() failed");
}
}
results.add(Benchmark.executionTimeAutotuned("Arrays.sort()", new Callable<Void>() {
#Override
public Void call() throws Exception {
int[] temp = Arrays.copyOf(inputArray, inputArray.length);
Arrays.sort(temp);
return null;
}
}));
results.add(Benchmark.executionTimeAutotuned("BubbleSort.sort()", new Callable<Void>() {
#Override
public Void call() throws Exception {
int[] temp = Arrays.copyOf(inputArray, inputArray.length);
BubbleSort.sort(temp);
return null;
}
}));
results.add(Benchmark.executionTimeAutotuned("OrbitSort.sort()", new Callable<Void>() {
#Override
public Void call() throws Exception {
int[] temp = Arrays.copyOf(inputArray, inputArray.length);
OrbitSort.sort(temp);
return null;
}
}));
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ArrayList<Benchmark.Result> results = new ArrayList<Benchmark.Result>();
for (int i = 16; i <= 16384; i <<= 1) {
results.clear();
executeBenchmark(i, results);
System.out.println("input size : " + i);
System.out.println("");
for (Benchmark.Result result : results) {
System.out.print(result.toString());
}
System.out.println("----------------------------------------------------");
}
}
}
It is O(n^2) (assuming it works, I am not sure about that), as to already exists - maybe - it is not really original, as it can be considered a variation of a trivial sorting implementation, but I doubt if there is any published algorithm which is exactly the same as this one, specifically one with two consecutive inner loops.
I am not saying it is without merit, there can be a use case for which its behavior is uniquely efficient (maybe where reading is much faster than writing, and cache behavior benefits its access pattern).
To see why it is O(n^2), think about the first n/6 outer loop iterations, the inner loops run on O(n) length O(n) times.

Categories

Resources