I implement again quicksort algorithm by hand. Here is my code. Below code is run infinity:
public class QuickSort {
private static int partition(int[] arr, int low, int high) {
int pivot = (low + high) / 2;
int pivotValue = arr[pivot];
while (low <= high) {
while (arr[low] < pivotValue) {
low++;
}
while (arr[high] > pivotValue) {
high--;
}
if (low <= high) {
int tmp = arr[low];
arr[low] = arr[high];
arr[high] = tmp;
low++;
high--;
}
}
return low;
}
private static void print(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
public static void quicksort(int[] arr, int low, int high) {
if (low >= high) return;
int k = partition(arr, low, high);
quicksort(arr, low, k);
quicksort(arr, k+1, high);
}
public static void quicksort(int[] arr) {
quicksort(arr, 0, arr.length - 1);
}
public static void main(String[] args) {
// int[] arr = new int[]{9, 2, 3, 4, 1, 8, 7};
int[] arr = new int[]{1, 2, 5, 4, -1, -2, -3};
quicksort(arr);
print(arr);
}
}
The wrong thing is:
int k = partition(arr, low, high);
quicksort(arr, low, k);
quicksort(arr, k+1, high);
If I update again:
int k = partition(arr, low, high);
quicksort(arr, low, k-1);
quicksort(arr, k, high);
I don't understand this point. Why some implementation see this interchangeable. Means I can use both case. But the first makes me infinity loop.
Thanks
For sure debug can help but I guess problem is in case when
low == hight + 1 =>
pivot == low =>
return low == hight =>
next call quicksort(arr, low, k) will call again partition(arr, low, high);
Related
I've the following implementation for quicksort, but trying to transfer it to quickselect fails.
class Solution {
public static void main(String[] args) {
for (int i = 1; i < 5; i++) {
int[] arr = new int[]{9,8,7,1,2,3,6,5,4};
System.out.println(quicksort(arr, i));
}
}
private static int quicksort(int[] arr, int k) {
return quicksort(arr, 0, arr.length - 1, k);
}
private static int quicksort(int[] arr, int low, int high, int k) {
int p = partition(arr, low, high);
/* Doesnt work:
if (p == k) {
return arr[k];
} else if (p < k) {
return quicksort(arr, p+1, high, k);
} else {
return quicksort(arr, low, p-1, k);
}
*/
}
private static int partition(int[] arr, int low, int high) {
int i = low;
int j = high;
int pivot = arr[low + (high - low) / 2];
while (true) {
while (arr[i] < pivot) {
i++;
}
while (arr[j] > pivot) {
j--;
}
if (i < j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i++;
j--;
} else {
return j;
}
}
}
}
It feels like the information that everything from 0..p is smaller or equal to arr[p] and vice-versa does not help at all.
Example:
9,8,7,1,2,3,6,5,4, after partition: 2, 1, 7, 8, 9, 3, 6, 5, 4 with p = 1 (choosen pivot was 2). So I know the first and second lowest value is in 0..1 range. But it isn't sorted, so I cannot simply say if (p == k-1) return arr[p], because it isn't guaranteed that arr[p] is the max of that half, just that everything in that half is less than the choosen pivot.
Any idea how I can make it work?
I am trying to implement a merge sort function, and am receiving a StackOverflowError exception when trying to run it. I saw another question similar to mine, with the answer about changing how the midpoint is calculated. I tried to change the midpoint, but am still getting the same stackoverflow error.
Thanks for looking.
public static void mergeSort(int [] arr, int low, int high) {
if (low < high) {
int mid = (low + high)/2;
mergeSort(arr, low, mid + 1);
mergeSort(arr, mid, high);
merge(arr, low, mid, high);
}
}
public static void merge(int [] arr, int low, int mid, int high) {
int n1 = mid - low + 1;
int n2 = high - mid;
int [] leftArr = new int[n1];
int [] rightArr = new int[n2];
for (int i = 0; i < n1; i++) leftArr[i] = arr[low + i];
for (int j = 0; j < n2; j++) rightArr[j] = arr[mid + j + 1];
int i = 0;
int j = 0;
int k = 1;
while (i < n1 && j < n2) {
if (leftArr[i] < rightArr[j]) {
arr[k] = leftArr[i++];
}
else {
arr[k] = rightArr[j++];
}
k++;
}
while (i < n1) arr[k++] = leftArr[i++];
while (j < n2) arr[k++] = rightArr[j++];
}
You implemented your mergesort function wrong.it should look like this
if (low < high) {
int mid = (low + high)/2;
mergeSort(arr, low, mid -1);
mergeSort(arr, mid, high);
merge(arr, low, mid, high);
}
And in the merge function you have initialised
k=1;
but it should be
k=low;
because if you will initialise k=1 everytime then it will override the array elements.
I have written quick sort code as below. The sort takes middle number as pivot:
import java.util.Arrays;
public class QuickSort {
public static void main(String[] args) {
int[] numbers = {3, 6, 9, 1, 34};
int low = 0;
int high = numbers.length - 1;
quicksort(numbers, low, high);
}
static void quicksort(int[] arr, int low, int high) {
int i = low;
int j = high;
int middle = arr[(low + high) / 2];
while(i < j) {
while(arr[i] < middle ) {
i++;
}
while(arr[j] > middle) {
j--;
}
if( i <= j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
if(low < j) {
quicksort(arr, low, j);
}
if(i < high) {
quicksort(arr, i, high);
}
System.out.println(Arrays.toString(arr));
}
}
However, after running the code i am getting stackoverflow exception.
It says Exception in thread "main" java.lang.StackOverflowError
Exception in thread "main" java.lang.StackOverflowError
at QuickSort.quicksort(QuickSort.java:47)
at QuickSort.quicksort(QuickSort.java:47)
at QuickSort.quicksort(QuickSort.java:47)
at QuickSort.quicksort(QuickSort.java:47)
at QuickSort.quicksort(QuickSort.java:47)
at QuickSort.quicksort(QuickSort.java:47)
at QuickSort.quicksort(QuickSort.java:47)
Please help me find out what might be wrong in running the above code.
The value of i and j needs to be incremented and decremented respectively. Please see below the working code:
import java.util.Arrays;
public class QuickSort {
public static void main(String[] args) {
int[] numbers = {3, 9, 6, 1, 34};
int low = 0;
int high = numbers.length - 1;
quicksort(numbers, low, high);
}
static void quicksort(int[] arr, int low, int high) {
int i = low;
int j = high;
int middle = arr[(low + high) / 2];
while(i <= j) {
while(arr[i] < middle ) {
i++;
}
while(arr[j] > middle) {
j--;
}
if( i <= j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
if(low < j) {
quicksort(arr, low, j);
}
if(i < high) {
quicksort(arr, i, high);
}
System.out.println(Arrays.toString(arr));
}
}
Hope this helps!
You can look at this link for better understanding of quick sort,how its work.
public static void quickSort(int[] arr, int low, int high) {
if (arr == null || arr.length == 0)
return;
if (low >= high)
return;
int middle = low + (high - low) / 2;
int pivot = arr[middle];
int i = low, j = high;
while (i <= j) {
while (arr[i] < pivot) {
i++;
}
while (arr[j] > pivot) {
j--;
}
if (i <= j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
// recursively sort two sub parts
if (low < j)
quickSort(arr, low, j);
if (high > i)
quickSort(arr, i, high);
}
I'm trying to write a modified merge sorting as an excercise. But i am stuck in why my code doesn't work and i cannot se where is the problem?! any hint or help is appreciate. Thanks in advance.
Here is my code:
public class MergeSort {
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) {
int middle = (high + low) / 2;
mergeSort(list, low, middle);
mergeSort(list, middle + 1, 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 low1 = low;
int high1 = high;
int mid = (low + high) / 2;
int end_low = mid;
int start_high = mid + 1;
while ((low <= end_low) && (start_high <= high1)) {
if (list[low] < list[start_high]) {
low++;
} else {
int temp = list[high - low + 1];
for (int k = start_high - 1; k >= low; k--) {
list[k + 1] = list[k];
}
list[low] = temp;
low++;
end_low++;
start_high++;
}
}
return list;
}
public static void main(String[] args) {
int[] list = { 2, 3, 2, 5, 6, 1, -2, 3, 14, 12, -5 };
mergeSort(list);
for (int i = 0; i < list.length; i++)
System.out.print(list[i] + " ");
}
}
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.