Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 快速排序算法未正确分配枢轴_Java_Sorting_Quicksort - Fatal编程技术网

Java 快速排序算法未正确分配枢轴

Java 快速排序算法未正确分配枢轴,java,sorting,quicksort,Java,Sorting,Quicksort,我观看了一个快速排序算法的奇妙可视化: 我觉得自己真正理解了快速排序背后的原则,并在一些在线指南的帮助下,着手创建自己的快速排序。 这就是我想到的: public void quickSort(int[] a, int left, int right) { int index = partition(a, left, right); if (left < index - 1) quickSort(a, left, index); if (index &

我观看了一个快速排序算法的奇妙可视化:

我觉得自己真正理解了快速排序背后的原则,并在一些在线指南的帮助下,着手创建自己的快速排序。
这就是我想到的:

public void quickSort(int[] a, int left, int right) {

    int index = partition(a, left, right);
    if (left < index - 1)
      quickSort(a, left, index);
    if (index < right)
      quickSort(a, index + 1, right);
}

private int partition (int[] a, int left, int right) {
    int i = left - 1;
    int j = right + 1;
    int pivot = a[0];

    while (i < j) {

        i++;

        while (a[i] < pivot)
            i++;

        j--;

        while (a[j] > pivot)
            j--;

        if (i < j)
            swap (a, i, j);
    }
return i;
}   

private void swap (int[] a, int i, int j) {
    int temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}
不幸的是,输出不正确。问题似乎在于我对枢轴的处理。在我观看的可视化过程中,讲师实际移除了枢轴,让指针指向任何东西。他继续进行教程,当他到达i和j(我称之为左和右)都指向同一个空白点时,他插入枢轴并继续进行

由于我在物理上保持枢轴在适当的位置,我发现很难对其进行正确排序

在这段代码中,我使用的是输入:

4 8 1 6 3 7 2 5
我得到输出:

1 3 2 6 8 7 4 5
一旦在算法开始时对“4”值(即枢轴)进行排序,我就再也不会使用它,这会使一切都变得混乱。此外,我认为快速排序方法有问题

有人能给我一些建议吗?谢谢


编辑:此处的两个编辑已被删除,因为它们包含不必要和不正确的信息。其中一个将轴更改为:(左+右)/2。这当然是错误的,原因如下所述。

我认为
分区
方法应该返回
j
,而不是
I

代码中的另一个问题是停止条件:

我将其更改为单个条件,而不是两个单独的条件:

if (left < right)  {

  do partition & recursive calls

}
if(左<右){
执行分区和递归调用
}
完整代码:

public void quickSort(int[] a, int left, int right) {
    if (left < right) {
      int index = partition(a, left, right);
      quickSort(a, left, index);
      quickSort(a, index + 1, right);
    }
}

private int partition (int[] a, int left, int right) {
    int i = left - 1;
    int j = right + 1;
    int pivot = a[(left+right)/2];

    while (i < j) {

        i++;

        while (a[i] < pivot)
            i++;

        j--;

        while (a[j] > pivot)
            j--;

        if (i < j)
            swap (a, i, j);
    }
    return j;
}   

private void swap (int[] a, int i, int j) {
    int temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}
public void快速排序(int[]a,int left,int right){
if(左<右){
int index=分区(a,左,右);
快速排序(a,左,索引);
快速排序(a,索引+1,右);
}
}
私有int分区(int[]a,int左,int右){
int i=左-1;
int j=右+1;
int pivot=a[(左+右)/2];
而(ipivot)
j--;
if(i
我必须去掉分区,因为您需要
I
j
。应该是这样的:

public void quickSort(int[] a, int left, int right) {

    int i = left; // Was -1 
    int j = right; // Was +1
    int pivot = a[left + (right - left) / 2]; // Pivot is the value of the middle index, not the index itself
    while (i <= j) { // Changed terminating condition
        //   i++;  Not needed
        while (a[i] < pivot) { 
            i++;
        }
        //    j++; Not needed
        while (a[j] > pivot) {
            j--;
        }
        if (i <= j) {  // Changed terminating condition
            swap(a, i, j);
            i++;  // You need to progress the indexes after the swap
            j--;
        }
    }

    System.out.println(Arrays.toString(a));
    if (left < j) {  // Changed condition
        quickSort(a, left, j);
    }
    if (i < right) { 
        quickSort(a, i, right); // was i + 1
    }
}

很明显,你已经得到了公认的答案。但是,我要提到的是,分区逻辑可以更容易地实现,只有一个for(或while)循环,没有嵌套循环:

int partition(final int[] a, final int left, final int right) {
        // set the last element as pivot
        final int pivot = a[right];
        int i = left - 1, j = left;
        for (; j < right; j++) 
            if (a[j] < pivot) {
                i++;
                swap(a, i, j);
            }       
        // swap a[i+1] and pivot
        swap(a, i + 1, right);
        return i + 1;
    }
int分区(final int[]a,final int left,final int right){
//将最后一个元素设置为轴
最终整数轴=a[右];
int i=左-1,j=左;
对于(;j
在您的快速排序方法中:

if (left < index)
  quickSort(a, left, index-1);
if (index < right)
  quickSort(a, index + 1, right);
if(左<索引)
快速排序(a,左,索引-1);
如果(索引<右)
快速排序(a,索引+1,右);
希望能有帮助

int pivot = a[0];
应该是

int pivot = a[left];
通过改变
swap(a,i,j)
交换(a,i--,j++)

上述变化的原因:

轴应该是范围中的第一个元素,而不是第一个元素

也不应该在中间,就像这里:

int pivot = a[(left + right) / 2];
无论您希望轴心是哪个元素,最简单的方法是始终将所选元素与第一个元素交换,然后继续正常操作。也许还有其他的方法,但这些方法可能更复杂

所以你可以说:

swap(left, (left + right) / 2);
int pivot = a[left];

这与上面的非常相似(不完全相同),只是更容易处理。

因为太本地化而关闭。@djechlin:我认为它针对的是一个特定的编程算法,如常见问题解答所示。如果我错了,你能推荐哪个堆栈交换来询问这个问题吗?@djechlin他在问一个显示代码的编码问题。这怎么可能太本地化了???@djechlin:我想指出的是,在常见问题解答中,它说:“你应该根据你所面临的实际问题,只提出实际的、可回答的问题。”我不知道在哪里“。如前所述,如果您知道我应该在另一个Stack Exchange站点发布此内容,请推荐。@djechlin您弄错了。问一个关于堆栈溢出的实际编码问题是完全可以的。我想也许你在想程序员。在任何情况下,请随时询问Meta以澄清。它可能需要这样做,但不幸的是,这会返回StackOverflow错误-可能是由于其他地方的错误。您应该将该更改应用于原始代码。您在edit2中的更改是错误的。您必须在循环之前更改i&j,因为它们被初始化为刚好超出您正在分区的数组范围的值。我已将我的个人副本更改回edit2之前,并将返回int更改为j-但是,它仍然会生成StackOverflow错误您有调试器吗?StackOverflow意味着partition方法不会对输入进行分区(即其中一个分区为空),这会导致无限递归。是的,我现在在Eclipse调试器上完成每个步骤(使用您的编辑)。只是不知道如何停止错误!工作完美。先生,你绝对是个传奇人物。我将研究你的代码和我的代码之间的差异,并尝试从中学习。没问题。如果你需要任何澄清,请在这里发表评论。嗨,你能进一步解释一下这句话吗?int pivot=a[left+(right-left)/2]@这意味着我们选择“<代码>枢轴< /代码>的值:位于<>代码>左和<代码>右< /代码>之间的元素。这都有帮助。我将研究这一点,并尝试从中学习。感谢you@AndrewMartin
int pivot = a[(left + right) / 2];
swap(left, (left + right) / 2);
int pivot = a[left];