尝试使用Hoare分区方案实现快速排序,但我遇到了一个问题,即无论数组大小如何,更改pivot的索引都会导致溢出。代码:
public void quickSort(int[] l, int min, int max){
if (min < max){
int p = partition(l, min, max);
quickSort(l, min, p);
quickSort(l, p+1, max);
}
}
public int partition(int[] l, int min, int max){
int pivot = l[min];
int i = min - 1;
int j = max +1;
while(true){
do{
i++;
}while(l[i] < pivot);
do{
j--;
}while(l[j] > pivot);
if (i >= j) {
return j;
}
//Swap
int temp = l[i];
l[i] = l[j];
l[j] = temp;
}
}
这个实现选择低索引(这里名为min)作为轴心元素,这样做很好。但是,将pivot元素更改为任何其他索引都会导致StackOverflow错误,而与正在排序的数组的大小无关。(错误参考第3行,其中调用了partition())我最好在(min,max)范围内随机选择pivot元素。这是什么原因造成的?
编辑:使用的数组生成如下:
public static int[] generateRandomArray(int size, int lower, int upper){
int[] random = new int[size];
for (int i = 0; i < random.length; i++) {
int randInt = ThreadLocalRandom.current().nextInt(lower, upper+1);
random[i] = randInt;
}
return random;
}
在一个溢出案例中,我使用了以下方法:
genereateRandomArray(10, 0, 9);
对于一些具体的例子,运行上面的代码,但将pivot元素更改为l[max-1]或l[min 1],l[min 2]等,会导致StackOverflow。
我的问题的解决方案是,正如用户MBo指出的那样,将枢轴元素交换到数组的第一个索引,因为算法本身依赖于索引0上的枢轴。这是我忽略的。(int i=min-1;是正确的,但保持这种方式。)
使用pivot的中间值对我来说很有用。下面是一个完整的示例:
public static void quickSort(int[] l, int min, int max){
if (min < max){
int p = partition(l, min, max);
quickSort(l, min, p);
quickSort(l, p+1, max);
}
}
public static int partition(int[] l, int min, int max){
int pivot = l[(min+max)/2];
int i = min - 1;
int j = max + 1;
while(true){
do{
i++;
}while(l[i] < pivot);
do{
j--;
}while(l[j] > pivot);
if (i >= j) {
return j;
}
int temp = l[i];
l[i] = l[j];
l[j] = temp;
}
}
public static int[] generateRandomArray(int size, int lower, int upper){
int[] random = new int[size];
for (int i = 0; i < random.length; i++) {
int randInt = ThreadLocalRandom.current().nextInt(lower, upper+1);
random[i] = randInt;
}
return random;
}
public static void main(String[] args) {
int[] A = generateRandomArray(10, 0, 9);
long bgn, end;
bgn = System.currentTimeMillis();
quickSort(A, 0, A.length-1);
end = System.currentTimeMillis();
for(int i = 1; i < A.length; i++){
if(A[i-1] > A[i]){
System.out.println("failed");
break;
}
}
System.out.println("milliseconds " + (end-bgn));
}
我们可以看到,在第一步i
变为等于min
,枢轴元素与其自身的比较失败,增量不会发生更多:
int pivot = l[min];
int i = min - 1;
...
do{
i++;
}while(l[i] < pivot);
从比较中排除pivot元素(inti=min;
),并在最后将其与分区1(似乎是l[j]
)交换
我有一个执行快速排序的应用程序。在我开始给它一些更大的数字(我第一次得到它是10000000)之前,它工作得很好。我知道是由递归引起的,但我不明白为什么我的应用程序会因此而崩溃。如有任何建议,将不胜感激。这是我的密码:
我试图实现就地快速排序,最后一个元素作为我的支点。下面附上我的代码 出于某种原因,我的代码给了我一个IndexOutOfBounds异常,它不能准确地对数组排序。我不知道为什么会出现这个错误。 如果我理解正确,我们应该把最后一个元素作为我们的轴心。然后,我们将左指针向右迭代,直到找到一个大于枢轴的元素。之后,我们从右侧(继续向左移动)执行相同的操作,直到找到一个小于轴的元素。然后我们交换这些元素,
问题内容: 这有效:http : //play.golang.org/p/-Kv3xAguDR。 这导致堆栈溢出:http : //play.golang.org/p/1-AsHFj51O。 我不明白为什么。在这种情况下,使用接口的正确方法是什么? 问题答案: 这个 将呼叫您的,依次呼叫,等等。如果您需要解组JSON然后对其进行处理,那么一种巧妙的技术是声明一个本地类型,将数据解组到其中,然后转换
问题内容: 我目前正在用Java编写一种快速排序算法,以对整数的随机数组进行排序,然后使用System.nanoTime()对它们进行计时。这些数组的大小是10的幂,从10 ^ 3到10 ^ 7结束。此外,随机列表具有不同的属性。我正在对纯随机列表进行排序,具有一些相同值的列表(fewUnique),反向排序的列表,已排序的列表和几乎已排序的列表。 排序有效。它对数组进行递归快速排序,直到需要对数
我正在使用一个正则表达式从任意长的输入字符串中提取键值对,并且遇到了这样的情况:对于具有重复模式的长字符串,它会导致堆栈溢出。 KV解析代码如下所示: 一些虚构的输出示例: 我显式地将generic放在上面,而不是在解析之前检查最大字符串长度的hacks(例如)。 我能想出的最粗俗的解决方法,一个真正的反模式,是 有趣的是,它在我试过的几次运行中都起作用了,但它不是一个值得推荐的有品位的东西。:-
因为最坏情况下的快速排序复杂度为O(n^2) 在递增顺序的情况下,当pivot选择第一个或最后一个元素时,它给出了正确的最坏情况复杂度O(n^2),因为树的一个子元素总是空的 但是当枢轴选择中间时,我感到困惑?它将树分成两半,使其复杂性O(n.logn) 假设10 20 30 40 50 60 70枢轴=40 (10 20 30 ) 40 (50 60 70) 左侧枢轴20,右侧枢轴60 (10)