Explanation on how inversions work with merge sort - java

my code currently works just fine, but my trouble is understand why it works. Why are certain parameters the way they need to be and why do certain have to to happen. I tried two other solutions and this seems to be the only working one.
public static int invCounter(int[] ranking)
{
int[] b = new int[ranking.length];
int[] aux = new int[ranking.length];
for (int i = 0; i < ranking.length; i++)
b[i] = ranking[i];
int inversions = mergeSortInv(ranking, b, aux, 0, ranking.length - 1);
return inversions;
}
private static int mergeInv(int[] a, int[] aux, int lo, int mid, int hi) {
int inversions = 0;
// copy to aux[]
for (int k = lo; k <= hi; k++) {
aux[k] = a[k];
}
// merge back to a[]
int i = lo, j = mid+1;
for (int k = lo; k <= hi; k++) {
if (i > mid) a[k] = aux[j++];
else if (j > hi) a[k] = aux[i++];
else if (aux[j] < aux[i]) { a[k] = aux[j++]; inversions += (mid - i + 1); }
else a[k] = aux[i++];
}
return inversions;
}
private static int mergeSortInv(int[] a, int[] b, int[] aux, int lo, int hi) {
int inversions = 0;
if (hi <= lo) return 0;
int mid = lo + (hi - lo) / 2;
inversions += mergeSortInv(a, b, aux, lo, mid);
inversions += mergeSortInv(a, b, aux, mid+1, hi);
inversions += mergeInv(b, aux, lo, mid, hi);
return inversions;
}
If someone could explain why this works and how it works that would be great.

Related

MergeSort with CutOFF slower than regular MergeSort - Java

So my goal is to time three different algorithms and show the difference in execution time in ms when they have the same input. The problem I get is that my implementation of Merge Sort with cutoff (to insertion sort) is slower then the regular one. Here are the different methods. I tried debugging and working on smaller input but I could't find the problem. The purpose of the CUTOFF variable - by changing the values I should observe speedup in execution time.
Insertion sort implementation:
public static void insertionSort(int inputArray[]) {
int j, temp;
//start the for loop for iterating the array elements in the array
for (int i = 1; i < inputArray.length; i++) {
//stores the value at index at i int temp
temp = inputArray[i];
//assign i-1 to j
j = i - 1;
//while loop iterates upto j>i-1 and inputArray[j]>temp are true
while ((j > -1) && (inputArray[j] > temp)) {
inputArray[j + 1] = inputArray[j];
j--;
}
//store temp values into particular index j+1
inputArray[j + 1] = temp;
}
}
For the merge sort implementation I use the same merge method for "CutOff" and "Regular". Here is the whole class:
public static class MergeSort {
private static final int CUTOFF = 0;
void merge(int inputArray[], int lo, int mid, int hi) {
// Creating temporary subarrays
int leftArray[] = new int[mid - lo + 1];
int rightArray[] = new int[hi - mid];
// Copying our subarrays into temporaries
for (int i = 0; i < leftArray.length; i++)
leftArray[i] = inputArray[lo + i];
for (int i = 0; i < rightArray.length; i++)
rightArray[i] = inputArray[mid + i + 1];
// Iterators containing current index of temp subarrays
int indexLeft = 0;
int indexRight = 0;
// Copying from leftArray and rightArray back into array
for (int i = lo; i < hi + 1; i++) {
// If there are still uncopied elements in R and L, copy minimum of the two
if (indexLeft < leftArray.length && indexRight < rightArray.length) {
if (leftArray[indexLeft] < rightArray[indexRight]) {
inputArray[i] = leftArray[indexLeft];
indexLeft++;
} else {
inputArray[i] = rightArray[indexRight];
indexRight++;
}
} else if (indexLeft < leftArray.length) {
// If all elements have been copied from rightArray, copy rest of leftArray
inputArray[i] = leftArray[indexLeft];
indexLeft++;
} else if (indexRight < rightArray.length) {
// If all elements have been copied from leftArray, copy rest of rightArray
inputArray[i] = rightArray[indexRight];
indexRight++;
}
}
}
void sortNoCutOff(int inputArray[], int lo, int hi) {
if (lo < hi) {
//Put the cut of here
int mid = lo + (hi - lo) / 2;
sortNoCutOff(inputArray, lo, mid);
sortNoCutOff(inputArray, mid + 1, hi);
merge(inputArray, lo, mid, hi);
}
}
void sortCutOff(int inputArray[], int lo, int hi) {
if (lo <= hi + CUTOFF -1) {
//Put the cut of here
insertionSort(inputArray);
} else{
int mid = (hi + lo) / 2;
sortCutOff(inputArray, lo, mid);
sortCutOff(inputArray, mid + 1, hi);
merge(inputArray, lo, mid, hi);
}
}
}

How to optimize quick sort without using Auxiliary array

This is a quick sort as you know and I want to optimize it in itself arrayList and don't want to use another array or using linkedList. Suppose that the half numbers of array was sorted in ascending order and others are in among them.I mean optimization is less swap in code that depends on where does choose a pivot or change the partition function.if you know how I should optimize it please help me.total of count variable is a number of swap if I write it true. Thanks!
public class Quick {
public static void main(String[] args) {
int[] a = {4,6,0,7,1,12,2,18,4,9,4,13,5,6};
sort(a,0,a.length - 1);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
}
static void sort(int[] a, int lo, int hi){
if(lo < hi){
int j = partiton(a ,lo ,hi);
sort(a, lo ,j - 1);
sort(a, j + 1, hi);
}
}
static int partiton(int[] a, int lo, int hi){
int i = lo; int j = hi + 1;
int v = a[lo];
int count = 0;
while(true){
while(a[++i] < v){
if (i == hi)
break;
}
while(v < a[--j]){
if (j == lo)
break;
}
if (i >= j){
break;
}
swap(a, i, j);
count = count + 1;
}
swap(a, lo, j);
count = count + 1;
System.out.println("swap : " + count);
return j;
}
static void swap(int[] a, int i, int j){
int temp = 0;
temp = a[j];
a[j] = a[i];
a[i] = temp;
}
}

How can I fix my code? Quick-sort fill with random numbers

I am writing a code using quicksort but can't seen to make it work.
I have declared my array to size 20 and filled it with random integers. Then I called my sort method to do the quicksorting. The show method just prints the output. Still my code doesn't work at all.
My entire code for quick-sorting:
public class JavaApplication3 {
public static void main(String[] args) {
QuickSort B = new QuickSort();
int[] snum = new int [20];
for(int index = 0; index < snum.length; index++ ){
snum[index]= (int) (Math.random ());
}
B.sort(snum);
B.show(snum);
}
}
class QuickSort{
public static void sort(int [] a ){
quicksort(a, 0, a.length -1);
}
private static void quicksort(int[] a, int lo, int hi){
if(hi <= lo) return;
int j = partition(a, lo, hi);
quicksort(a, lo, j-1);
quicksort(a, j+1, hi);
}
private static void exch(int [] a, int i, int j){
int t = a[i];
a[i] = a[j];
a[j] = t;
}
private static int partition(int[] a, int lo, int hi){
int i= lo;
int j = hi+1;
int pivot = a[lo];
while(i<=j){
while(a[i] < pivot){
i++;
}
while(a[j] > pivot){
j--;
}
if(i <= j){
exch(a, i, j);
i++;
j--;
}
}
if (lo < j)
quicksort(a, lo, j);
if (i < hi)
exch(a, i, j);
return j;
}
public static void show(int[]a){
for(int i=0; i<a.length;i++)
System.out.print(a[i] + " ");
System.out.println();
}
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:
20 at javaapplication3.QuickSort.partition(JavaApplication3.java:61)
at javaapplication3.QuickSort.quicksort(JavaApplication3.java:43) at
javaapplication3.QuickSort.sort(JavaApplication3.java:39) at
javaapplication3.JavaApplication3.main(JavaApplication3.java:29) Java
Result: 1
One problem is that Math.random produces fractional numbers less than one, and when you cast it to int, those numbers result in 0. So multiply math.random by 10.
Hope this helps.
int hoaresPartition(int *arr, int lo, int hi){
int pivot = arr[lo];
int i = lo - 1;
int j = hi + 1;
while (true){
do {
j = j -1;
}while (arr[j] > pivot);
do {
i = i+1;
}while (arr[i] < pivot);
if ( i < j){
int temp;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}else
return j;
}
}

Quicksort - stackoverflowerror

Apparently the sort method is causing a stackoverflowerror. Why?
public static void quickSort(int[] a, int low, int high) {
if (a.length > 1) {
int middle = a.length / 2;
int size = a.length - middle;
int pivot = a[middle];
sort(a, low, middle, high);
quickSort(a, low, middle);
quickSort(a, middle + 1, high);
}
}
public static void sort(int[] a, int low, int middle, int high) {
boolean b = true;
int i = low;
int j = high;
for (int x = 0; x < middle + 1; x++)
if (a[x] <= a[middle])
i++;
for (int x = middle + 1; x < high + 1; x++)
if (a[x] > a[middle])
j--;
if (i != middle && j != middle + 1) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
b = false;
}
if (b == false)
sort(a, low, middle, high);
return;
}
}
note here in sort function.
if (b == false) {
sort(a, low, middle, high);
}
this b always false. and you do no change in low, middle, hifg values. so sort function call recursive as it is. so no change at all, function call repeat and stackoverflow will occure.

Hoare Partition Correctness in java

I am working to implement a Hoare partition into a quicksort. I am trying to completely understand the hoare partition but the book doesnt explain everything. Mainly I am just wondering what the while TRUE part means? The excerpt from the book is below. If I were to put the while part in java what would I use and why?
Hoare-Partition(A,p,r)
x= A[p]
i = p-1
j=r+1
while true
repeat
j=j-1
until A [j] <= x
repeat
i = i +1
until A[i] >= x
if i < l
exchange A[i] with A[j]
else return j
try this code for the algo that you have above :
int HoarePartition (int a[],int p, int r)
{
int x=a[p],i=p-1,j=r+1;
while (true)
{
while (a[j] <= x) j--;
while (a[i] >= x) i++;
if (i < j) swap(a[i],a[j]);
else return j;
}
}
Here's a working translation:
public static void quicksort(int[] ar) {
if (ar == null) return;
quicksort(ar, 0, ar.length-1);
}
private static void quicksort(int[] ar, int lo, int hi) {
if (lo < hi) {
int splitPoint = partition(ar, lo, hi);
quicksort(ar, lo, splitPoint);
quicksort(ar, splitPoint+1, hi);
}
}
private static int partition(int[] ar, int lo, int hi) {
int pivot = ar[lo];
int i = lo-1, j = hi+1;
while(true) {
do { i++; } while(ar[i] < pivot);
do { j--; } while(ar[j] > pivot);
if (i < j) swap(ar, i, j);
else return j;
}
}
private static void swap(int[] ar, int i, int j) {
int tmp = ar[i];
ar[i] = ar[j];
ar[j] = tmp;
}

Categories