【问题标题】:JAVA quicksort ,what is the mistake in partition method? [closed]JAVA快速排序,分区方法有什么错误? [关闭]
【发布时间】:2012-12-01 00:44:29
【问题描述】:
/**
     * Sort an array in ascending order
     * @param arr array to sort
     */
    public static void quickSort(int[] arr){
        qs(arr, 0, arr.length);
    }

/**
     * Sort a region of an array in ascending order.
     * Elements outside the given region are unchanged.
     * requires: 0 <= start <= end <= arr.length
     * @param arr   array to sort
     * @param start start of region (inclusive)
     * @param end   end of region (exclusive)
     */
    private static void qs(int[] arr, int start, int end){
        if (end <= start+1){    //region of length 0 or 1
            return;
        }
        int x = arr[start];
        int p = partition(arr, start+1, end, x);
            //now swap arr[start] with arr[p-1]
        arr[start] = arr[p-1];
        arr[p-1] = x;
        qs(arr, start, p-1);
        qs(arr, p, end);



    }

    /**
     * Partition a region of an array.
     * Rearranges elements in region so that small ones
     *   all have smaller indexes than the big ones.
     * Elements outside the region are unchanged.
     * requires: 0 <= start <= end <= arr.length
     * @param arr   array to partition
     * @param start start of region (inclusive)
     * @param end   end of region (exclusive)
     * @param x     pivot - "small" and "big" are <x, >=x.
     * @return      start index (inclusive) of big elements
     *              in region after partition.
     */
    private static int partition(
        int[] arr, int start, int end, int x)
    {

        int l = start -1, r = end+1;
        while (true) {
            while (l < end && arr[++l] < x) ;

            while(r> l && arr[--r] >x);// find smaller item

                if(l >= r) // if pointers cross,
                    break; // partition done
                    else  {
                        int temp;
                temp = arr[l];
                arr[l] = arr[r];
                arr[r] = temp;
            }
        }
        return l;
        }


    public static void main(String[] args) {
        int[] a = {15,8,9,6,2,8,8,5,8,4,2};
        quickSort(a);
        for (int i = 0; i < a.length; i++){
            System.out.print(" "+a[i]);
        }
    }
}

partition 方法中的错误是什么?

【问题讨论】:

  • 抛出arrayindexoutofbounds异常
  • 在哪一行?堆栈跟踪说明了什么?

标签: java quicksort


【解决方案1】:

让我强调一些重要的事实:

 * @param end   end of region (exclusive)
                               ^^^^^^^^^

 * @param x     pivot - "small" and "big" are <x, >=x.
 * @return      start index (inclusive) of big elements
 *              in region after partition.
 */
private static int partition(
    int[] arr, int start, int end, int x)
{

    int l = start -1, r = end+1;
                      ^^^^^^^^^^

    while (true) {
        while (l < end && arr[++l] < x) ;
               ^^^^^^^^^^^^^^^^^^^^^^^

        while(r> l && arr[--r] >x);// find smaller item
                      ^^^^^^^^

当整个数组被分区时,end 就是arr.length。然后你设置end = arr.length + 1,并在循环增加较低的索引l之后,如果没有引发ArrayIndexOutOfBoundsException(尝试访问arr[end],如果枢轴是例如最大元素数组),您尝试在下一个循环中访问的第一个数组元素是arr[arr.length]。这引发了ArrayIndexOutOfBoundsException

因此,您一定会在partition 获得 AIOBE。

您可以设置r = end 并将循环控件更改为

while(++l < r && arr[l] < x)

while(r-- > l && arr[r] > x)

或者您也可以将更高的索引包含在内,然后从main 调用qs(arr, 0, arr.length -1)

【讨论】:

  • 我认为我需要使 r=end +1 并更改循环,因为我离开 r=end 最后一个索引将保持不变
  • 您希望r 在要分区的数组块之后开始一个。这意味着,要么end 是包容性的,你以r = end+1 开头,要么end 是排斥性的,rend 开头。你有选择。嗯,有更常规的变体,在循环体而不是循环控制中增加和减少。
  • start
  • 或者我可以离开 r=end;并将循环更改为 while(++l
猜你喜欢
  • 2018-10-24
  • 2010-12-06
  • 1970-01-01
  • 2017-10-26
  • 2021-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多