【问题标题】:Randomized QuickSort IndexOutOfBounds exception [duplicate]随机快速排序 IndexOutOfBounds 异常 [重复]
【发布时间】:2021-10-26 15:26:13
【问题描述】:

这是我提出的 QuickSort Randomized,但它不断抛出 IndexOutOfBounds 异常。我可以帮忙吗?谢谢!

import java.util.Random;

public class QuickSort {

    void quickSort(int[] A, int start, int end) { // Initially: start = 0, end = n-1
        while (start < end) {
            int iOfPartition = randomisedPartition(A, start, end);
            if (iOfPartition - start < end - iOfPartition) {
                quickSort(A, start, iOfPartition - 1);
                start = iOfPartition + 1;
            } else {
                quickSort(A, iOfPartition + 1, end);
                end = iOfPartition - 1;
            }
        }
    }

    int randomisedPartition(int[] A, int start, int end) {
        Random rng = new Random();
        int randomNum = rng.nextInt(end + 1 - start) + start;
        swap(A, A[randomNum], A[start]);
        return hoarePartition(A, start, end);
    }

    int hoarePartition(int[] A, int start, int end) {
        int pivot = A[start];
        int i = start;
        int j = end;
        while (i < j) {
            while (A[i] <= pivot && i < end) i++;
            while (A[j] > pivot && j > start) j--;
            if (i < j) swap(A, A[i], A[j]); 
        }
        swap(A, A[start], A[j]);
        return j; 
    }

    void swap(int[] A, int i, int j) {
        int temp = A[i];
        A[i] = A[j];
        A[j] = temp;
    }
}

我不断收到 arrayindexoutofbounds 错误。

【问题讨论】:

  • 您能否分享异常的堆栈跟踪以及每个函数的作用的 cmets 会有所帮助
  • 我更喜欢给你一根鱼竿而不是一条鱼。我知道这是一种学习过程,因为通常你永远不会为已经实现多年(并且工作正常)的东西编写自己的代码。由于 qsort 本质上是递归的,因此您需要做的就是在您的 quickSort 方法开始时在某个地方(通过 system.out.println 或其他)调试或写入后续调用。您将立即看到小于零或大于数组长度的值,因为这就是此异常的全部内容。祝你好运!
  • 在hoarePartition() 中,i 应该从start+1 开始,而不是start - start 是枢轴槽。此外,如果i 和j 交叉(相遇),whiles 可以终止。
  • @500-InternalServerError 谢谢大家,但在这里我认为 i=start+1 没关系?因为我的 A[i]
  • @Roo:你是对的。 pivot 和 A[start] 之间的第一个比较是多余的,但没什么大不了的。

标签: java random quicksort indexoutofboundsexception arrayindexoutofboundsexception


【解决方案1】:

我赞同上面评论的观点,你应该学会使用调试器或打印语句来尝试拼凑正在发生的事情。

不过,我还是忍不住去调查。

在调用 swap 时查看您在此处执行的操作。您正在使用 A[randomNum]

获取位于 randomNum 位置的值
    swap(A, A[randomNum], A[start]); // incorrectly indexing here

但是在交换内部,您正在重复该过程,并在不一定存在的 A[A[randomNum]] 处获取值。

int temp = A[i]; // indexing here again

所以你的问题是你错误地索引了两次。您应该只在交换函数中使用 [],而不是在 randomisedPartition 函数中。 randomisedPartition 应该发送交换索引,而不是索引值。

我是怎么想出来的? 我尝试使用非常简单的数据进行通话

int data[] = {5,3,4};
new Example().quickSort(data, 0, 2);

并得到一个索引超出范围 5 错误。这就是你调试的方式。

【讨论】:

  • 是的,谢谢。这个错误是因为最初我将函数 swap 定义为 swap(int i, int j) 却没有意识到我需要 swap(int[]A, int i, int j) 来编辑数组本身。然后我在纠正它后方便地忽略了交换功能,因为我愚蠢地认为它是次要的。 facepalm 我是使用 IntelliJ 和一般编程的新手,但下次会学习如何正确调试,如果您有任何调试技巧,我将不胜感激,谢谢您的帮助! :)
  • 任何调试技巧?不要让我开始,我有一百万个。 :) 基本上,这一切都是从故障点开始并从那里进行回溯。最小化数据,例如像我一样从一个小数组开始。然后看异常。如果它在 Example.swap(Example.java:39) 处显示 IndexOutofBounds[5],则转到该行并打印所有变量以查看哪个是 5。然后您会想,好吧,我是怎么到这里的?谁派了5个去那里?您转到调用函数并在那里打印语句(如果使用调试器,则为断点)。快乐学习:)
猜你喜欢
  • 2013-01-29
  • 1970-01-01
  • 2013-11-22
  • 1970-01-01
  • 2017-09-08
  • 2015-12-11
  • 1970-01-01
  • 2021-03-15
  • 2021-03-29
相关资源
最近更新 更多