快速选择实施不起作用

时间:2016-05-15 07:24:02

标签: java algorithm quicksort quickselect

我正在尝试编写代码来确定数组中的n个最小项。很遗憾我正在努力解决这个问题。根据我当时的大学教科书中的算法,这看起来是正确的。但是,显然我做错了,因为它给了我一个堆栈溢出异常。

我的方法是:

  1. 将枢轴设置为开始+(结束 - 开始)/ 2(而不是开始+结束/ 2以防止溢出)
  2. 使用此位置的整数作为我将所有内容与
  3. 进行比较的轴心
  4. 迭代并交换此枢轴周围的所有内容,以便对事物进行排序(相对于枢轴排序)
  5. 如果n == pivot,那么我认为我已经完成了
  6. 否则,如果我想要4个最小的元素,例如,枢轴是3,那么我需要在右侧看(如果我想要第2个最小的元素,则需要左侧)。
  7. -

    public static void main(String[] args) {
        int[] elements = {30, 50, 20, 10};
        quickSelect(elements, 3);
    }
    
    private static int quickSelect(int[] elements2, int k) {
        return quickSelect(elements2, k, 0, elements2.length - 1);
    }
    
    private static int quickSelect(int[] elements, int k, int start, int end) {
        int pivot = start + (end - start) / 2;
        int midpoint = elements[pivot];
        int i = start, j = end;
    
        while (i < j) {
            while (elements[i] < midpoint) {
                i++;
            }
    
            while (elements[j] > midpoint) {
                j--;
            }
    
            if (i <= j) {
                int temp = elements[i];
                elements[i] = elements[j];
                elements[j] = temp;
                i++;
                j--;
            }
        }
        // Guessing something's wrong here
        if (k == pivot) {
            System.out.println(elements[pivot]);
            return pivot;
        } else if (k < pivot) {
            return quickSelect(elements, k, start, pivot - 1);
        } else {
            return quickSelect(elements, k, pivot + 1, end);
        }
    }
    

    编辑:请至少费心评论为什么要打算回复一个有效的问题。

2 个答案:

答案 0 :(得分:1)

这不会解决问题,但您的代码存在一些问题:

  • 如果你不检查i&lt;结束并且j>从你的时间开始,在某些情况下你可能会遇到界限
  • 您选择枢轴位于子阵列的中间,但没有任何证据表明它在分区过程中不会改变位置。然后,检查k ==枢轴与旧的枢轴位置,这显然不起作用

希望这有点帮助。

答案 1 :(得分:0)

好吧所以我做的第一件事就是返工我的枢轴/分区点。 T. Claverie指出,缺点是我使用的枢轴在技术上并不是枢轴,因为在分区阶段元素的位置会发生变化。

我实际上将分区代码重写为自己的方法,如下所示。这略有不同。

我选择第一个元素(在开始时)作为枢轴,并在此前面创建一个“部分”,其项目小于此枢轴。然后,我将pivot的值与值&lt;部分中的最后一项交换。枢轴。我将最终索引作为数据点的返回点。

可以更多地清理它(创建单独的交换方法)。

private static int getPivot(int[] elements, int start, int end) {
    int pivot = start;
    int lessThan = start;

    for (int i = start; i <= end; i++) {
        int currentElement = elements[i];
        if (currentElement < elements[pivot]) {
            lessThan++;
            int tmp = elements[lessThan];
            elements[lessThan] = elements[i];
            elements[i] = tmp;
        }
    }
    int tmp = elements[lessThan];
    elements[lessThan] = elements[pivot];
    elements[pivot] = tmp;

    return lessThan;
}

以下是例如:

private static int quickSelect(int[] elements, int k, int start, int end) {

    int pivot = getPivot(elements, start, end);

    if (k == (pivot - start + 1)) {
        System.out.println(elements[pivot]);
        return pivot;
    } else if (k < (pivot - start + 1)) {
        return quickSelect(elements, k, start, pivot - 1);
    } else {
        return quickSelect(elements, k - (pivot - start + 1), pivot + 1, end);
    }
}