V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wenb1
V2EX  ›  Java

Java 快速排序算法问题

  •  
  •   wenb1 · 2018-12-18 06:42:32 +08:00 · 2963 次点击
    这是一个创建于 2197 天前的主题,其中的信息可能已经有所发展或是发生改变。

    菜鸡如我又来问问题了,我懂快速排序的思路,但是没看懂这个方法 private static int partition(Comparable[] a, int lo, int hi)两个 while 循环是怎么配合 exch(a, i, j),less()执行的,while(true)里代码的执行顺序是什么样的。希望大神们能指教下,多谢了!

    源码 link: https://algs4.cs.princeton.edu/23quicksort/Quick.java.html

    public class Quick {
    
    // This class should not be instantiated.
    private Quick() { }
    
    /**
     * Rearranges the array in ascending order, using the natural order.
     * @param a the array to be sorted
     */
    public static void sort(Comparable[] a) {
        StdRandom.shuffle(a);
        sort(a, 0, a.length - 1);
        assert isSorted(a);
    }
    
    // quicksort the subarray from a[lo] to a[hi]
    private static void sort(Comparable[] a, int lo, int hi) { 
        if (hi <= lo) return;
        int j = partition(a, lo, hi);
        sort(a, lo, j-1);
        sort(a, j+1, hi);
        assert isSorted(a, lo, hi);
    }
    
    // partition the subarray a[lo..hi] so that a[lo..j-1] <= a[j] <= a[j+1..hi]
    // and return the index j.
    private static int partition(Comparable[] a, int lo, int hi) {
        int i = lo;
        int j = hi + 1;
        Comparable v = a[lo];
        while (true) { 
    
            // find item on lo to swap
            while (less(a[++i], v)) {
                if (i == hi) break;
            }
    
            // find item on hi to swap
            while (less(v, a[--j])) {
                if (j == lo) break;      // redundant since a[lo] acts as sentinel
            }
    
            // check if pointers cross
            if (i >= j) break;
    
            exch(a, i, j);
        }
    
        // put partitioning item v at a[j]
        exch(a, lo, j);
    
        // now, a[lo .. j-1] <= a[j] <= a[j+1 .. hi]
        return j;
    }
    
    private static boolean less(Comparable v, Comparable w) {
        if (v == w) return false;   // optimization when reference equals
        return v.compareTo(w) < 0;
    }
        
    // exchange a[i] and a[j]
    private static void exch(Object[] a, int i, int j) {
        Object swap = a[i];
        a[i] = a[j];
        a[j] = swap;
    }
    
    10 条回复    2018-12-18 11:17:40 +08:00
    ywcjxf1515
        1
    ywcjxf1515  
       2018-12-18 08:14:10 +08:00 via iPhone
    三个 break 都表示跳出循环,这时变一下基准数位置,就切分完毕,变成比基准数小,基准数,比基准数大三部分。第一个 break,到右边界,跳出循环,表示其他所有数都比基准数小。第二个 break,到左边界,跳出循环,表示所有其他所有数都比基准数大。while(true)内部的的第二个 while 之下的 if 的条件能成立,表示剩下所有数是前面部分比基准数大,后面部分比基准数小,同样是变一下基准数位置就切分完毕。exch(a,i,j)是放在 break 之后,有隐含条件是 if(i<j),为了交换左边的一个和右边的一个数,最终是为了达到左边比基准数小,右边比基准数大。
    wenb1
        2
    wenb1  
    OP
       2018-12-18 08:31:06 +08:00
    @ywcjxf1515 感谢回答,你说的这些我都明白的,可能我问的不太清楚,我想问两个 while 在什么条件会停下来得到 i 和
    j 并完成一次交换? while 是在得到 less 的结果为 true 的时候停下来吗,然后得到了 i 的值,同理取得 j 的值,再进行交换?
    luosuosile
        3
    luosuosile  
       2018-12-18 08:43:09 +08:00
    大红本算法第四版,理由有图,说的很清楚。数据结构和算法的好书
    wenb1
        4
    wenb1  
    OP
       2018-12-18 09:01:11 +08:00
    @luosuosile 多谢提醒,我没仔细看那个图,看了一下明白了。。。
    ywcjxf1515
        5
    ywcjxf1515  
       2018-12-18 09:13:15 +08:00 via iPhone   ❤️ 1
    @wenb1 你问的 while 的应该是 while(true)内部的两个 while 吧?在得到 less 的结果为 true 时,并不会停下来,内部不是还有一个 if,停下来要么是 if 的 break 执行了,要么是 less 的结果是 false,这时 i 才不变,等着被交换。j 同理。切分的目标是左边的所有比基准数小,右边的所有比基准数大,排定基准数。为了减少交换,从左边起比基准数小,就自加序号看下一个数,直到不比基准数大(也就是 false)。
    wenb1
        6
    wenb1  
    OP
       2018-12-18 09:15:43 +08:00
    @ywcjxf1515 明白了,感谢回答!
    dezhou9
        7
    dezhou9  
       2018-12-18 10:41:00 +08:00 via Android
    这个函数命名很差 less exch 都不是完整的话啊
    quinoa42
        8
    quinoa42  
       2018-12-18 10:41:48 +08:00
    觉得难理解可以看 clrs 快排那章,思路清晰也很好懂
    wenb1
        9
    wenb1  
    OP
       2018-12-18 11:17:18 +08:00
    @dezhou9 不会吧,这本书还是比较权威的教科书
    wenb1
        10
    wenb1  
    OP
       2018-12-18 11:17:40 +08:00
    @quinoa42 我已经明白了,谢谢啦
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1170 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 18:25 · PVG 02:25 · LAX 10:25 · JFK 13:25
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.