I have a task where I need to sort an array by quicksort algorithm. Size of array and amount of threads can be custom. Also I've have to merge threads like on picture: here
As I understood I need to split an array by amount of proccessors and sorted it.
class Quicksort implements Callable<int[]>{
int[] arr;
Quicksort(int[] array){
this.arr = array;
}
#Override
public int[] call() throws Exception {
sort(arr,0,arr.length-1);
long threadId = Thread.currentThread().getId();
return arr;
}
/* This function takes last element as pivot,
places the pivot element at its correct
position in sorted array, and places all
smaller (smaller than pivot) to left of
pivot and all greater elements to right
of pivot */
int partition(int arr[], int low, int high)
{
int pivot = arr[high];
int i = (low-1); // index of smaller element
for (int j=low; j<high; j++)
{
// If current element is smaller than or
// equal to pivot
if (arr[j] <= pivot)
{
i++;
// swap arr[i] and arr[j]
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
// swap arr[i+1] and arr[high] (or pivot)
int temp = arr[i+1];
arr[i+1] = arr[high];
arr[high] = temp;
return i+1;
}
/* The main function that implements QuickSort()
arr[] --> Array to be sorted,
low --> Starting index,
high --> Ending index */
void sort(int arr[], int low, int high)
{
if (low < high)
{
/* pi is partitioning index, arr[pi] is
now at right place */
int pi = partition(arr, low, high);
// Recursively sort elements before
// partition and after partition
sort(arr, low, pi-1);
sort(arr, pi+1, high);
}
}
In Main class I'm using ExecutorService to do sorting stuff
public static void main(String args[]) {
List<int[]> chunckedList = Utils.covertFrom2DToList(chuncked);
try {
ExecutorService executorService = Executors.newFixedThreadPool(10);
List<Quicksort> callableList = new ArrayList<>();
for (int[] chunck : chunckedList) {
callableList.add(new Quicksort(chunck));
}
List<Future<int[]>> futureObjects = executorService.invokeAll(callableList);
executorService.shutdown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
But I have no idea how to merge it in threads.
Could you give me a hint or advice how to implement it. Thanks!
Related
I have two implementation of quick sort the first one uses a median of (fist ,middle , last ) as pivot and the second uses the middle element as pivot
the first Implementation :
public class quickMedian {
public void sort(int array[])
// pre: array is full, all elements are non-null integers
// post: the array is sorted in ascending order
{
quickSort(array, 0, array.length - 1); // quicksort all the elements in the array
}
public void quickSort(int array[], int start, int end)
{
int i = start; // index of left-to-right scan
int k = end; // index of right-to-left scan
if (end - start >= 1) // check that there are at least two elements to sort
{
if (array[start+(end-start)/2]>array[end]){
swap(array,start+(end-start)/2, end);
}
if (array[start]>array[end]){
swap(array,start, end);
}
if (array[start+(end-start)/2]>array[start]){
swap(array, start+(end-start)/2, start);
}
int pivot = array[start]; // set the pivot as the first element in the partition
while (k > i) // while the scan indices from left and right have not met,
{
while (array[i] <= pivot && i <= end && k > i) // from the left, look for the first
i++; // element greater than the pivot
while (array[k] > pivot && k >= start && k >= i) // from the right, look for the first
k--; // element not greater than the pivot
if (k > i) // if the left seekindex is still smaller than
swap(array, i, k); // the right index, swap the corresponding elements
}
swap(array, start, k); // after the indices have crossed, swap the last element in // the left partition with the pivot
quickSort(array, start, k - 1); // quicksort the left partition
quickSort(array, k + 1, end); // quicksort the right partition
}
else // if there is only one element in the partition, do not do any sorting
{
return; // the array is sorted, so exit
}
}
public void swap(int array[], int index1, int index2)
// pre: array is full and index1, index2 < array.length
// post: the values at indices 1 and 2 have been swapped
{
int temp = array[index1]; // store the first value in a temp
array[index1] = array[index2]; // copy the value of the second into the first
array[index2] = temp; // copy the value of the temp into the second
}
}
The second Implementation :
public class quickSort {
private int array[];
private int length;
public void sort(int[] inputArr) {
if (inputArr == null || inputArr.length == 0) {
return;
}
this.array = inputArr;
length = inputArr.length;
quickSorter(0, length - 1);
}
private void quickSorter(int lowerIndex, int higherIndex) {
int i = lowerIndex;
int j = higherIndex;
// calculate pivot number, I am taking pivot as middle index number
int pivot = array[lowerIndex+(higherIndex-lowerIndex)/2];
// Divide into two arrays
while (i <= j) {
/**
* In each iteration, we will identify a number from left side which
* is greater then the pivot value, and also we will identify a number
* from right side which is less then the pivot value. Once the search
* is done, then we exchange both numbers.
*/
while (array[i] < pivot) {
i++;
}
while (array[j] > pivot) {
j--;
}
if (i <= j) {
exchangeNumbers(i, j);
//move index to next position on both sides
i++;
j--;
}
}
// call quickSort() method recursively
if (lowerIndex < j)
quickSorter(lowerIndex, j);
if (i < higherIndex)
quickSorter(i, higherIndex);
}
private void exchangeNumbers(int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
To obtain the median we need to do extra steps on each recursion which may increase the time a little bit (if the array is totally random) .
I am testing these two classes on an array of size N=10,000,000 randomly generated and I have done the test many times the first Implementation takes around 30 seconds and the second takes around 4 seconds
so this is obviously not caused by the extra overhead to get the median of three numbers .
There must be something wrong with the first implementation, what is it ?
here is the testing code :
public static void main(String[] args) {
File number = new File ("f.txt");
final int size = 10000000;
try{
// quickSort s = new quickSort();
quickMedian s = new quickMedian();
writeTofile(number, size);
int [] arr1 =readFromFile(number, size);
long a=System.currentTimeMillis();
s.sort(arr1);
long b=System.currentTimeMillis();
System.out.println("quickSort: "+(double)(b-a)/1000);
}catch (Exception ex){ex.printStackTrace();}
}
I'm trying to count minimum swaps(only consecutive swaps) in an array sorted by mergesort. It works for some cases but this case doesn't work for example: http://puu.sh/kC9mg/65e055807f.png. The first number is how many numbers it should sort, then you enter the numbers. In that case it should print 1 because the number of minimum consecutive swaps is 1 in this case which will swap 4 and 3.
This is the code I have:
public class MergeSort {
private int[] numbers;
private int[] helper;
private int number;
private long swapCounter = 0;
public MergeSort(int[] inputNumbers)
{
numbers = inputNumbers;
number = inputNumbers.length;
helper = new int[number];
mergesort(0, number-1);
}
private void mergesort(int low, int high) {
// check if low is smaller then high, if not then the array is sorted
if (low < high) {
// Get the index of the element which is in the middle
int middle = low + (high - low) / 2;
// Sort the left side of the array
mergesort(low, middle);
// Sort the right side of the array
mergesort(middle + 1, high);
// Combine them both
merge(low, middle, high);
}
}
private void merge(int low, int middle, int high) { // Merge it
long internCounter = 0;
for (int i = low; i <= high; i++) { // Copy both parts into the helper array
helper[i] = numbers[i];
}
int i = low;
int j = middle + 1;
int k = low;
while (i <= middle && j <= high) { // Copy the smallest values from either the left or the right side back to the original array
if (helper[i] < helper[j]) {
numbers[k] = helper[i];
i++;
internCounter++;
} else {
numbers[k] = helper[j];
j++;
swapCounter += internCounter;
}
k++;
}
while (i <= middle) { // Copy the rest of the left side of the array into the target array
numbers[k] = helper[i];
k++;
i++;
swapCounter += internCounter;
}
}
public long getCounter() // Get the counter
{
return this.swapCounter;
}
}
And this is my main class:
import java.util.Scanner;
public class Fr {
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
int numberOfStudents;
int[] inputNumbers2;
numberOfStudents = input.nextInt();
inputNumbers2 = new int[numberOfStudents];
for(int i = 0; i < numberOfStudents; i++)
{
inputNumbers2[i] = input.nextInt();
}
MergeSort ms = new MergeSort(inputNumbers2);
System.out.println(ms.getCounter());
input.close();
}
}
Do anyone have any thoughts what could be wrong?
I don't think you need the intern counter at all. Just count how many positions you swap an element when taking an element from the high half:
public class MergeSort {
private int[] numbers;
private int[] helper;
private int number;
private long swapCounter = 0;
public MergeSort(int[] inputNumbers)
{
numbers = inputNumbers;
number = inputNumbers.length;
helper = new int[number];
mergesort(0, number-1);
}
private void mergesort(int low, int high) {
// check if low is smaller then high, if not then the array is sorted
if (low < high) {
// Get the index of the element which is in the middle
int middle = low + (high - low) / 2;
// Sort the left side of the array
mergesort(low, middle);
// Sort the right side of the array
mergesort(middle + 1, high);
// Combine them both
merge(low, middle, high);
}
}
private void merge(int low, int middle, int high) { // Merge it
for (int i = low; i <= high; i++) { // Copy both parts into the helper array
helper[i] = numbers[i];
}
int i = low;
int j = middle + 1;
int k = low;
while (i <= middle && j <= high) { // Copy the smallest values from either the left or the right side back to the original array
if (helper[i] < helper[j]) {
numbers[k] = helper[i];
i++;
} else {
numbers[k] = helper[j];
swapCounter += (j-k);
j++;
}
k++;
}
while (i <= middle) { // Copy the rest of the left side of the array into the target array
numbers[k] = helper[i];
k++;
i++;
}
}
public long getCounter() // Get the counter
{
return this.swapCounter;
}
}
I am currently working with mergeSort. I have come across a task that ask me specifically to NOT use temporary arrays to create a mergeSort. So recursion is the way to go. Here's my code:
UPDATE: Posted the rest of the code, by request.
public class RecursiveMergeSort {
public static void mergeSort(int[] list){
mergeSort(list, 0, list.length - 1);
}
private static void mergeSort(int[] list, int low, int high){
if(low < high){
//recursive call to mergeSort, one for each half
mergeSort(list, low, (high/2));
mergeSort(list, list.length/2, high);
int[] temp = merge(list, low, high);
System.arraycopy(temp, 0, list, low, high - low + 1);
}
}
private static int[] merge(int[] list, int low, int high){
int[] temp = new int[high - low + 1];
int mid = (high/2) + 1;
if(list[low] < list[mid] && mid < list.length){
temp[low] = list[low];
temp[mid] = list[mid];
}
if(list[low] > list[mid] && mid < list.length){
temp[low] = list[mid];
temp[mid] = list[low];
}
low++;
mid++;
return temp;
}
public static void main(String[] args) {
int[] list = {2, 3, 4, 5};
mergeSort(list);
for(int i = 0; i < list.length; i++){
System.out.println(list[i] + " ");
}
}
}
I'm supposed to recursively divide and conquer this. However, I get stuck at a infinite loop that causes stack overflow(naturally) for the second half. And I am at a complete loss for figuring out a gentle and smooth way to tell my method to keep splitting. Bear in mind that the if statement in my snippet is supposed to be there, by courtesy of our teacher.
The low and high values are the lowest and the highest Index for the array passed in the method.
Need a pointer please.
I modified quick sort to make it multithread.
I expected it to work , coz the original algorithm was working.
After partitioning, for the recursive calls to left and right of pivot .. I am creating a new thread.
public class QuickSort extends Thread{
private int[] arr;
private int left;
private int right;
public QuickSort(int[] arr){
this.arr= arr;
this.left=0;
this.right=arr.length -1;
this.start();
}
public QuickSort(int[] arr, int left , int right){
this.arr= arr;
this.left=left;
this.right=right;
this.start();
}
int partition( int left, int right)
{
int i = left, j = right;
int tmp;
int pivot = arr[(left + right) / 2];
while (i <= j) {
while (arr[i] < pivot)
i++;
while (arr[j] > pivot)
j--;
if (i <= j) {
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i++;
j--;
}
};
return i;
}
void quickSort(int left, int right) {
int index = partition(left, right);
if (left < index - 1)
new QuickSort(arr, left , index -1);
if (index < right)
new QuickSort(arr ,index, right);
}
public void run(){
quickSort(left , right);
}
public static void main(String arg[])
{
int[] s = {100,99,98,97,96,95,94,93,92,91};
new QuickSort(s);
for(int i: s)
System.out.println(i);
}
}
Your first problem is that you aren't waiting for any thread to exit, so you are printing the data while the threads are still running. You need some Thread.join() calls.
I'm not saying there aren't other problems ... Your sort fails if there are already sorted elements, e.g. if you add 89,90 to your test array.
For one thing, you're never waiting for any of the threads to finish. So by the time you go to print out the array who knows how much work has been done.
You'll need to somehow join() the threads you've spun up (or come up with some other mechanism to figure out they're done).
I have the code below that I have found. I am trying to learn which sorting method is the fastest and which ones use the most and least comparisons. Anyone have any idea how I can add some code in here to do that? I want to tally the total number of comparisons of each sort.
//***********************************************************************************
// Sorting.java
//
// Contains various sort algorithms that operate on an array of comparable objects.
//
//************************************************************************************
public class Sorting
{
//------------------------------------------------------------------------------------
// Sorts the specified array of integers using the selection sort algorithm.
//------------------------------------------------------------------------------------
public static void selectionSort (Comparable[] data)
{
int min;
for (int index = 0; index < data.length-1; index ++)
{
min = index;
for (int scan = index+1; scan < data.length; scan++)
if (data[scan].compareTo(data[min]) < 0)
min = scan;
swap (data, min, index);
}
}
//---------------------------------------------------------------------------------------
// Swaps to elements in the specified array.
//---------------------------------------------------------------------------------------
private static void swap (Comparable[] data, int index1, int index2)
{
Comparable temp = data[index1];
data[index1] = data[index2];
data[index2] = temp;
}
//---------------------------------------------------------------------------------------
// Sorts the specified array of objects using an insertion sort algorithm.
//---------------------------------------------------------------------------------------
public static void insertionSort (Comparable[] data)
{
for (int index = 1; index < data.length; index++)
{
Comparable key = data[index];
int position = index;
// shift larger values to the right
while (position > 0 && data[position-1].compareTo(key) > 0)
{
data[position] = data[position-1];
position--;
}
data[position] = key;
}
}
//---------------------------------------------------------------------------------------
// Sorts the specified array of objects using a bubble sort algorithm.
//---------------------------------------------------------------------------------------
public static void bubbleSort (Comparable[] data)
{
int position, scan;
for (position = data.length - 1; position >= 0; position--)
{
for (scan = 0; scan <= position - 1; scan ++)
if (data[scan].compareTo(data[scan+1]) >0)
swap (data, scan, scan+1);
}
}
//---------------------------------------------------------------------------------------
// Sorts the specified array of objects using the quick sort algorithm.
//---------------------------------------------------------------------------------------
public static void quickSort (Comparable[] data, int min, int max)
{
int pivot;
if (min < max)
{
pivot = partition (data, min, max); // make partitions
quickSort(data, min, pivot-1); //sort left paritions
quickSort(data, pivot+1, max); //sort right paritions
}
}
//---------------------------------------------------------------------------------------
// Creates the partitions needed for quick sort.
//---------------------------------------------------------------------------------------
public static int partition (Comparable[] data, int min, int max)
{
//Use first element as the partition value
Comparable partitionValue = data[min];
int left = min;
int right = max;
while (left < right)
{
// Search for an element that is greater than the partition element
while (data[left].compareTo(partitionValue) <= 0 && left < right)
left++;
// Search for an element that is less than the partition element
while (data[right].compareTo(partitionValue) > 0)
right--;
if (left < right)
swap (data, left, right);
}
// Move the partition element to its final position
swap (data, min, right);
return right;
}
//---------------------------------------------------------------------------------------
// Sorts the specified array of objects using the merge sort algorithm.
//---------------------------------------------------------------------------------------
public static void mergeSort (Comparable[] data, int min, int max)
{
if (min < max)
{
int mid = (min + max) / 2;
mergeSort(data, min, mid);
mergeSort(data, mid+1, max);
merge (data, min, mid, max);
}
}
//---------------------------------------------------------------------------------------
// Sorts the specified array of objects using the merge sort algorithm.
//---------------------------------------------------------------------------------------
public static void merge (Comparable[] data, int first, int mid, int last)
{
Comparable[] temp = new Comparable[data.length];
int first1 = first, last1 = mid; //endpoints of first subarray
int first2 = mid + 1, last2 = last; //endpoints of second subarray
int index = first1; // next index open in temp array
// Copy smaller item from each subarry into temp until one of the subarrays is exhausted
while (first1 <= last1 && first2 <= last2)
{
if (data[first1].compareTo(data[first2]) < 0)
{
temp[index] = data[first1];
first1++;
}
else
{
temp[index] = data[first2];
first2++;
}
index++;
}
// Copy remaining elements from first subarray, if any
while (first1 <= last1)
{
temp[index] = data[first1];
first1++;
index++;
}
// Copy remaining elements from second subarray, if any
while (first2 <= last2)
{
temp[index] = data[first2];
first2++;
index++;
}
// Copy merged data into original array
for (index = first; index <= last; index++)
data[index] = temp[index];
}
}
If you're interested in speed, use Arrays.sort(). If you're academically interested in what's involved in various sorting techniques, it's probably faster to just look at Wikipedia. If you want us to do your homework for you...we won't, sorry.
Edit: I guess it's fair for me to say this: Is there any reason you couldn't just initialize an integer to 0 at the start of each method, increment it every time something interesting happened, and then print it at the end?
Rather learn about O-notation from a good book like:
http://www.amazon.com/Data-Structures-Algorithms-Java-2nd/dp/0672324539
You should define an abstract class that implements the counting, and then some derived classes that implement the algorithms. The main program would look like this:
List<String> list = new ArrayList<String>();
// TODO: add some elements to the list
SortingAlgorithm alg = new BubbleSort();
alg.sort(list);
alg.printSummary();
Now the abstract class that implements the counting:
public abstract class SortingAlgorithm<T> {
/* the actual algorithm, which uses the compare and swap methods. */
public abstract void sort(List<T> list);
private long compares = 0;
private long swaps = 0;
protected int compare(T a, T b) {
compares++;
return a.compareTo(b);
}
protected void swap(int index1, int index2) {
swaps++;
// TODO: do the actual swapping
}
public void printSummary() {
// TODO
}
}
The concrete algorithms now only have to implement the sort method. How to do this is left as an excercise for the reader.