Java Quicksort - Stack Overflow

时间:2018-03-26 18:43:32

标签: java stack-overflow infinite-loop quicksort

我试图实现一种使用按如下方式计算的数据透视表的快速排序版本:

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);
  }

1 个答案:

答案 0 :(得分:1)

算法的第一步是:

  

从数组中选择一个名为pivot的元素。

此表达式不会这样做:

(list[start] + list[end] + list[size / 2]) / 3

它只计算3个数字的平均值,其中一个数字可以在正在排序的分区之外(参见start +)。
因此,给定此数组:{1,2,3,4,5,6,7}start = 4end = 6所选项目将为(5 + 7 + 2)/3 = 4.(6)7,此不是分区的一个元素{{ 1}}。
您应该做的是选择{5,6,7}范围内的数字作为数据透视的索引。

开始+

我相信你实际想到的支点(分区的第一个,最后一个和中间元素的平均值)是:

start...end

虽然这个表达式没有从分区中选择一个元素,但它会选择一个不大于/小于分区中所有值的值,它会起作用。

带有/ 3轴的工作解决方案:

(list[start] + list[end] + list[start + (size / 2)]) / 3.0