簡體   English   中英

QuickSort能夠堆棧溢出嗎?

[英]Is QuickSort able to stack overflow?

在我的代碼中,該方法將自行調用(遞歸)。 我們知道,深層的方法調用將導致堆棧溢出。 那么,當有大量數據時會發生堆棧溢出嗎?

我的QuickSort代碼:(排序類的內部類)

private static class QuickSortor extends Sortor {

    protected <E> void sort(E[] a, boolean isAsc) {
        quickSort(a, 0, a.length - 1, isAsc);
    }

    private <E> void quickSort(E[] a, int left, int right, boolean isAsc) {
        if (left >= right)
            return;
        int middle = left;
        Comparable<E> cmp = (Comparable<E>) a[left];
        for (int i = left + 1; i <= right; i++) {
            int result = cmp.compareTo(a[i]);
            if (!isAsc)
                result = -result;
            if (result >= 0)
                swap(a, ++middle, i);
        }
        swap(a, left, middle);
        quickSort(a, left, middle - 1, isAsc);
        quickSort(a, middle + 1, right, isAsc);
    }
}

遞歸的深度以及快速排序需要多長時間,取決於數據點的相對順序以及數量。 如果樞軸點總是最終成為數據的最大或最小成員,則在上面的代碼上遞歸的遞歸將與數據大小一樣深。

使用快速排序,即使遞歸深度仍然需要很長時間,您也可以確保遞歸深度很小。 http://en.wikipedia.org/wiki/Quicksort中對此進行了非常簡短的討論,如下所示:

為了確保最多使用O(log N)空間,請首先遞歸到數組的較小部分,然后使用tail調用遞歸到另一個數組。

非常簡短,這意味着您首先要重寫

f(...)
{
  ...
  f()
  f()
}

f()
{
  while (...)
  {
    ...
    f()
    ...
 }
}

(使用while循環將參數修改為f,以便第二個遞歸調用對應於while循環的第二遍)。

然后看一下如何將數組拆分為兩個遞歸調用,並確保第二個遞歸調用(變成while循環)用於數組的較大部分。 這意味着剩余的遞歸調用始終不超過數組的一半,這意味着您永遠不會比數組大小的對數基數更深。

編寫的算法始終選擇最左邊的元素作為樞軸。 如果在已經排序的數組上執行,這將表現出QuickSort的病理性O(n^2)行為,這會導致相當小的數組導致堆棧溢出。

您可以通過按序從0到15000之類的Integers數組進行排序來嘗試一下。 我得到一個StackOverflowError嘗試一下。 在15000個隨機Integer數組上執行它不會導致堆棧溢出。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM