【问题标题】:Quick Sort Comparison Count快速排序比较计数
【发布时间】:2015-10-03 18:48:03
【问题描述】:

我正在尝试使用这些快速排序方法来确定发生了多少比较。我们得到了一个全局变量来进行计数,但是当我们提交它时我们无法使用全局变量。相反,我们需要递归地计算比较。现在我试图弄清楚如何做到这一点,我不是在寻找答案,我正在尝试采取正确的步骤来解决这个问题。我已经尝试了几个小时了,但没有运气。

static int qSortCompares = 0;  // GLOBAL var declaration

/**
 * The swap method swaps the contents of two elements in an int array.
 *
 * @param The array containing the two elements.
 * @param a The subscript of the first element.
 * @param b The subscript of the second element.
 */
private static void swap(int[] array, int a, int b) {
    int temp;

    temp = array[a];
    array[a] = array[b];
    array[b] = temp;
}

 public static void quickSort(int array[]) {
    qSortCompares = 0;
    int qSCount = 0;
    doQuickSort(array, 0, array.length - 1);

}

/**
 * The doQuickSort method uses the QuickSort algorithm to sort an int array.
 *
 * @param array The array to sort.
 * @param start The starting subscript of the list to sort
 * @param end The ending subscript of the list to sort
 */
private static int doQuickSort(int array[], int start, int end) {
    int pivotPoint;
    int qSTotal = 0;
    if (start < end) {

        // Get the pivot point.
        pivotPoint = partition(array, start, end);
        
        // Note - only one +/=
        // Sort the first sub list.
        doQuickSort(array, start, pivotPoint - 1);

        // Sort the second sub list.
        doQuickSort(array, pivotPoint + 1, end);

    }

    return qSTotal;
}

/**
 * The partition method selects a pivot value in an array and arranges the
 * array into two sub lists. All the values less than the pivot will be
 * stored in the left sub list and all the values greater than or equal to
 * the pivot will be stored in the right sub list.
 *
 * @param array The array to partition.
 * @param start The starting subscript of the area to partition.
 * @param end The ending subscript of the area to partition.
 * @return The subscript of the pivot value.
 */
private static int partition(int array[], int start, int end) {
    int pivotValue;    // To hold the pivot value
    int endOfLeftList; // Last element in the left sub list.
    int mid;           // To hold the mid-point subscript
    int qSCount = 0;

    // see http://www.cs.cmu.edu/~fp/courses/15122-s11/lectures/08-qsort.pdf
    // for discussion of middle point - This improves the almost sorted cases
    // of using quicksort
    // Find the subscript of the middle element.
    // This will be our pivot value.
    mid = (start + end) / 2;

    // Swap the middle element with the first element.
    // This moves the pivot value to the start of
    // the list.
    swap(array, start, mid);

    // Save the pivot value for comparisons.
    pivotValue = array[start];

    // For now, the end of the left sub list is
    // the first element.
    endOfLeftList = start;

    // Scan the entire list and move any values that
    // are less than the pivot value to the left
    // sub list.
    for (int scan = start + 1; scan <= end; scan++) {
        qSortCompares++;
        qSCount++;
        if (array[scan] < pivotValue) {
            endOfLeftList++;
            // System.out.println("Pivot=" + pivotValue + "=" + endOfLeftList + ":" + scan);
            swap(array, endOfLeftList, scan);
        }
    }

    // Move the pivot value to end of the
    // left sub list.
    swap(array, start, endOfLeftList);

    // Return the subscript of the pivot value.
    return endOfLeftList;
}

/**
 * Print an array to the Console
 *
 * @param A
 */
public static void printArray(int[] A) {
    for (int i = 0; i < A.length; i++) {
        System.out.printf("%5d ", A[i]);
    }
    System.out.println();
}

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    final int SIZE = 10;
    int[] A = new int[SIZE];

    // Create random array with elements in the range of 0 to SIZE - 1;
    System.out.printf("Lab#2 Sorting Algorithm Performance Analysis\n\n");

    for (int i = 0; i < SIZE; i++) {
        A[i] = (int) (Math.random() * SIZE);
    }

    System.out.printf("Unsorted Data = %s\n", Arrays.toString(A));

    int[] B;

    // Measure comparisons and time each of the 4 sorts
    B = Arrays.copyOf(A, A.length);  // Need to do this before each sort
    long startTime = System.nanoTime();
    quickSort(B);
    long timeRequired = (System.nanoTime() - startTime) / 1000;

    System.out.printf("Sorted Data = %s\n", Arrays.toString(B));
    System.out.printf("Number of compares for quicksort     = %8d time = %8d us Ratio = %6.1f compares/us\n", qSortCompares, timeRequired, qSortCompares / (double) timeRequired);

    // Add code for the other sorts here ...
}

说明给出了一些提示,但我还是迷路了:

快速排序方法目前使用全局变量计算比较次数。这不是一个好的编程技术。修改快速排序方法以通过传递参数来计算比较。这有点棘手,因为比较是在分区方法中完成的。您应该能够看到在调用 partition 方法之前可以确定比较的次数。您将需要从 Quicksort 方法返回此值并修改 quickSort 标头以将此值传递给每个递归调用。您需要递归地添加计数。

作为递归计数的替代方法,您可以保留代码原样并在不修改的情况下完成实验。

我一直在查看这个分配的方式,我在名为 qSCount 的分区方法中创建了一个变量,当它被调用时将计算进行了多少比较。但是我不能使用该变量,因为我没有返回它。而且我不确定在那种状态下我将如何使用递归。我的想法是在每次 qSCount 有一个值之后,我可以以某种方式将它存储在 qSTotal 下的 doQuickSort 方法中。但是又一次提示说我需要在快速排序中创建一个参数,所以我很困惑。

【问题讨论】:

  • 您需要移除全局变量并使用计数器作为方法的参数吗?
  • 这里最重要的提示是doQuickSort调用partition时,比较的次数取决于doQuickSort传递给partition方法的内容,所以doQuickSort可以计算出多少比较不会涉及partition - 仅基于它将发送的参数。
  • 是的,最终不应该需要全局变量。我应该只有一个存储计数的参数。至少我很确定说明书是这么说的。
  • 现在您似乎没有使用函数返回的值。这将是一个很好的第一步。
  • @RealSkeptic 我不能 100% 确定我明白你的意思。 doQuickSort 如何在不进行分区的情况下进行总计?

标签: java recursion quicksort


【解决方案1】:

为了使用递归方法(没有全局变量)计算某些东西,我们需要返回它。你有:

private static int doQuickSort(int array[], int start, int end)

这是正确的想法。但是由于比较实际上发生在

private static int partition(int array[], int start, int end)

您需要让分区返回进行了多少比较。

这给我们留下了两个选择:

  1. 我们可以创建或使用现有的 Pair 类,让此方法返回一对整数,而不仅仅是一个(枢轴)。
  2. 我们可以创建一个计数器类并传递一个计数器对象并在那里完成计数。这消除了返回另一个值的需要,因为该参数可用于增加计数。

【讨论】:

  • 指令中具体说“可以在调用分区方法之前确定比较的次数”。这意味着您根本不需要更改partition
猜你喜欢
  • 2014-12-25
  • 1970-01-01
  • 2021-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-22
  • 2015-07-08
  • 1970-01-01
相关资源
最近更新 更多