【问题标题】:QuickSort java.lang.StackOverflowError快速排序 java.lang.StackOverflowError
【发布时间】:2015-03-25 03:02:03
【问题描述】:

我正在尝试计算快速排序算法在三种情况下的执行时间“中枢轴,第一个枢轴,随机枢轴”数组已经排序。

mid pivot 和 random 适用于任何大小,但如果大小大于 25000,第一个 pivot 情况会产生 stackoverflow。

代码如下:

static void q_sort( int left, int right)
{

int pivot;
int l_hold, r_hold;

  l_hold = left;
  r_hold = right;
  pivot = array[left];
  while (left < right)
  {
    while ((array[right] >= pivot) && (left < right))
      right--;
    if (left != right)
    {
      array[left] = array[right];
      left++;
    }
    while ((array[left] <= pivot) && (left < right))
      left++;
    if (left != right)
    {
      array[right] = array[left];
      right--;
    }
  }
  array[left] = pivot;
  pivot = left;
  left = l_hold;
  right = r_hold;
  if (left < pivot)
    q_sort(left,(int) pivot-1);
  if (right > pivot)
    q_sort( (int)pivot+1, right);
}

这是调用代码:

double startTime1 = System.currentTimeMillis();
q_sort(0,size -1);
double stopTime1 = System.currentTimeMillis();
double elapsedTime1 = stopTime1 - startTime1;      
System.out.println(elapsedTime1);

【问题讨论】:

  • 如果您不继续重用现有变量来表示不同的东西,您的代码会更容易理解 - 目前pivot 表示枢轴 value 一半的时间,以及其余时间的 index。非常混乱!
  • 既然已经发明了这个轮子,为什么还要编写自己的快速排序?
  • @JonSkeet 它不是我从这里复制的代码,我只是在为我的老师测试执行时间......所以有什么帮助吗?
  • 如果你不能改变代码,那么我们调试它就没有意义了。如果您准确地测量了执行时间,那么您就完成了。如果事情发生爆炸,这不是你的错。只需捕获异常、恢复并报告结果。

标签: java stack-overflow


【解决方案1】:

您没有说明数组是如何生成的,但我怀疑它已经排序了。

问题如下:如果对已排序的数组进行快速排序,则第一个枢轴会导致以下递归:0..24999, 1..24999, 2..24999, 3..24999, 4..24999占用大量堆栈空间并导致堆栈溢出。这是因为数组是 0..24999,pivot 是 0,那么第二个分区就会变成 1..24999。

您应该消除其中一个尾调用。要消除哪个尾调用取决于哪个分区更小。您希望递归处理尽可能少的数据。其中一个递归被简单地替换为循环。这个尾递归消除已经在Quicksort and tail recursive optimization进行了解释

无论如何,我建议使用现有的快速排序算法而不是自己编写代码,除非这是一个家庭作业问题。

【讨论】:

  • 是作业,但已经抄了……老师不在乎代码他只想要图表
  • 也许您应该报告该算法不适用于这些情况?更好的是,解释为什么它不起作用。阅读我编辑的答案并尝试理解它。
  • 哦,我应该提一下,使用已经排序的数组对排序算法进行基准测试会导致数据不正确。垃圾进垃圾出。因此,请不要在测试用例中使用已经排序的数组,除非老师或问题陈述明确指示这样做。
  • 感谢您的回答,显然,他命令我们使用排序数据来显示平衡(最佳)情况、不平衡(最差)情况和随机(平均)情况之间的差异。跨度>
  • 哦,那你做的正是你应该做的。只需报告它由于堆栈溢出而无法工作以及为什么它没有工作。
猜你喜欢
  • 2019-06-30
  • 1970-01-01
  • 2020-08-14
  • 2016-12-23
  • 1970-01-01
  • 1970-01-01
  • 2014-10-10
  • 1970-01-01
  • 2016-02-12
相关资源
最近更新 更多