Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 快速排序:更改枢轴元素会导致堆栈溢出_Java_Algorithm_Stack Overflow_Quicksort - Fatal编程技术网

Java 快速排序:更改枢轴元素会导致堆栈溢出

Java 快速排序:更改枢轴元素会导致堆栈溢出,java,algorithm,stack-overflow,quicksort,Java,Algorithm,Stack Overflow,Quicksort,尝试使用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

尝试使用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;
    }

}
对于一些具体的例子,运行上面的代码,但将pivot元素更改为l[max-1]或l[min+1],l[min+2]等,会导致StackOverflow

我的问题的解决方案正如用户MBo指出的那样,将枢轴元素交换到数组的第一个索引,因为算法本身依赖于索引0上的枢轴。这是我忽略的。
(int i=min-1;但是是正确的,并且保持不变。)

我们可以看到,在第一步
i
变为等于
min
,枢轴元素与自身的比较失败,增量不会发生更多:

int pivot = l[min];
    int i = min - 1;
...
 do{
            i++;
        }while(l[i] < pivot);
int pivot=l[min];
int i=最小值-1;
...
做{
i++;
}而(l[i]

从比较中排除pivot元素(
int i=min;
),并在末尾将其与分区1(似乎
l[j]
)交换,使用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));
    }
publicstaticvoidquicksort(int[]l,int-min,int-max){
如果(最小值<最大值){
INTP=分区(l,最小值,最大值);
快速排序(l,min,p);
快速排序(l,p+1,最大值);
}
}
公共静态int分区(int[]l,int最小,int最大){
int pivot=l[(最小值+最大值)/2];
int i=最小值-1;
int j=最大值+1;
while(true){
做{
i++;
}而(l[i]pivot);
如果(i>=j){
返回j;
}
int temp=l[i];
l[i]=l[j];
l[j]=温度;
}
}
公共静态int[]generateRandomArray(int-size、int-lower、int-upper){
int[]随机=新的int[大小];
for(int i=0;iA[i]){
System.out.println(“失败”);
打破
}
}
System.out.println(“毫秒”+(结束bgn));
}

堆栈溢出只应发生在
pivot=l[max]
时。任何其他索引都应该可以。通常选择中间元素:
pivot=[(min+max)/2]
。除min之外的任何索引(或者至少是我测试过的每个索引,包括中间元素)都会导致错误发生。如下文所述,这将有助于显示实际的失败示例,以及调用参数和使用的数据。添加了一些详细信息和示例。我更新了答案以显示问题代码的工作示例,但使用中间元素作为轴心。I=min-1是正确的方法。看一看。根据建议的更改,while循环可能会前进到子数组的末尾,如果没有值,例如已经排序的数据,则会失败。初始do while循环依赖于轴或与轴相等的元素,以阻止循环通过子数组的末端。每次交换都会阻止下一组do while循环从子数组的末端运行。@rcgldr我必须同意您的意见。太匆忙了。@删除accept标记是值得的,因为您显示的代码是正确的。但是您必须向我们显示导致错误的代码。我更新了我的答案,以显示问题代码,使用中间元素作为pivot,没有问题。
int pivot = l[min];
    int i = min - 1;
...
 do{
            i++;
        }while(l[i] < 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));
    }