【问题标题】:Quicksort issue in JavaJava中的快速排序问题
【发布时间】:2020-06-18 16:47:00
【问题描述】:

我正在尝试使用递归和几种辅助方法来实现快速排序。当我运行程序时,我收到一条越界消息,告诉我我已经转向数组的索引 -1。任何人都可以提供有关修复我的快速排序方法的建议吗? (这就是问题所在)。我知道我的其他方法是正确的。

示例 {7,6,5,4,3,2,1}

应该是{1,2,3,4,5,6,7}

public static <T extends Comparable<? super T>> void quickSort(T[] a) {
        quickSort(a,0,a.length - 1);
    }

    public static <T extends Comparable<? super T>> void quickSort(T[] a,int start,int end) { 
        if(start<end) {
            int pivotIndex = partition(a, start, end);
            quickSort(a,start,pivotIndex-1); // sort left partition
            quickSort(a,pivotIndex+1,end); // sort right partition
        }

    }

    public static <T extends Comparable<? super T>> int partition(T[] a, int start, int end) {
        int mid =midpoint(start,end);
        sortFirstMiddleLast(a,start,mid,end);


        swap(a,mid,end-1);
        int pivotIndex = end -1 ;
        T pivotValue = a[pivotIndex];

        int indexFromLeft = start +1 ;
        int indexFromRight = end -2;
        boolean done = false;
        while (!done) {
            while (a[indexFromLeft].compareTo(pivotValue)<0) {
                indexFromLeft++;
                }
            while (a[indexFromRight].compareTo(pivotValue)>0) {
                indexFromRight--;
            }
            if (indexFromLeft < indexFromRight) {
                swap(a,indexFromLeft,indexFromRight);
                indexFromLeft++;
                indexFromRight--;
            }
            else {
                done=true;
            }

        }
            swap(a,pivotIndex,indexFromLeft);
            pivotIndex=indexFromLeft;

        return pivotIndex;
    }

    public static <T extends Comparable<? super T>> void sortFirstMiddleLast(T[] a, int start, int mid, int end) {
        if (a[start].compareTo(a[mid])>0) {
            swap(a,start,mid);
        }
        else if (a[mid].compareTo(a[end])>0) {
            swap(a,mid,end);
        }
        else if (a[start].compareTo(a[end])>0) {
            swap(a,start,end);
        }
        else if(a[start].compareTo(a[mid])>0) {
            swap (a,start,mid);
        }

        }

    private static int midpoint(int first, int last) {
            return first + (last - first) / 2;
        }

private static void swap(Object[] a, int first, int second) {
        Object temp = a[first];
        a[first] = a[second];
        a[second] = temp;
    }

【问题讨论】:

  • 你还没有分享swap方法的代码。
  • 抱歉,刚刚发布了
  • 您需要对内部while 循环之一进行范围检查。查看任何经典实现。
  • @user207421 - 如果未从起始索引对中排除枢轴,则不需要范围检查。

标签: java quicksort


【解决方案1】:

代码是 Hoare 分区方案的一种变体。假设您不想向内部循环添加范围检查,那么枢轴元素需要在左右索引之间的范围内。两个内循环之后的if应该使用左索引

另一个问题是,对于典型的 Hoare 分区方案,pivot 或 elements = pivot 可以在任何地方结束,并且 partition 返回的索引可能不是枢轴。索引只是将数组拆分为元素 = 枢轴(同样,元素 == 枢轴或枢轴本身可以在任何地方结束)。这意味着调用代码不能从递归调用中排除返回的索引。同样对于典型的 Hoare 分区方案,最后一个元素不能用于枢轴,因为这会导致无限递归。 Wiki 文章有一个基于 Hoare 的预递增和预递减快速排序示例。

https://en.wikipedia.org/wiki/Quicksort#Hoare_partition_scheme

Hoare 分区方案的后递增和递减变体的示例 C 代码,分区逻辑合并到快速排序函数中。对于 Hoare 分区方案的这种特殊变体,任何元素,包括最后一个元素,都可以用作枢轴,但是选择第一个或最后一个元素作为枢轴会导致已排序或反向的最坏情况时间复杂度为 O(n^2)排序的数据,同时选择如下所示的中间元素会导致已排序或反向排序数据的最佳情况。

void QuickSort(int a[], int lo, int hi)
{
int i, j;
int p, t;
    if(lo >= hi)
        return;
    p = a[lo + (hi-lo)/2];
    i = lo;
    j = hi;
    while (i <= j){
        while (a[i] < p)i++;
        while (a[j] > p)j--;
            if (i > j)
                break;
            t = a[i];
            a[i] = a[j];
            a[j] = t;
            i++;
            j--;
    }
    QuickSort(a, lo, j);
    QuickSort(a, i, hi);
}

【讨论】:

    猜你喜欢
    • 2018-01-31
    • 2018-05-27
    • 2017-01-14
    • 1970-01-01
    • 1970-01-01
    • 2016-10-02
    • 2021-03-11
    • 2020-12-13
    • 1970-01-01
    相关资源
    最近更新 更多