Java快速排序-堆栈溢出
我正在尝试实现一个版本的quick sort,它使用一个计算如下的pivot:Java快速排序-堆栈溢出,java,stack-overflow,infinite-loop,quicksort,Java,Stack Overflow,Infinite Loop,Quicksort,我正在尝试实现一个版本的quick sort,它使用一个计算如下的pivot: pivot=(a[start]+a[end]+a[size/2])/3 ATM它可以在大小为6或更小的数组上完美地工作,但是一旦对大小为7或更大的数组进行排序,程序就会进入无限循环。到目前为止,我对递归的理解还不牢固,所以我怀疑它正在崩溃。我知道它在检查索引4和6时会进入一个循环,然后只持续检查这些索引 编辑:添加了对quickSort()的调用,并修复了一些格式问题 public static void quick
pivot=(a[start]+a[end]+a[size/2])/3
ATM它可以在大小为6或更小的数组上完美地工作,但是一旦对大小为7或更大的数组进行排序,程序就会进入无限循环。到目前为止,我对递归的理解还不牢固,所以我怀疑它正在崩溃。我知道它在检查索引4和6时会进入一个循环,然后只持续检查这些索引
编辑:添加了对quickSort()的调用,并修复了一些格式问题
public static void quickSort(double[] list, int start, int end){
if (end - start > 1){
int pivot = split(list, start, end);
quickSort(list, start, pivot - 1);
quickSort(list, pivot + 1, end);
}
if ( (end - start) == 1){
if (list[start] > list[end]){
double temp = list[start];
list[start] = list[end];
list[end] = temp;
}
}
}
public static int split(double[] list, int start, int end){
// splitPoint = (a[begin] + a[end] + a[size/2]) / 3
int size = end - start + 1;
double pivotValue = (list[start] + list[end] + list[size/2]) / 3;
int leftPosition = start;
int rightPosition = end;
double temp = 0;
while (true){
// find a value to swap on the left side of pivot
while ( (leftPosition <= rightPosition) && (list[leftPosition] <= pivotValue) ){
leftPosition++;
}
// find a value to swap on the right side of pivot
while ( (rightPosition >= leftPosition) && (list[rightPosition] >= pivotValue) ){
rightPosition--;
}
// if positions pass each other
if (rightPosition < leftPosition){
break;
} else {
// swap values
temp = list[leftPosition];
list[leftPosition] = list[rightPosition];
list[rightPosition] = temp;
}
}
return rightPosition;
}
public static void main(String[] args){
double[] list = {7, 6, 5, 4, 3, 2, 1};
quickSort(list, 0, list.length-1);
}
publicstaticvoidquicksort(双[]列表,int开始,int结束){
如果(结束-开始>1){
int pivot=拆分(列表、开始、结束);
快速排序(列表、开始、透视-1);
快速排序(列表,透视+1,结束);
}
如果((结束-开始)==1){
如果(列表[开始]>列表[结束]){
双温=列表[开始];
列表[开始]=列表[结束];
列表[结束]=温度;
}
}
}
公共静态整型拆分(双[]列表,整型开始,整型结束){
//拆分点=(a[开始]+a[结束]+a[大小/2])/3
int size=end-start+1;
双数据透视值=(列表[开始]+列表[结束]+列表[大小/2])/3;
int leftPosition=开始;
int rightPosition=结束;
双温=0;
while(true){
//在轴的左侧查找要交换的值
while((leftPosition=pivotValue)){
右位--;
}
//如果位置相互传递
如果(右位置<左位置){
打破
}否则{
//交换值
临时=列表[左位置];
列表[左位置]=列表[右位置];
列表[右位置]=温度;
}
}
返回正确位置;
}
公共静态void main(字符串[]args){
双[]列表={7,6,5,4,3,2,1};
快速排序(list,0,list.length-1);
}
算法的第一步是:
从数组中拾取一个称为轴的元素
此表达式不会执行以下操作:
(list[start] + list[end] + list[size / 2]) / 3
它只计算3个数字的平均值,其中一个数字可能位于正在排序的分区之外(请参见start+)。因此,给定此数组:
{1,2,3,4,5,6,7}
,start=4
和end=6
拾取的项将是(5+7+2)/3=4.(6)7
,并且该不是分区{5,6,7}
的元素您应该做的是选择
start…end
范围内的一个数字作为轴的索引
开始+
我相信您实际考虑的轴心(分区的第一个、最后一个和中间元素的平均值)是:
虽然这个表达式不从分区中选取元素,但它将选取一个不大于/小于分区中所有值的值,并且它将工作
使用a/3枢轴的工作解决方案:
void快速排序(双[]列表,整数开始,整数结束){
int size=end-start+1;
//这是“经典”支点
//双数据透视值=列表[开始+(结束-开始)/2];
双数据透视值=(列表[开始]+列表[结束]+列表[开始+(大小/2)])/3.0;
int leftPosition=开始;
int rightPosition=结束;
while(左位置数据透视值){
右位--;
}
if(leftPosition)堆栈溢出情况最好通过在IDE中运行并启用“异常时中断”来解决——这样,您可以检查堆栈并查看算法出错的位置。由于它在相对较小的情况下中断,您可以在if(end-start>1)处设置断点{
然后等待其中一个值为负值。
(list[start] + list[end] + list[start + (size / 2)]) / 3.0
void quickSort(double[] list, int start, int end) {
int size = end - start + 1;
// this is the 'classic' pivot
// double pivotValue = list[start + (end - start) / 2];
double pivotValue = (list[start] + list[end] + list[start + (size / 2)]) / 3.0;
int leftPosition = start;
int rightPosition = end;
while (leftPosition <= rightPosition) {
while (list[leftPosition] < pivotValue) {
leftPosition++;
}
while (list[rightPosition] > pivotValue) {
rightPosition--;
}
if (leftPosition <= rightPosition) {
exchange(list, leftPosition, rightPosition);
leftPosition++;
rightPosition--;
}
}
if (start < rightPosition)
quickSort(list, start, rightPosition);
if (leftPosition < end)
quickSort(list, leftPosition, end);
}
void exchange(double[] list, int i, int j) {
double temp = list[i];
list[i] = list[j];
list[j] = temp;
}