Related
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;
}
I tried and wrote a code for Quicksort with middle element as pivot.
I was successful in writing one.
But Pivot has the property that:
Elements on its left are lesser than pivot and greater on its right.
I was not able to achieve this in my following code.
private static void QuickSortAlgorithm(int[] a, int i, int n)
{
if(i<n)
{
int part = partition(a,i,n);
QuickSortAlgorithm(a, i, part-1);
QuickSortAlgorithm(a, part, n);
}
}
private static int partition(int[] a, int i, int n)
{
int pivot = (i+n)/2;
int left = i;
int right = n;
while(left<=right)
{
while(a[left]<a[pivot]){
left++;
}
while(a[right]>a[pivot])
{
right--;
}
if(left<=right)
{
swap(a,left,right);
left++;
right--;
}
}
return left;
}
Main Method:
int a[]={5,7,3,9,1};
int n = a.length;
QuickSortAlgorithm(a,0,n-1);
System.out.println(Arrays.toString(a));
My doubt is:
I am sending left as my partitioned index.
But, when I am recursively calling QuickSortAlgorithm()
I am sending i to part-1 and part to n;
What should I send as partition index so that
I could call something like this: So that pivot property is satisfied?
QuickSortAlgorithm(a, i, part-1);
QuickSortAlgorithm(a, part+1, n);
Thank you:)
you have to send pivot value in first stack call inclusive and pivot+1 as lower index for second stack call.
You also have to put value of left as i+1 then your code will give an correct output
You have to change the return value to left+1 in partition method.
Try this program:
import java.io.*;
public class QuickSort {
public int partion(int[] a, int l, int h) {
int middle = (h+l)/2;
//System.out.println(middle);
int pivot = a[middle];
int i = l;
int j = h;
while (i <= j) {
while (a[i] < pivot) i++;
while (a[j] > pivot) j--;
if (i <= j) {
swap(a, i, j);
i++;
j--;
}
}
// swap(a,i,j);
System.out.println((i+j)/2);
return i-1;
}
public void quick(int[] a, int l, int h) {
if (l<h) {
int pi = partion(a, l, h);
System.out.println(pi);
if (l < pi - 1)
quick(a, l, pi+1);
if (pi < h)
quick(a, pi+1, h);
}
}
public void swap(int[] a, int l, int h){
int temp=a[l];
a[l]=a[h];
a[h]=temp;
}
public static void main(String[] args) {
int[] a = {10,80,30,90,40,50,70};
int l=0;
int h=a.length-1;
QuickSort q =new QuickSort();
q.quick(a,0,h);
System.out.println(" Sorted Array : ");
for(int e :a){
System.out.print(e+" , ");
}
}
}
You can choose the leftmost element in the array or you can choose any random element to be your pivot.
Check out the wikipedia page on quicksort for more details about choosing pivot
I am trying to modify a Quicksort program that used the first element as pivot to a Quicksort that uses the median of three (median of first, last and middle element) as pivot. My implementation thus far is however giving me ArrayIndexOutOfBoundsException(s) when testing it.
I guess I am missing something here, but I just can't figure out where I'm wrong. Any help and advice is highly appreciated.
public class Sorts {
private static void swap(int[] array, int index1, int index2) {
// Precondition: index1 and index2 are >= 0 and < SIZE.
//
// Swaps the integers at locations index1 and index2 of the values array.
int temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
private static int medianOfThree(int[] array, int first, int last) {
int mid = array[(first+last)/2];
if (array[first] > array[mid]) {
swap(array, first, mid);
}
if (array[first] > array[last]) {
swap(array, first, last);
}
if (array[mid] > array[last]) {
swap(array, mid, last);
}
swap(array, mid, last-1);
return array[last-1];
}
private static int partition(int[] array, int first, int last, int median) {
int pivot = array[last-1];
int saveF = last-1;
boolean onCorrectSide;
first++;
do {
onCorrectSide = true;
while (onCorrectSide) { // move first toward last
if (array[first] > pivot) {
onCorrectSide = false;
}
else {
first++;
onCorrectSide = (first <= last);
}
}
onCorrectSide = (first <= last);
while (onCorrectSide) { // move last toward first
if (array[last] <= pivot) {
onCorrectSide = false;
}
else {
last--;
onCorrectSide = (first <= last);
}
}
if (first < last) {
swap(array, first, last);
first++;
last--;
}
} while (first <= last);
swap(array, saveF, last);
return last;
}
private static void quickSort(int[] array, int first, int last) {
if (first < last) {
int pivot;
int median = medianOfThree(array, first, last);
pivot = partition(array, first, last, median);
// values[first]..values[splitPoint - 1] <= pivot
// values[splitPoint] = pivot
// values[splitPoint+1]..values[last] > pivot
quickSort(array, first, pivot - 1);
quickSort(array, pivot + 1, last);
}
}
public static void quickSort(int[] array) {
quickSort(array, 0, array.length-1);
}
}
you are not using the variable in the right way:
int mid = array[first+last/2];
gives you the value in mid of the array, but not the offset (index) of the array.
But you are using mid, as index variable in your calls of the methods:
swap(array, first, mid);
I need help figuring out what exactly is wrong with this partitioning code. I have been struggling with it for a few days now, cant seem to wrap my head around it.
The pIdx is the pivot index, left and right are the bounds integer options for the array, and the array a is just an array or stored long values.
protected static int partition(long[] a, int left, int right, int pIdx) {
//long numbers[] = {4,3,8,9,7,2,1,5};
long pivot = a[pIdx];
swap(a, pIdx, right);
int storeIndex = left;
for(int i=left; i<right; i++) {
if(a[i] <= pivot)
swap(a, i, storeIndex);
}//for
swap(a, right, storeIndex);
return storeIndex;
}//partitio
I tried fixing your code. See if this works for you.
protected static int partition(long[] a, int left, int right, int pIdx) {
//long numbers[] = {4,3,8,9,7,2,1,5};
long pivot = a[pIdx];
swap(a, pIdx, right);
int storeIndex = left;
for(int i=left; i<right; i++) {
if(a[i] < pivot) {
swap(a, i, storeIndex);
storeIndex = storeIndex + 1;
}
}
swap(a, storeIndex, right);
return storeIndex;
}
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;
}
}
}
}