Quicksort 3路分区代码没有按照它所说的去做

时间:2017-11-14 11:18:14

标签: java algorithm quicksort partitioning

我需要制作一个利用3路分区的快速方法。我可以在这里找到使用的算法https://algs4.cs.princeton.edu/lectures/23DemoPartitioning.pdf向下滚动到Dijkstra 3路分区演示。对于某些数组,如5 5 7 3 5 1 6 2 4 8,我的方法有效。但是,当我放置一个数组,如5 5 7 3 5 1 6 2 4 8 9 8时,我的代码无法正常工作。我得到输出:1 2 3 4 5 5 5 6 7 8 9 8.我知道问题是什么,但我不明白为什么我的代码没有处理它。这是我的代码:

import java.util.Scanner;

public class QuickSortDriver {

    public static void main(String[] args) 
    {
        Scanner scan = new Scanner(System.in);
        System.out.print("\n\nEnter array elements: ");
        String s = scan.nextLine();
        String[] token = s.split(" ");
        int[] array = new int[token.length];

        for(int i=0; i < array.length; i++)
            array[i] = Integer.parseInt(token[i]);

        quicksort(array, 0, array.length - 1);

        System.out.print("\nSorted array: ");

        for(int i = 0; i < array.length; i++)
            System.out.printf("%d ", array[i]);

        System.out.print("\n\n");
        scan.close();
    }

    public static void quicksort(int [] array, int low, int high)
    {
        //debugging: shows what the array is
        //before the while loop
        System.out.print("\n");
        for(int j = low; j <= high; j++)
            System.out.printf("%d ", array[j]);

        if(high <= low) 
            return;

        int lt = low;
        int gt = high;
        int i = low;

        while(i <= gt)
        {
            if(array[i] < array[low])
                swap(array, lt++, i++);
            else if(array[i] > array[low])
                swap(array, i, gt--);
            else
                i++;
        }

        //debugging: shows what the array is
        //after the while loop
        System.out.print("\n");
        for(int j = low; j <= high; j++)
            System.out.printf("%d ", array[j]);

        quicksort(array, low, lt -1);
        quicksort(array, gt + 1, high);
    }

    public static void swap(int array[], int i, int j)
    {
        int tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }

}

为了调试目的,我在排序方法的开头和结尾放置了打印出数组的for循环,并通过这样做我发现了问题。这是打印调试语句的输入输出:

Enter array elements: 5 5 7 3 5 1 6 2 4 8 9 8

5 5 7 3 5 1 6 2 4 8 9 8 
4 3 2 1 5 5 6 5 8 9 8 7 
4 3 2 1 
3 2 1 4 
3 2 1 
2 1 3 
2 1 
1 2 
1 



6 5 8 9 8 7 
5 6 9 8 7 8 
5 
9 8 7 8 
8 7 9 8 <--right here is the problem
8 7 
7 8 
7 


Sorted array: 1 2 3 4 5 5 5 6 7 8 9 8 

当我的程序进入数组的9 8 7 8部分时,它应该这样做:

(请遵循Dijkstra 3路分区算法中的逻辑。)

9 8 7 8

i = 9 lt = 9 gt = 8(at end) increment i

9 8 7 8

i = 8 lt = 9 gt = 8(at end) swap i and lt and increment i

8 9 7 8

i = 7 lt = 9 gt = 8(at end) swap i and lt and increment i

8 7 9 8

i = 8(在结束时)lt = 9 gt = 8(在结束时)此时它应该交换i和lt并递增i。但是,它并没有,我不明白为什么。我的while循环中的条件是while(i&lt; = gt),因此它应该在该点继续迭代,因为i和gt处于相同的索引(参考代码),但它不是。如果这里的任何人可以帮我解决这个问题,我将非常感谢我真的要开始拔头发。

2 个答案:

答案 0 :(得分:1)

这不是错误修复。仅仅是一些帮助来确定问题:

添加更多这样的调试:

    System.out.println("Part 1: " + low + " to " + (lt-1));
    System.out.println("Part 2: " + (gt+1) + " to " + high);
    quicksort(array, low, lt -1);
    quicksort(array, gt + 1, high);

如果初始输入数组是9,8,7,8,则在第一次迭代后数组将是8,7,9,8。新输出变为

Part 1: 0 to 1
Part 2: 4 to 3

这意味着前两项 - 8,7 - 将在下一轮中进行排序。但是之后没有任何事情发生,因为4> 3,所以9,8将保持错误的顺序。很明显,如果(在这种情况下)第2部分是&#34; 2到3&#34;,那一切都会好的。

可悲的是,如何解决这个问题还不太清楚。在这种情况下,以下方法可行,但我怀疑Quicksort应该如何工作,并且在其他情况下可能不起作用:

    quicksort(array, low, lt -1);
    quicksort(array, lt, high);

答案 1 :(得分:1)

尝试在while循环中使用lt而不是low。它应该是这样的:

    while(i <= gt)
    {
        if(array[i] < array[lt])
            swap(array, lt++, i++);
        else if(array[i] > array[lt])
            swap(array, i, gt--);
        else
            i++;
    }