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;
}
Related
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;
}
}
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;
}
}
I am working on a non recursive merge sort for my CS class and it is not exactly working. I know it is being called since when I run the test program it changes the array, just not into the correct order. Can someone please help? Thanks!
private static void mergeSort(int[] a, int left, int right)
{
int midPoint = ((right + left) / 2);
int[] buffer = new int[19];
selectionSort(a, left, midPoint);
selectionSort(a, midPoint-1, right);
merge(a, buffer, 0, 9, 19);
}
private static void selectionSort(int[] a, int beginning, int end)
{
int [] temp = new int[end-1];
for(int y = 0; y < end - 1; y++)
{
temp[y] = a[y];
}
for (int i = 0; i < temp.length - 1; i++)
{
int minIndex = findMinimum(temp, i);
if (minIndex != i)
swap (temp, i, minIndex);
}
}
private static int findMinimum(int[] a, int first)
{
int minIndex = first;
for (int i = first + 1; i < a.length; i++)
{
if (a[i] < a[minIndex])
minIndex = i;
}
return minIndex;
}
private static void swap(int []a, int x, int y)
{
int temp = a[x];
a[x] = a[y];
a[y] = temp;
}
private static void merge(int[] a, int[] temp, int left, int mid, int right) {
if (mid >= a.length) return;
if (right > a.length) right = a.length;
int i = left, j = mid+1;
for (int k = left; k < right; k++) {
if (i == mid)
temp[k] = a[j++];
else if (j == right)
temp[k] = a[i++];
else if (a[j] < a[i])
temp[k] = a[j++];
else
temp[k] = a[i++];
}
for (int k = left; k < right; k++)
a[k] = temp[k];
}
There may be other bugs, but one that sticks out is that selectionSort doesn't actually do anything to the array. You pass in an array reference as the a parameter:
private static void selectionSort(int[] a, int beginning, int end)
Since this is a reference, if selectionSort did anything to assign to any elements of a, like
a[x] = y;
it would change the element of the caller's array, like you want. But there is no statement in selectionSort that changes anything in a. The code copies elements to temp, works with temp--but then throws all the work away.
So I implemented "find the kth smallest element in an array" using a modified quicksort algorithm. However, right now it is infinite looping. I'm not quite sure where the error is. Updated: The debugger says the error is on line 14: "return kthSmallestError(arr, start, j-1, k); According to print statements, the (start, j-1, k) values are (3, 3, 0)" Thanks for the help!
class kthSmallestElement {
public static void main(String[] args) {
int[] input = {3, 1, 5, 2, 6, 4, 7};
int result = kthSmallestElement(input, 0, input.length-1, 3);
System.out.println(result);
}
public static int kthSmallestElement(int[] arr, int start, int end, int k) {
int j = partition(arr, start, end);
if (j == k) return arr[j];
if (j < k) {
return kthSmallestElement(arr, j+1, end, k-j-1);
}
else {
return kthSmallestElement(arr, start, j-1, k);
}
}
public static int partition(int[] arr, int left, int right) {
int pivot = arr[left+(right-left)/2];
while (left <= right) {
while (arr[left] < pivot) {
left++;
}
while (arr[right] > pivot) {
right--;
}
if (left <= right) {
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
}
return left;
}
}
An obvious bug: left, right, j are absolute indices whie k is relative. All comparisons and arithmetics between j and k should be calibrated by start.
Please try this.
thanks,
--john
public static int kthSmallestElement(int[] arr, int start, int end, int k) {
//int j = partition(arr, start, end);
int j = partition2(arr, start, end);
if (j == k)
return arr[j];
if (j < k) {
// without -1 as original code.
return kthSmallestElement(arr, j + 1, end, k - j );
} else {
return kthSmallestElement(arr, start, j - 1, k);
}
}
public static int partition2(int[] arr, int lo, int hi) {
int left = lo;
int right = hi+1;
int p = arr[lo];
while (true) {
while (arr[++left] < p) {
if (left == hi)
break;
}
while (p < arr[--right]) {
if (right == lo) {
break;
}
}
if (left >= right) {
break;
}
exchange(arr, left, right);
}
exchange(arr, lo, right);
return right;
}
My code works properly (to my knowledge) up until my input array size (a.length) is around 62,000 at which time I consistently get a StackOverFlowError. I previously had used 2 recursive calls to quicksort (less than, and greater than the pivot q) and then I switched to tail recursion. As you can see, I'm selecting the pivot to be the value at the end of the array. I know this isn't the best way to choose a pivot, but I still shouldn't be seeing StackOverFlowErrors with an array size this small, right? What could be causing this? Thanks in advance! Here's my code:
public static void quicksort(int[] a, int p, int r)
{
int q;
while (p < r)
{
q = partition(a, p, r);
quicksort(a, p, q - 1);
p = q + 1;
}
}
public static int partition(int[] a, int p, int r)
{
int j = p - 1;
int x = a[r];
for (int i = p; i < r; i++)
{
if (a[i] <= x)
{
j++;
swap(a, i, j);
}
}
j++;
swap(a, j, r);
return j;
}
private static void swap(int[] a, int i, int j)
{
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
The worst-case input (sorted order) makes quicksort Θ(n^2). Partition always puts a single element on one side of the partition (Cormen et al.). By randomizing the sort (choosing a random pivot) no particular input elicits its worst-case behavior.
import java.util.Random;
public class Quicksort
{
private static Random rand = new Random();
public static void quicksort(int[] arr, int left, int right)
{
if (left < right)
{
int pivot = randomizedPartition(arr, left, right);
quicksort(arr, left, pivot);
quicksort(arr, pivot + 1, right);
}
}
private static int randomizedPartition(int[] arr, int left, int right)
{
int swapIndex = left + rand.nextInt(right - left) + 1;
swap(arr, left, swapIndex);
return partition(arr, left, right);
}
private static int partition(int[] arr, int left, int right)
{
int pivot = arr[left];
int i = left - 1;
int j = right + 1;
while (true)
{
do
j--;
while (arr[j] > pivot);
do
i++;
while (arr[i] < pivot);
if (i < j)
swap(arr, i, j);
else
return j;
}
}
private static void swap(int[] arr, int i, int j)
{
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
// Sort 100k elements that are in reversed sorted order
public static void main(String[] args)
{
int arr[] = new int[100000];
for (int i = 0; i < arr.length; i++)
arr[i] = arr.length - i;
System.out.println("First 20 elements");
System.out.print("Before sort: ");
for (int i = 0; i < 20; i++)
System.out.print(arr[i] + " ");
System.out.println();
quicksort(arr, 0, arr.length - 1);
System.out.print("After sort: ");
for (int i = 0; i < 20; i++)
System.out.print(arr[i] + " ");
System.out.println();
}
}
Given the right input, your implementation will recurse once for every single element of the array. 60,000 recursive calls could easily be enough to overflow the stack in Java in the default configuration.