Java 具有 20,000 个或更多整数的快速排序堆栈溢出
Java QuickSort Stack Overflow with 20,000 or more integers
当我对包含 20,000 个或更多整数的数组进行 运行 快速排序时,出现以下错误。
线程异常 "main" java.lang.WhosebugError
在项目 1.Project1.quickSort(Project1.java:31)
我用 p=0 和 r=array.length-1
调用快速排序
public static int[] createArray(int size)
{
int []array = new int[size];
for(int i=0;i<size;i++)
{
array[i]= randomGenerator.nextInt(100000);
}
return array;
}
public static void quickSort(int p, int r)
{
if(p < r)
{
int q = partition(p, r);
quickSort(p,q - 1);
quickSort(q+1,r);
}
}
public static int partition(int p,int r)
{
int x = array[r];
int i = p-1;
for(int j=p;j<=r-1;j++)
{
if(array[j]<= x)
{
i++;
swap(i,j);
}
}
swap(i+1,r);
return i+1;
}
public static void swap(int i, int j)
{
int temp = array[i];
array[i]= array[j];
array[j]= temp;
}
public static void main(String[] args)
{
//Get all the required input data
System.out.print("Size to be tested: ");
sc = new Scanner(System.in);
int input = sc.nextInt();
float selectionAvg= 0,quickAvg= 0,countAvg=0, medianAvg=0;
//Run the Quick sort algorithm
array= startArray;
int low= 0;
int high = array.length-1;
startTime= System.currentTimeMillis();
quickSort(low, high);
endTime = System.currentTimeMillis();
time= endTime - startTime;
System.out.println("Quick Sort Time: " + time + " milliseconds");
//printArray();
quickAvg+= time;
}
您可以考虑将您的程序修改为可迭代的。这样做的基本思路是自己用一个栈来处理当前递归处理的工作。
阅读此 article 以进一步参考。
简单实施 QuickSort 的问题之一是递归深度在最坏情况下为 O(n)
。如果所有或几乎所有分区仅将 O(1)
元素分配给结果分区之一,就会发生这种情况。将触发的条件取决于枢轴的选择和数据。在您的特定情况下,如果数组元素都具有相同的值或者它们是排序的或反向排序的,那么看起来会发生这种情况。这种情况可能解释了您的堆栈溢出。
枢轴的选择对于快速排序非常重要,它可以高效地处理最广泛的输入。我建议将三分中位数或随机选择作为相当不错、相对简单的选择。这些中的任何一个都可以解决[反向]排序的情况,但需要进行额外的更改才能解决常量值的情况。
此外,您可以确定将递归深度限制为最多O(log n)
,方法是仅对每个分区的较小部分进行递归排序,而不是循环对较大的部分。这很难通过在递归调用的单独函数中执行的分区来实现,但它 会 相当好地解决常量值的情况。
当我对包含 20,000 个或更多整数的数组进行 运行 快速排序时,出现以下错误。
线程异常 "main" java.lang.WhosebugError 在项目 1.Project1.quickSort(Project1.java:31)
我用 p=0 和 r=array.length-1
调用快速排序public static int[] createArray(int size)
{
int []array = new int[size];
for(int i=0;i<size;i++)
{
array[i]= randomGenerator.nextInt(100000);
}
return array;
}
public static void quickSort(int p, int r)
{
if(p < r)
{
int q = partition(p, r);
quickSort(p,q - 1);
quickSort(q+1,r);
}
}
public static int partition(int p,int r)
{
int x = array[r];
int i = p-1;
for(int j=p;j<=r-1;j++)
{
if(array[j]<= x)
{
i++;
swap(i,j);
}
}
swap(i+1,r);
return i+1;
}
public static void swap(int i, int j)
{
int temp = array[i];
array[i]= array[j];
array[j]= temp;
}
public static void main(String[] args)
{
//Get all the required input data
System.out.print("Size to be tested: ");
sc = new Scanner(System.in);
int input = sc.nextInt();
float selectionAvg= 0,quickAvg= 0,countAvg=0, medianAvg=0;
//Run the Quick sort algorithm
array= startArray;
int low= 0;
int high = array.length-1;
startTime= System.currentTimeMillis();
quickSort(low, high);
endTime = System.currentTimeMillis();
time= endTime - startTime;
System.out.println("Quick Sort Time: " + time + " milliseconds");
//printArray();
quickAvg+= time;
}
您可以考虑将您的程序修改为可迭代的。这样做的基本思路是自己用一个栈来处理当前递归处理的工作。
阅读此 article 以进一步参考。
简单实施 QuickSort 的问题之一是递归深度在最坏情况下为 O(n)
。如果所有或几乎所有分区仅将 O(1)
元素分配给结果分区之一,就会发生这种情况。将触发的条件取决于枢轴的选择和数据。在您的特定情况下,如果数组元素都具有相同的值或者它们是排序的或反向排序的,那么看起来会发生这种情况。这种情况可能解释了您的堆栈溢出。
枢轴的选择对于快速排序非常重要,它可以高效地处理最广泛的输入。我建议将三分中位数或随机选择作为相当不错、相对简单的选择。这些中的任何一个都可以解决[反向]排序的情况,但需要进行额外的更改才能解决常量值的情况。
此外,您可以确定将递归深度限制为最多O(log n)
,方法是仅对每个分区的较小部分进行递归排序,而不是循环对较大的部分。这很难通过在递归调用的单独函数中执行的分区来实现,但它 会 相当好地解决常量值的情况。