【问题标题】:In-Place Quicksort w/ Last Element Pivot?带有最后一个元素枢轴的就地快速排序?
【发布时间】:2017-01-21 08:43:39
【问题描述】:

我正在尝试实现就地快速排序,以最后​​一个元素作为我的支点。下面附上我的代码

public static void main(String[] args){
        int[] input = {3,2,4,6,10,1,9,7,5};
        quickSort(input, 0, input.length-1);
    }
    public static void swap(int[] array, int i, int j) {
        int tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }

    public static int partition(int arr[], int left, int right) {
        int pivot = arr[right];
        int high = right-1;

        while(left < high){
            while(arr[left] < pivot){
                left++;
            }
            while(arr[high] > pivot){
                high--;
            }
            swap(arr,left, high);
            left++;
            high--;
        }
        swap(arr, left, pivot);
        System.out.println(Arrays.toString(arr));
        return left;
    }

    public static void quickSort(int arr[], int left, int right) {
        int index = partition(arr, left, right);
        quickSort(arr, left, index - 1);
        quickSort(arr, index, right);
    }

由于某种原因,我的代码给了我一个 IndexOutOfBounds 异常,它没有准确地对数组进行排序。我不确定为什么会收到此错误。

如果我理解正确,我们应该将最后一个元素作为我们的支点。然后,我们向右迭代左指针,直到找到大于枢轴的元素。之后,我们从右侧做同样的事情(继续向左移动),直到找到一个小于枢轴的元素。然后我们交换这些元素并继续做同样的事情。

最后,当左/右指针相同时,我们将中心值与我们的枢轴交换。

这是正确的思考方式吗?如果是这样,我的代码有什么错误?任何帮助将不胜感激

【问题讨论】:

  • 一个 IndexOutOfBoundsException 是不言自明的;您正在使用的索引对于有问题的数组来说太大或太小(负)。此外,要求社区查找代码中的所有错误也是题外话。
  • @ChiefTwoPencils 这就是这个网站的目的。但是 OP 应该做更多的工作,比如发布确切的堆栈跟踪并尝试通过打印出中间结果来调试它。
  • @MarkoTopolnik,没错。所以,当你问“我的代码有什么错误”时,这是题外话。那是在请求这个站点不是的调试服务。
  • 接下来,我强​​烈建议您发布正在运行的特定测试用例以及遇到的特定边界错误。该信息使我们能够更轻松地重现错误,并且您遇到的特定边界错误通常可以作为调试指南(您对待负索引访问与大型正索引访问不同。)

标签: java algorithm sorting quicksort


【解决方案1】:

假设最终的数组元素是最小的元素,跟踪这段代码。调整高的循环将不断递减高,因为每个其他数组元素都大于枢轴,所以最终高会从数组的前面掉下来,导致你越界访问。

要解决此问题,请在该循环中添加另一个检查,以确保您没有高左交叉。然后,您可能需要在之后添加一些额外的逻辑来处理这种特殊情况。

【讨论】:

  • 额外的检查会降低性能,特别是对于几乎排序的输入(错误预测的分支不占主导地位),但选择枢轴似乎无法避免。通常首选从中间选择一个枢轴,因为我们保证 &gt;&lt; 检查将在数组中的某个点失败。
【解决方案2】:

一些错误:

  • left &lt; high 检查添加到您的内部循环。每次修改left或right时都应该检查它。

  • 检查arr[high] &gt;= pivot而不是arr[high] &gt; pivot

  • swap(arr, left, pivot); 错误。您应该使用位置而不是值与枢轴交换左。应该是swap(arr, left, right);

  • 您应该在快速排序方法中检查left &lt; right

修复这些错误后,您的代码应如下所示:

    public static void main(String[] args){
        int[] input = {3,2,4,6,10,1,9,7,5};
        quickSort(input, 0, input.length-1);
    }
    public static void swap(int[] array, int i, int j) {
        int tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }

    public static int partition(int arr[], int left, int right) {
        int pivot = arr[right];
        int high = right;

        while(left < high){
            while(left < high && arr[left] < pivot){
                left++;
            }
            while(left < high && arr[high] >= pivot){
                high--;
            }
            swap(arr,left, high);
        }
        swap(arr, left, right);
        System.out.println( Arrays.toString(arr));
        return left;
    }

    public static void quickSort(int arr[], int left, int right) {
        if( left < right)
        {
            int index = partition(arr, left, right);
            quickSort(arr, left, index - 1);
            quickSort(arr, index, right);
        }
    }

【讨论】:

  • 终于找到了我正在寻找的解决方案,我必须用这种方法说。感谢您节省时间。
猜你喜欢
  • 1970-01-01
  • 2011-08-31
  • 2011-01-19
  • 2021-11-28
  • 2019-11-23
  • 1970-01-01
  • 2010-09-14
  • 2014-10-25
  • 1970-01-01
相关资源
最近更新 更多