[英]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.