Java QuickSort algorithm - java

I am trying to learn Quick Sort algorithm and this is my code so far:
import java.util.Arrays;
public class JavaFiddle {
static int[] myArray = new int[]{35, 12, 25, 1, 5, 33, 56};
public static void QuickSort(int[] array) {
QuickSort(array, 0, array.length - 1);
}
public static void QuickSort(int[] array, int left, int right) {
if (left < right) {
int pivot = left + ((right - left) / 2);
int index = partition(array, left, right, pivot);
QuickSort(array, left, index - 1);
QuickSort(array, index + 1, right);
}
}
public static int partition(int[] array, int left, int right, int pivot) {
while (left < right) {
while (array[left] < pivot) {
left++;
}
while (array[right] > pivot) {
right--;
}
if (left < right) {
swap(array, left, right);
left++;
right--;
}
}
return left;
}
public static void swap(int[] array, int left, int right) {
int temp = array[left];
array[left] = array[right];
array[right] = temp;
}
public static void main(String[] args) {
System.out.println(Arrays.toString(myArray));
QuickSort(myArray);
System.out.println(Arrays.toString(myArray));
}
}
However, this code gives me an incorrect result:
[35, 12, 25, 1, 5, 33, 56] - before sort
[1, 12, 25, 35, 5, 33, 56] - after sort
What do I have wrong here? I cannot find the flaw in the logic.

Multiple errors here,
You define pivot in main method, but quick sort algorithm will swap pivot from right element to the middle.
You edit left and right values in your while loop in a while loop, which result right and left to be smaller/taller than your pivot and skipping some swaps.
Here's the correct implementation without your while { while { ... } } and a correct pivot (from right to middle)
import java.util.Arrays;
public class Main
{
static int[] myArray = new int[] {35, 12, 25, 1, 5, 56, 33};
public static void QuickSort(int[] array) {
QuickSort(array, 0, array.length - 1);
}
public static void QuickSort(int[] array, int left, int right){
if(left < right) {
int index = partition(array, left, right);
QuickSort(array, left, index - 1);
QuickSort(array, index + 1, right);
}
}
public static int partition(int[] array, int left, int right){
int pivot = array[right];
int first = left - 1;
for (int j = left; j <= right - 1; j++) {
if(array[j] < pivot) {
first ++;
swap(array, first, j);
}
}
swap(array, first + 1, right);
return first + 1;
}
public static void swap(int[] array, int left, int right) {
int temp = array[left];
array[left] = array[right];
array[right] = temp;
}
public static void main(String[] args)
{
System.out.println(Arrays.toString(myArray));
QuickSort(myArray);
System.out.println(Arrays.toString(myArray));
}
}
Also you compare pivot which is an index with array[...] which is a value

Related

Quick sort partition tweak

but I am trying to figure out how I can make so I may choose which ever pivot point I wish, Say for example on this list of integers, 8, 7, 1, 9 , 11, 5 , 6, I wished to choose say key 6 as the pivot point in my code. Or if I wanted to choose 9 or whatever. How could I write this into my code? Any help is much appreciated.
package quicksort;
public class quicky {
private static void quicksort(int[] arr, int left, int right) {
int index = partition(arr, left, right);
if(left < index - 1)
quicksort(arr, left, index - 1);
if(index < right)
quicksort(arr, index, right);
}
private static int partition (int[] arr, int left, int right) {
int pivot = arr[(left + right) / 2];
while(left<= right) {
while(arr[left] < pivot) left++;
while(arr[right]> pivot) right--;
if(left<= right) {
int tmp = arr[left];
arr[left] =arr[right];
arr[right] = tmp;
left++;
right--;
}
}
return left;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] array = new int [] { 8, 7, 1, 9, 11, 5, 6};
quicksort(array, 0 , array.length-1);
for(int i = 0; i <array.length; i++)
System.out.print(array[i]+ " ");
}
}
}
Here in your code
private static int partition (int[] arr, int left, int right) {
/*
Here in below code only you need to make your changes and that needs to be through out the same as you are calling this from quicksort also you need to make use of the left and right for that, as everytime you will be passing that otherwise it will be static value.
like you can do
int pivot = arr[left] // for left most as pivot, if you want the last one then have arr[right] as pivot, right now you have mid element as pivot.
*/
int pivot = arr[(left + right) / 2];
while(left<= right) {
while(arr[left] < pivot) left++;
while(arr[right]> pivot) right--;
if(left<= right) {
int tmp = arr[left];
arr[left] =arr[right];
arr[right] = tmp;
left++;
right--;
}
}
return left;
}
Simple method:
Check if value exists in array.
If it does, swap value with value in default pivot index.
Proceed using same code/ lomuto partition.

Cannot call the sort method in my quicksort implementation

I'm trying to code the quick sort algorithm using java. My problem is, that i cannot call the sort method. This is my code:
public class quickSort
{
int partition(int a[], int left, int right)
{
int i= left, j= right, temp;
int pivot=a[j];
//System.out.println(pivot+"pivot");
while(i<=j)
{
while(a[i]<pivot)
i++;
while(a[j-1]>pivot)
j++;
if(i<j)
{
temp=a[i];
a[i]=a[j-1];
a[j-1]=temp;
System.out.println(a[i] +"i");
System.out.println(a[j-1] +"j");
i++;
j--;
}
}
System.out.println(i);
System.out.println(j);
return i;
}
int[] sort(int[] numbers, int left, int right)
{
int x = partition(numbers, left, right);
System.out.println(x +"Qi");
if(left < right)
sort(numbers, left, x-1);
sort(numbers, x+1, right);
return numbers;
}
public static void main(String[] args)
{
quickSort q= new quickSort();
int[] numbers = {2,6,4,9,7,0,1,3,5};
int left = 0, right=numbers.length-1;
q.sort(numbers, left, right);
}
}
problem:
sort(numbers, left, x-1);
sort(numbers, x+1, right);
this recursion is not getting executed
It also results in an out of bounds exception, when i try to code in the partition method.
This is a screenshot of the output I m using it just to display the output and show the IDE I used to execute :
https://drive.google.com/file/d/1j6lHuEONZkO_Dr3ZszoPKh4bNXZgkgbT/view?usp=sharing.
The current code produces in the partition-method either an endless loop or an ArrayIndexOutOfBoundsException depending on your choosen numbers-array. A possible fix is e.g.:
private int partition(int a[], int left, int right) {
int i = left, j = right, temp;
int pivot = a[j];
while (i <= j) {
if (a[i] > pivot) {
temp = a[i];
for (int k = i; k < right; k++) { // remove a[i] and move all elements...
a[k] = a[k + 1]; // ...following a[i] to the left
}
j--; // decrement pivot's index
a[right] = temp; // move a[i] to the right end
} else {
i++;
}
}
return j; // return pivot's modified index
}
Furthermore, in the sort-method you have to ensure for both recursive sort-calls that the left boundary is smaller than the right boundary, e.g.:
private int[] sort(int[] numbers, int left, int right) {
int x = partition(numbers, left, right);
if (left < right) { // left boundary smaller than right one
sort(numbers, left, x - 1);
sort(numbers, x + 1, right);
}
return numbers;
}

Data Structures

I am coding a program which is basically going to compute the number of inversions in the array. The requirement is to use a divide-and-conquer algorithm.
I have used merge sort but afterwards I am stuck. I need to create another method called count in order to count the inversions using recursion. Here I need your help...
Thank you in advance
import java.util.*;
public class inversions
{
public static void main(String[] args)
{
Integer[] a = {2, 6, 3, 5, 1};
mergeSort(a);
System.out.println(Arrays.toString(a));
}
public static void mergeSort(Comparable [ ] a)
{
Comparable[] tmp = new Comparable[a.length];
mergeSort(a, tmp, 0, a.length - 1);
}
private static void mergeSort(Comparable [ ] a, Comparable [ ] tmp, int left, int right)
{
if( left < right )
{
int center = (left + right) / 2;
mergeSort(a, tmp, left, center);
mergeSort(a, tmp, center + 1, right);
merge(a, tmp, left, center + 1, right);
}
}
private static void merge(Comparable[ ] a, Comparable[ ] tmp, int left, int right, int rightEnd )
{
int leftEnd = right - 1;
int k = left;
int num = rightEnd - left + 1;
while(left <= leftEnd && right <= rightEnd)
if(a[left].compareTo(a[right]) <= 0)
tmp[k++] = a[left++];
else
tmp[k++] = a[right++];
while(left <= leftEnd) // Copy rest of first half
tmp[k++] = a[left++];
while(right <= rightEnd) // Copy rest of right half
tmp[k++] = a[right++];
// Copy tmp back
for(int i = 0; i < num; i++, rightEnd--)
a[rightEnd] = tmp[rightEnd];
}
public int count(int[] A, int n){}
}
Added some changes in Your Code.
import java.util.*;
public class inversions
{
public static int countInversions = 0;
public static void main(String[] args)
{
Integer[] a = {2, 6, 3, 5, 1};
mergeSort(a);
System.out.println(Arrays.toString(a));
System.out.println(countInversions);
}
public static void mergeSort(Comparable [ ] a)
{
Comparable[] tmp = new Comparable[a.length];
mergeSort(a, tmp, 0, a.length - 1);
}
private static void mergeSort(Comparable [ ] a, Comparable [ ] tmp, int left, int right)
{
if( left < right )
{
int center = (left + right) / 2;
mergeSort(a, tmp, left, center);
mergeSort(a, tmp, center + 1, right);
merge(a, tmp, left, center + 1, right);
}
}
private static void merge(Comparable[ ] a, Comparable[ ] tmp, int left, int right, int rightEnd )
{
int leftEnd = right - 1;
int k = left;
int num = rightEnd - left + 1;
while(left <= leftEnd && right <= rightEnd)
if(a[left].compareTo(a[right]) <= 0)
tmp[k++] = a[left++];
else {
countInversions+=((leftEnd-left)+1); // Counts the inversions
tmp[k++] = a[right++];
}
while(left <= leftEnd) // Copy rest of first half
tmp[k++] = a[left++];
while(right <= rightEnd) // Copy rest of right half
tmp[k++] = a[right++];
// Copy tmp back
for(int i = 0; i < num; i++, rightEnd--)
a[rightEnd] = tmp[rightEnd];
}
}
In the above code, we are counting the inversions when two arrays are merging. For example 1st sub-array contains [1, 6] and 2nd sub-array has [2, 3]. So when these are merged together inversion count will be 2 i.e. [6>2] & [6>3]. When the condition comes that a[left] > a[right] it will count the number of elements remaining on the right sub-array because will be less than the a[left] and will add them to countInversions.

Quick sort Error java

public int partition(int[]a,int i,int j){
int x=a[i];
int c=i;
for (int d = c+1; d < j; d++) {
if (a[d]<=x) {
c=c+1;
exchange(a, c, d);
}
}
exchange(a, c, i);
return c;
}
public void exchange(int[]a,int c,int d){
int temp=a[c];
a[c]=a[d];
a[d]=temp;
}
public void sort(int[]a,int i,int j){
int index;
if(i<j){
index=partition(a, i, j);
sort(a, i, index-1);
sort(a,index+1, j);
}
}
**strong text**public static void main(String[] args) {
// TODO code application logic here
QUICKSORT abir=new QUICKSORT();
abir.PRINT(abir.a);
abir.sort(abir.a, 0,10);
abir.PRINT(abir.a);
}
Here is my QuickSort code.
If i enter [6 10 13 5 8 3 2 11]
it prints [2 5 3 6 8 11 10 13]
Can anyone explain whats wrong with my code???
THank you
Your code seems quite strange to me, where did you take that?
Anyway why don't you take a look at this page for an explanation of quick sort?
http://www.algolist.net/Algorithms/Sorting/Quicksort
int partition(int arr[], 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 sort(int arr[], int left, int right) {
int index = partition(arr, left, right);
if (left < index - 1)
sort(arr, left, index - 1);
if (index < right)
sort(arr, index, right);
}
static int[] a = {6, 10, 13, 5, 8, 3, 2, 11};
public static void main(String[] args) {
// TODO code application logic here
QUICKSORT abir=new QUICKSORT();
System.out.println(Arrays.toString(a));
abir.sort(a, 0, 7);
System.out.println(Arrays.toString(a));
}

Implementing Quicksort

i am trying to implement quicksort but i am not getting correct results. Here is my code:
public static void quickSort(Comparable[] a, int start, int stop) {
if (start < stop) {
int pivot = partition(a, start ,stop);
System.out.print("Pivot: "+a[pivot]+" Array: ");
printArray(a);
quickSort(a,start,pivot-1);
quickSort(a,pivot+1, stop);
}
}
public static int partition(Comparable[] a, int start, int stop) {
Comparable pivot = a[stop];
int i = start;
int j = stop-1;
while (i < j) {
while( (isLess(a[i], pivot)|| isEqual(a[i], pivot)))
i++;
while((isGreater(a[j], pivot)|| isEqual(a[j], pivot)))
j--;
if(i < j)
swap(a, i,j);
}
swap(a,i, stop);
return i;
}
For input: {51,17,82,10,97,6,23,45,6,73}, i am getting result: 6 6 10 17 23 45 51 73 97 82
For input: {12,9,4,99,120,1,3,10}, i am getting an index out of bounds error. Would appreciate some help in where i am going wrong.
Your two problems are unrelated.
The problem with {51,17,82,10,97,6,23,45,6,73} is — what happens when stop == start + 1? Then i == start == stop - 1 == j, so you never enter the while-loop, so you unconditionally swap(a, i, stop) — even if a[i] was already less than a[stop].
The problem with {12,9,4,99,120,1,3,10} is seemingly that you didn't read the stacktrace. ;-) Assuming you have a decent Java compiler and JVM, it should have given you the exact line-number and problematic index, so you would have seen that the problem is in this line:
while((isGreater(a[j], pivot)|| isEqual(a[j], pivot)))
once j gets to -1. (This will happen if pivot is the very least value in the range of interest.) You just need to add a check for that:
while(j > start && (isGreater(a[j], pivot)|| isEqual(a[j], pivot)))
(and, for that matter, for the corresponding case of i:
while(i < stop && (isLess(a[i], pivot)|| isEqual(a[i], pivot)))
)
. . . and you need to learn how to debug your code. :-)
I recommend you Algorithms: Design and Analysis, very good internet course from Stanford. After this course you will write such codes more easily. It is a bit enhanced version, pivot is chosen as a median of three. Note that you don't have to write your own printArray() function. In Java you can do it with System.out.println(Arrays.toString(numbers)). Also you can observe how to call quickSort() in more elegant way, with only one argument, using method overloading.
public class QuickSort
{
public static void main(String[] args)
{
int numbers[] =
{ 51, 17, 82, 10, 97, 6, 23, 45, 6, 73 };
quickSort(numbers);
System.out.println(Arrays.toString(numbers));
}
public static void quickSort(int[] array)
{
quickSort(array, 0, array.length - 1);
}
private static void quickSort(int[] array, int left, int right)
{
if (left >= right)
{
return;
}
int pivot = choosePivot(array, left, right);
pivot = partition(array, pivot, left, right);
quickSort(array, left, pivot - 1);
quickSort(array, pivot + 1, right);
}
private static int partition(int[] array, int pivot, int left, int right)
{
swap(array, pivot, left);
pivot = left;
int i = left + 1;
for (int j = left + 1; j <= right; j++)
{
if (array[j] < array[pivot])
{
swap(array, j, i);
i++;
}
}
swap(array, pivot, i - 1);
return i - 1;
}
private static void swap(int[] array, int j, int i)
{
int temp = array[j];
array[j] = array[i];
array[i] = temp;
}
private static int choosePivot(int[] array, int left, int right)
{
return medianOfThree(array, left, (left + right) / 2, right);
// return right;
}
private static int medianOfThree(int[] array, int aIndex, int bIndex, int cIndex)
{
int a = array[aIndex];
int b = array[bIndex];
int c = array[cIndex];
int largeIndex, smallIndex;
if (a > b)
{
largeIndex = aIndex;
smallIndex = bIndex;
}
else
{
largeIndex = bIndex;
smallIndex = aIndex;
}
if (c > array[largeIndex])
{
return largeIndex;
}
else
{
if (c < array[smallIndex])
{
return smallIndex;
}
else
{
return cIndex;
}
}
}
}

Categories