Learning about sorting need some help? - java

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.

Related

Binary search algorithm check if an integer is contained in an array

I am having trouble implementing binary search within my code, can you explain how it works.
binarySearch takes an array of integers a and an integer n and uses
binary search algorithm check if n is contained in a. it returns true if n is
contained in a, as well as printing the number of decision made and false
otherwise.
import java.util.Arrays;
import java.util.Random;
public class Excersice2 {
public static void main(String[] args) {
int[] arr = createArray(10);
System.out.println("the array not sorted");
printArray(arr);
arr = sortArray(arr);
System.out.println("the array sorted");
printArray(arr);
System.out.println(binarySearch(arr,50));
}
public static void printArray(int []arr)
{
System.out.println(Arrays.toString(arr));
}
public static int [] createArray(int n) {
int[] arr = new int[n];
Random rand = new Random();
for(int i = 0; i < n; i++)
arr[i] = rand.nextInt(101);
return arr;
}
public static int[] sortArray(int[] arr) {
Arrays.sort(arr);
return arr;
}
public static boolean binarySearch(int arr[], int n) {
int firstIdx = 0;
int lastIdx = - 1;
int middle = (firstIdx + lastIdx)/2;
int idx = arr.length/2;
while( firstIdx <= lastIdx) {
if(binarySearch[middle] < arr);
}
}
}
The outcomes should look:
It took 2 times to find that the value 50 is contained the array. When looking through the list
You can use Binary Search Algorith when you have an array of numbers and your array is sorted.
Algorithm checks if the key (the number you are looking for) is equal with the middle value of the array.
If it is, the searching is done and the key is at the middle position.
If it isnt, then the algorithm checks if the key is greater or less than the middle value.
if it is greater, then the algorithm repeats the search only at the second half of the array, taking as left the next position of the middle.
If it is less, then only at the first half taking as right the position before the middle.
And repeats that until the key is found or there is no more positions in array.
Calling the binary search method
//the number you are looking for. For example 4.
int key = 4;
//the first element of array
int left = 0;
//the last element of array
int right = arr.length - 1;
int pos = binarySearch(left, right, key);
if(pos == -1) { System.out.println("Array does not contain key"); }
else { System.out.println("Array contains key at position : " + pos); }
Binary Search Algorithm method
int binarySearch(int left, int right, int key) {
int pos;
int mid;
if(left > right) {
//there is no more positions to search
pos = -1;
} else {
//Getting the middle position of array
mid = (left + right) / 2;
//if the key is the middle positions value
if(arr[mid] == key)
pos = mid;
//if the key is less than the middle value
else if(key < arr[mid])
//repeat the search only at the first half of array
pos = binarySearch(left, mid-1, key);
else
//else if the key is greater than the middle value
//search at the second half of array
pos = binarySearch(mid+1, right, key);
}
return pos;
}

Mergin threads by treebased pattern

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!

Finding a more efficient heap sort?

Current I have a home work question which says,
It is possible to make the heap sort algorithm more efficient by
writing a method that will order the entire list at once instead of
adding the elements one at a time.
However I can't figure out what exactly it means by "instead of adding elements one at a time", surely one has to building a heap first (which involves adding element from a unsorted list one by one), then remove the largest from the heap one at a time.
Here is my heap array:
import exceptions.exceptions.*;
public class ArrayHeap<T> extends ArrayBinaryTree<T> implements HeapADT<T> {
public ArrayHeap(){
super();
}
public void addElement (T element){
if (count==size())
expandCapacity();
tree[count] = element;
count++;
if (count > 1)
heapifyAdd();
}
private void heapifyAdd(){
int index = count - 1;
while ((index != 0) && (((Comparable)tree[index]).compareTo(tree[(index-1)/2]) < 0))
{
T temp = tree[index];
tree[index] = tree[(index-1)/2];
tree[(index-1)/2] = temp;
index = (index-1)/2;
}
}
public T removeMin(){
if (isEmpty())
throw new EmptyCollectionException ("Empty Heap");
T minElement = findMin();
tree[0] = tree[count-1];
heapifyRemove();
count--;
return minElement;
}
private void heapifyRemove()
{
T temp;
int node = 0;
int left = 1;
int right = 2;
int next;
if ((tree[left] == null) && (tree[right] == null))
next = count;
else if (tree[left] == null)
next = right;
else if (tree[right] == null)
next = left;
else if (((Comparable)tree[left]).compareTo(tree[right]) < 0)
next = left;
else
next = right;
while ((next < count) && (((Comparable)tree[next]).compareTo(tree[node]) < 0)){
temp = tree[node];
tree[node] = tree[next];
tree[next] = temp;
node = next;
left = 2*node + 1;
right = 2*(node+1);
if ((tree[left] == null) && (tree[right] == null))
next = count;
else if (tree[left] == null)
next = right;
else if (tree[right] == null)
next = left;
else if (((Comparable)tree[left]).compareTo(tree[right]) < 0)
next = left;
else
next = right;
}
}
public T findMin() {
if (isEmpty())
throw new EmptyCollectionException ("Empty Heap");
return tree[0];
}
}
Here is more HeapSort algorithm:
import ArrayHeap;
public class HeapSort<T>{
public T[] heapsort(T[] data, int min, int max){
ArrayHeap<T> temp = new ArrayHeap<T>();
for (int c = min; c <= max; c++){
temp.addElement(data[c]);
}
int count = min;
while(!(temp.isEmpty())){
T jj = temp.removeMin();
data[count] = jj;
count ++;
}
return data;
}
The most straight-forward way to perform heapsort is to use a separate heap and add all the elements to it, then the elements will be in order when we pop them out one by one. This is what "adding the elements one at a time" refers to in the statement, and this is what your implementation is doing: create a heap of type ArrayHeap and insert the elements of data to it, in the end pop the elements back to data.
A more efficient way (in terms of both space and time) is to perform in-place sorting, where we use the array to be sorted as the heap, rather than using additional memory for the heap, this is what "order the entire list at once" refers to. The steps of this implementation is as follow, we will order the elements in non-decreasing order:
We max-heapify the input array (i.e. we re-arrange the elements in the array so that it follows the max-heap property.
For i = n - 1 to 1:
Swap the 0-th element in the array with the i-th element.
Decrease the size of the heap by 1 (i.e. the heap should be of size i).
Perform the sift-down operation on the heap to restore the max-heap property.
Note that whenever the max-heap property holds, the top-most element in the heap is the largest element, so at the start of the k-th iteration (k = n - i here) the 0-th element is the k-largest element, and we place is in the correct position in the array by swapping.
Note that step 1 can be done in O(n), and in step 2 there are O(n) iterations and each sift-down operation takes time O(log(n)), so the overall time complexity is O(n log(n)).
Below is an implementation in Java for your reference:
import java.util.Random;
public class HeapSort {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
System.out.println(String.format("Iteration number %d%n", i));
Integer[] array = randomIntArray(10, 0, 100);
System.out.println(String.format("Array before sorting: [%s]", toStr(array)));
heapSort(array);
System.out.println(String.format("Array after sorting: [%s]", toStr(array)));
System.out.println("================================================================");
}
}
private static <T extends Comparable<T>> T[] heapSort(T[] array) {
maxHeapify(array, array.length);
for (int i = array.length - 1; i > 0; i--) {
swap(array, 0, i);
siftDown(array, i, 0);
}
return array;
}
private static <T extends Comparable<T>> void maxHeapify(T[] array, int heapSize) {
for (int i = getParentIdx(heapSize - 1); i >= 0; i--) {
siftDown(array, heapSize, i);
}
}
private static <T extends Comparable<T>> void siftDown(T[] array, int heapSize, int idx) {
final int length = Math.min(array.length, heapSize) - 1;
if (idx > length || idx < 0) throw new IllegalArgumentException("Index out of range");
while (true) {
int maxIdx = idx;
int leftChildIdx = getLeftChildIdx(idx);
int rightChildIdx = getRightChildIdx(idx);
if (leftChildIdx <= length && array[maxIdx].compareTo(array[leftChildIdx]) < 0) maxIdx = leftChildIdx;
if (rightChildIdx <= length && array[maxIdx].compareTo(array[rightChildIdx]) < 0) maxIdx = rightChildIdx;
if (idx != maxIdx) {
swap(array, idx, maxIdx);
idx = maxIdx;
} else {
return;
}
}
}
private static int getParentIdx(int idx) {
return (idx - 1) / 2;
}
private static int getLeftChildIdx(int idx) {
return idx * 2 + 1;
}
private static int getRightChildIdx(int idx) {
return idx * 2 + 2;
}
private static <T> void swap(T[] array, int i, int j) {
T tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
private static <T> String toStr(T[] array) {
StringBuilder sb = new StringBuilder();
for (T element : array) {
sb.append(element + ", ");
}
return sb.substring(0, sb.length() - 2);
}
private static Integer[] randomIntArray(int size, int lowerBound, int upperBound) {
Integer[] result = new Integer[size];
Random random = new Random();
int diff = upperBound - lowerBound + 1;
for (int i = 0; i < size; i++) result[i] = lowerBound + random.nextInt(diff);
return result;
}
}

big difference in time between two Implementation of quick Sort

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

Given an array of integers, find out the third largest value in the array

public int thirdLargest(int[] arr){
int f_l = arr[0];
int s_l = arr[0];
int t_l = arr[0];
for(int i=1;i<arr.length;i++)
{
if (f_l < arr[i]){
t_l = s_l;
s_l = f_l;
f_l = arr[i];
}
else if (s_l < arr[i]){
t_l = s_l;
s_l = arr[i];
}
else if (t_l < arr[i]){
t_l = arr[i];
}
}
return t_l;
}
my code didn't passes some cases,any suggestion?
parameter {24,27,30,31,34,37,40,42}' , passes
parameter {2,-1,-2,-3,-4,-5}' , fails
This is simply cause by the fact that you initialize all values to arr[0]. If all elements are smaller than arr[0] this code won't update the values, even though the second-largest element for example wouldn't be arr[0]. Instead initialize the variables for the third/second/largest value with Integer.MIN_VALUE and start the search with the first element (index = 0) instead of the second.
There is actually a well-known algorithm for this, which is more generic than yours. It is called quick-select and looks like a quick sort with an optimization making it faster (linear time in average) : since we don't need to sort the array, we just recurse on the part of the array containing the index we are looking for (in your case, third item so index 2).
Here is an implementation in Java :
private static final Random rd = new Random();
public static int kthElement(int[] arr, int k) {
return kthElement(arr,k,0,arr.length);
}
private static T kthElement(int[] arr, int k, int min, int max) {
if (min < max - 1) {
int p = pivot(arr,min,max);
return p == k - 1 ? arr[p] :
p < k - 1 ? kthElement(arr,k,p + 1,max) : kthElement(arr,k,min,p);
}
return arr[min];
}
private static int pivot(int[] arr, int min, int max) {
int pivot = min + rd.nextInt(max - min);
swap(arr,pivot,max - 1);
pivot = min;
for (int i=min ; i<max ; i++)
if (arr[i] < arr[max - 1]) swap(arr,i,pivot++);
swap(arr,max - 1,pivot);
return pivot;
}
private static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
Well, as an alternative to your working code, here is a solution that will allow you to find the Nth largest integer in your array using Collections to do the heavy lifting:
import java.util.Arrays;
import java.util.Collections;
public class ArrayNthLargest {
public static int getNthLargest(int[] arrayInput, int n) {
Integer[] sortedArray = new Integer[arrayInput.length];
for (int i = 0; i < arrayInput.length; i++) {
sortedArray[i] = new Integer(arrayInput[i]);
}
Arrays.sort(sortedArray, Collections.reverseOrder());
return (sortedArray[n - 1]);
}
public static void main(String[] args){
int nth = new Integer(0);
int n = new Integer(3);
int[] testArray = {1,2,3,4,5,6,23,44,55,8,1};
nth = getNthLargest(testArray, n);
System.out.printf("The %d sorted array value is %d", n, nth);
}
}
This was actually an interesting question to me to do in O(n) complexity. I hope this solution is order n. I used an ArrayList as a stack (since Stack object won't allow addition of items in specific incidences (I've generalized it).
public int thirdLargest(int[] arr){
public int N_TH = 3; // Assuming this is nth largest you want
public ArrayList<Integer> largest = new ArrayList<Integer>(N_TH);
for(int i = 0;i<N_TH;i++)
largest.add(0); // initialize the ArrayList
for(int i = 0;i<arr.length;i++) {
for(int j=0;j<largest.size();j++){
if(arr[i] >= largest.get(j)) {
// Add the item at the correct index
// Pop the last element
largest.remove(largest.size()-1);
largest.add(j,arr[i]);
break;
}
}
}
return largest.get(N_TH);
}
Let me know if you find any problems with it, I might have mistyped part of trying to put it in OP's method.
EDIT won't work with negative numbers at the moment. You can find the smallest value in arr and initialize largest with that value. Then it'll also with negative numbers

Categories

Resources