我编写了一个基于quicksort原理对数组元素进行排序的程序。所以程序所做的是它接受一个数组,假设第一个元素作为数据,然后将它与数组的其余元素进行比较。如果元素发现更大,那么它将存储在另一个相同数组的最后(例如b),如果元素小于小于它将该元素放在数组b的开头。通过这种方式,枢轴将找到通向阵列中间的路径,其中左侧的元素较小,而右侧的元素大于枢轴。然后将数组b的元素复制到主数组,并通过递归调用整个函数。这是必需的代码。
package sorting;
import java.util.*;
public class AshishSort_Splitting {
private static Scanner dogra;
public static void main(String[] args)
{
dogra=new Scanner(System.in);
System.out.print("Enter the number of elements ");
int n=dogra.nextInt();
int[] a=new int[n];
for(int i=n-1;i>=0;i--)
{
a[i]=i;
}
int start=0;
int end=n-1;
ashishSort(a,start,end);
for(int i=0;i<n;i++)
{
System.out.print(+a[i]+"\n");
}
}
static void ashishSort(int[]a,int start,int end)
{
int p;
if(start<end)
{
p=ashishPartion(a,start,end);
ashishSort(a,start,p-1);
ashishSort(a,p+1,end);
}
}
public static int ashishPartion(int[] a,int start,int end)
{
int n=start+end+1;
int[] b=new int[n];
int j=start;
int k=end;
int equal=a[start];
for(int i=start+1;i<=end;i++)
{
if(a[i]<equal)
{
b[j]=a[i];
j++;
}
else if(a[i]>equal)
{
b[k]=a[i];
k--;
}
}
b[j]=equal;
for(int l=0;l<=end;l++)
{
a[l]=b[l];
}
return j;
}
}
当我输入n到13930的值时,此代码工作正常,但在此之后,它显示
Exception in thread "main" java.lang.StackOverflowError
at sorting.AshishSort_Splitting.ashishSort(AshishSort_Splitting.java:28)
at sorting.AshishSort_Splitting.ashishSort(AshishSort_Splitting.java:29)
我知道由于错误的递归导致的错误,但我多次测试我的代码并且没有找到更好的替代方案。请帮忙。提前谢谢。
编辑:有人可以建议一种方法来克服这个问题。答案 0 :(得分:0)
我首先看到了性能问题。我在你的分区方法中看到了:
int n = start+end+1
就在那里,如果在int [1000]上使用start = 900和end = 999调用该方法,那么你正在分配一个int [1900] ......不打算,我认为......!
如果您真的要丢弃内存而不是就地分区, 假设
int n = end-start+1
而不是更小的分配,j和k索引b [],它们将是j = 0和k = n,并返回start + j。
第二,你的
else if(a[i]<equal)
不是必需的并导致错误。一个简单的其他就足够了。如果您不替换b [j..k]中的0,则在重新填充[]时会遇到麻烦。
最后,你的最终副本是假的,从[0到end]超出了调用的范围[start..end],最重要的是,你的b中[b附近0]通常没有任何兴趣[]原样。 b []的区域(在您的版本中)是[start..end](在我建议的版本中它将是[0..n-1])
这是我的版本,但它仍然存在评论中提到的O(n)堆栈问题。
public static int ashishPartion(int[] a, int start, int end) {
int n = end-start + 1;
int[] b = new int[n];
int bj = 0;
int bk = n-1;
int pivot = a[start];
for (int i = start + 1; i <= end; i++) {
if (a[i] < pivot) {
b[bj++] = a[i];
} else {
b[bk--] = a[i];
}
}
b[bj] = pivot;
System.arraycopy(b, 0, a, start, n);
return start+bj;
}
如果您可以自由选择排序算法,那么mergesort在性能上会更均匀,具有logN堆栈深度。易于实施。
否则,你将不得不使用手动堆栈来解除你的算法,这是一个很好的功课,我不会为你做的...... LOL