简体   繁体   中英

Quicksort: Almost sorted, but not quite. What's wrong?

Here's the code. The output is a very nearly correctly sorted array, but there are several elements out of order. Anyone able to spot the error?

I'm pretty sure the swap and quicksort methods are correct, but I'm posting all the methods here just in case.

package quicksort;
import java.util.Random;
import java.util.Arrays;

public class QuickSort {

/**
 * @param args the command line arguments
 */

private static int[] u;

public static void main(String[] args) {

    u = makeArray(100);
    System.out.println(Arrays.toString(u));

    quicksort(0, u.length - 1);
    System.out.println(Arrays.toString(u));

}

public static int[] makeArray(int n) {

    int[] a = new int[n];
    int j;
    Random r = new Random();

    for (int i = 0; i < n; i++) {
        j = (r.nextInt(100) + 1);
        a[i] = j;
    }

    return a;
}

public static int partition(int left, int right, int pivot) {

    int p = pivot;    // pivot
    int lPt = left - 1;
    int rPt = right + 1;

    while (true) {

        while ((lPt < right) && (u[++lPt] < p));

        while ((rPt > left) && (u[--rPt] > p));

        if (lPt >= rPt) {
            break;
        } else {

            swap(lPt, rPt);
            System.out.println("Swapping " + lPt + " " + rPt);

        }


    }

    return lPt;
}

public static void swap (int a, int b) {        
    int temp = u[a];
    u[a] = u[b];
    u[b] = temp;
}

public static void quicksort(int l, int r) {

    if (r - l <= 0) {
        return;

    } else {

        int part = partition(l, r, u[l]);

        quicksort (l, part - 1);
        quicksort (part + 1, r);

    }
}

}

The problem is in the partition method. The pivot element is not being placed in its correct position at the end of your swaps. I've changed the method signature so that you pass in the position of the pivot element, rather than the value of the pivot, so in quicksort() you would now write:

int part = partition(l, r, l);

In the body of the pivot method, I swapped the pivot element to the end of the section (by swapping with right). So that we then ignore this element with our swaps, I took away the "+ 1" on the initialisation of rPT. I then added a statement after your while loop to move the pivot element into place. With those three changes, the method now looks like this:

public static int partition(int left, int right, int pivotPosition) {

    int p = u[pivotPosition];    // pivot

    // Move pivot to the end
    swap(pivotPosition, right);

    int lPt = left - 1;
    int rPt = right;

    while (true) {

        while ((lPt < right) && (u[++lPt] < p));

        while ((rPt > left) && (u[--rPt] > p));

        if (lPt >= rPt) {
            break;
        } else {

            swap(lPt, rPt);
            System.out.println("Swapping " + lPt + " " + rPt);
        }

    }

    // Put pivot in its place
    swap(lPt, right);

    return lPt;
}

With these changes, the code works for me.

You have to find a values in the left list which is larger than the pivot element and find a value in the right list which is smaller then the pivot element then we exchange the values.

package quicksort;
import java.util.Random;
import java.util.Arrays;

public class QuickSort {
    /**
     * @param args the command line arguments
     */
    private static int[] u;

    public static void main(String[] args) {

        u = makeArray(10);
        System.out.println(Arrays.toString(u));

        quicksort(0, u.length - 1);
        System.out.println(Arrays.toString(u));

    }

    public static int[] makeArray(int n) {
        int[] a = new int[n];
        int j;
        Random r = new Random();
        for (int i = 0; i < n; i++) {
            j = (r.nextInt(100) + 1);
            a[i] = j;
        }
        return a;
    }

    private static void quicksort(int low, int high) {
        int i = low, j = high;
        int pivot = u[low];
        while (i <= j) {
            while (u[i] < pivot) {
                i++;
            }
            while (u[j] > pivot) {
                j--;
            }
            if (i <= j) {
                exchange(i, j);
                i++;
                j--;
            }
        }
        if (low < j) {
            quicksort(low, j); // note here
        }
        if (i < high) {
            quicksort(i, high); // note here
        }
    }

    private static void exchange(int i, int j) {
        int temp = u[i];
        u[i] = u[j];
        u[j] = temp;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM