首页 > 技术文章 > 算法(Algorithms)第4版 练习 2.3.17

songdechiu 2017-03-28 14:20 原文

关键代码:

  public static void sort(Comparable[] a) {
        StdRandom.shuffle(a);//eliminate dependence on input
        StdOut.print("After shuffle:");//for test
        show(a);//for test
        int largest = largest(a);
        exch(a, largest, a.length - 1);
        StdOut.print("After find largest and exchange:");//for test
        show(a);//for test
        sort(a, 0, a.length-1);
    }
    
    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);
        
    }
    
    private static int partition(Comparable[] a, int lo, int hi) {
        
        int i = lo;
        int j = hi + 1;
        Comparable v = a[lo];
        
        StdOut.println();//for test
        StdOut.printf("partition(input, %4d, %4d)\n", lo, hi);//for test
        
        while(true) {
            
            while(less(a[++i], v));//find item larger or equal to v
            while(less(v, a[--j]));//not need to worry about j will be out of bound
            
            StdOut.println("i:" + i + " j:" + j);//for test
            
            if(i >= j)//cross
                break;
            
            exch(a, i, j);
            show(a);//for test
        }
        exch(a, lo, j);
        
        StdOut.printf("j is %4d\n", j);//for test
        show(a);//for test
        
        return j;
        
    }

 

测试用例:

package com.qiusongde;

import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;

public class QuickSentinel {

    public static void sort(Comparable[] a) {
        StdRandom.shuffle(a);//eliminate dependence on input
        StdOut.print("After shuffle:");//for test
        show(a);//for test
        int largest = largest(a);//find largest item
        exch(a, largest, a.length - 1);//set sentinel in right bound
        StdOut.print("After find largest and exchange:");//for test
        show(a);//for test
        sort(a, 0, a.length-1);
    }
    
    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);
        
    }
    
    private static int partition(Comparable[] a, int lo, int hi) {
        
        int i = lo;
        int j = hi + 1;
        Comparable v = a[lo];
        
        StdOut.println();//for test
        StdOut.printf("partition(input, %4d, %4d)\n", lo, hi);//for test
        
        while(true) {
            
            while(less(a[++i], v));//find item larger or equal to v
            while(less(v, a[--j]));//not need to worry about j will be out of bound
            
            StdOut.println("i:" + i + " j:" + j);//for test
            
            if(i >= j)//cross
                break;
            
            exch(a, i, j);
            show(a);//for test
        }
        exch(a, lo, j);
        
        StdOut.printf("j is %4d\n", j);//for test
        show(a);//for test
        
        return j;
        
    }
    
    private static void exch(Comparable[] a, int i, int j) {
        
        Comparable t = a[i];
        a[i] = a[j];
        a[j] = t;
        
    }
    
    private static int largest(Comparable[] a) {
        assert a != null;
        assert a.length > 1;
        
        int largestindex = 0;
        for(int i = 1; i < a.length; i++) {
            if(less(a[largestindex], a[i]))
                largestindex = i;
        }
        
        return largestindex;
    }
    
    private static boolean less(Comparable v, Comparable w) {
        
        return v.compareTo(w) < 0;
        
    }
    
    private static void show(Comparable[] a) {
        
        //print the array, on a single line.
        for(int i = 0; i < a.length; i++) {
            StdOut.print(a[i] + " ");
        }
        StdOut.println();
        
    }
    
    public static boolean isSorted(Comparable[] a) {
        
        for(int i = 1; i < a.length; i++) {
            if(less(a[i], a[i-1]))
                return false;
        }
        
        return true;
        
    }
    
    public static void main(String[] args) {
        //Read strings from standard input, sort them, and print.
        String[] a = In.readStrings();
        show(a);
        sort(a);
        assert isSorted(a);
        show(a);
    }
    
}

 

输出结果:

红色部分可看到右子数组的最左元素可作为左子数组右边界的哨兵。

K R A T E L E P U I M Q C X O S 
After shuffle:E S I X E T P K C O R Q L U M A 
After find largest and exchange:E S I A E T P K C O R Q L U M X 

partition(input,    0,   15)
i:1 j:8
E C I A E T P K S O R Q L U M X 
i:2 j:4
E C E A I T P K S O R Q L U M X 
i:4 j:3
j is    3
A C E E I T P K S O R Q L U M X 

partition(input,    0,    2)
i:1 j:0
j is    0
A C E E I T P K S O R Q L U M X 

partition(input,    1,    2)
i:2 j:1
j is    1
A C E E I T P K S O R Q L U M X 

partition(input,    4,   15)
i:5 j:4
j is    4
A C E E I T P K S O R Q L U M X 

partition(input,    5,   15)
i:13 j:14
A C E E I T P K S O R Q L M U X 
i:14 j:13
j is   13
A C E E I M P K S O R Q L T U X 

partition(input,    5,   12)
i:6 j:12
A C E E I M L K S O R Q P T U X 
i:8 j:7
j is    7
A C E E I K L M S O R Q P T U X 

partition(input,    5,    6)
i:6 j:5
j is    5
A C E E I K L M S O R Q P T U X 

partition(input,    8,   12)
i:13 j:12
j is   12
A C E E I K L M P O R Q S T U X 

partition(input,    8,   11)
i:10 j:9
j is    9
A C E E I K L M O P R Q S T U X 

partition(input,   10,   11)
i:12 j:11
j is   11
A C E E I K L M O P Q R S T U X 

partition(input,   14,   15)
i:15 j:14
j is   14
A C E E I K L M O P Q R S T U X 
A C E E I K L M O P Q R S T U X 

 

性能对比:

For 2000 random Doubles 10000 trials
Quick is 2.3s QuickSentinel is 2.3s

没有大区别。

推荐阅读