zoukankan      html  css  js  c++  java
  • 常用算法之排序(Java)

    一.常用算法(Java实现)
    1.选择排序(初级算法)
    原理:有N个数据则外循环就遍历N次并进行N次交换。内循环实现将外循环当前的索引i元素与索引大于i的所有元素进行比较找到最小元素索引,然后外循环进行元素交换
      第1次遍历,将索引为0的元素与索引大于0的所有元素进行比较找到最小的元素,将最小元素与索引为0的元素交换位置(若索引为0的元素就是最小元素那么它就和自己交换)
      第2次遍历,将索引为1的元素与索引大于1的所有元素进行比较找到最小的元素,将最小元素与索引为1的元素交换位置(若索引为1的元素就是最小元素那么它就和自己交换)。
       如此往复,直到将整个数组排好序。
    特点:N*N/2次比较和N次交换
     
    优点:数据交换次数最少的,与数组大小是线性关系,只有N次,别的排序算法大部分的增长数量级都是线性对数或平方级别
    缺点:运行时间和输入无关。如,两个长度都为N的数组,一个元素顺序随机的数组,另一个已排好序或所有元素相等的数组,他们的排序时间一样长。
    选择排序源码:Selection.java
     
    @SuppressWarnings("unchecked")
    public class Selection
    {
        // This class should not be instantiated.
        private Selection() { }
        
        public static void sort(Comparable[] a)
        {
            // in ascending order
            int N = a.length;
            for(int i = 0;i < N;i++)
            {
                // exchange elements
                int min = i;
                for(int j= i+1;j < N;j++)
                {
                    // find the index of the smallest element 
                    if(less(a[j], a[min]))
                    {
                        min = j;
                    }    
                }
                exch(a, i, min);
            }    
    
        }
        
        // is v < w ?
        private static boolean less(Comparable v, Comparable w) {
            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;
        }
        
        // print array to standard output
        private static void show(Comparable[] a) {
            for (int i = 0; i < a.length; i++) {
                System.out.print(a[i]+" ");
            }
            System.out.println("");
        }
        
        public static void main(String[] args) {
            Comparable[] a = {3,5,2,1,7,4,6};
            Selection.sort(a);
            show(a);
        }
    }
     
    2.插入排序(初级算法)
    原理:就像现实中玩扑克牌一样,一张一张的来,将每一张牌插入到其他已经有序的牌中的适当的位置。为了给要插入的元素腾出空间,需将其余所有元素在插入前向右移动一位。
    特点:
       原始数据有序性越高,插入排序越快。
       平均情况下:插入排序需要N*N/4次比较和N*N/4次交换
       最坏情况下:插入排序需要N*N/2次比较和N*N/2次交换(逆序数组)
       最好情况下:插入排序需要N-1次比较和0次交换(已排好序的数组)
     
    优点:插入排序运行时间取决于数组元素初始顺序。如,使用插入排序对一个很大且其中的元素已有序(或接近有序)的数组进行排序将会比对随机顺序的数组或逆序数组进行排序要快的多
    缺点:比较次数越少,插入点后的数据移动越多,特别是当数据总量庞大的时候
    适用场景:插入排序对部分有序的数组十分高效,也很适合小规模数组
    插入排序源码:Insertion.java
     
    @SuppressWarnings("unchecked")
    public class Insertion
    {
        // This class should not be instantiated.
        private Insertion() { }
        
        public static void sort(Comparable[] a)
        {
            // in ascending order
            int N = a.length;
            for(int i = 1;i < N;i++)
            {
                // exchange elements
                for(int j= i;j > 0 && less(a[j],a[j -1]);j--)
                {
                    exch(a, j, j-1);    
                }
            }    
    
        }
        
        // less()、show()、exch()和main()方法见Selection.java
    }
    3.希尔排序(基于插入排序的基础上进行改进的排序算法)
    原理:在插入排序的基础上使数组中任意间隔为h的元素都是有序的
    优点:代码量小,且不需要额外的内存空间,比插入排序和选择排序快得多(因为它权衡了子数组的规模和有序性),数组越大,优势越大
    缺点:h乘以的常数因子只能凭经验来设置,不太稳定
    适用场景:大规模乱序数组
    希尔排序源码:Shell.java
     
    @SuppressWarnings("unchecked")
    public class Shell
    {
        // This class should not be instantiated.
        private Shell() { }
        
        public static void sort(Comparable[] a)
        {
            // in ascending order
            int N = a.length;
            // 3x+1 increment sequence:  1, 4, 13, 40, 121, 364, 1093, ... 
            int h = 1;
            while (h < N/3) {
                h = 3*h + 1; 
            }
            while (h >= 1) {
                // h-sort the array
                for (int i = h; i < N; i++) {
                    for (int j = i; j >= h && less(a[j], a[j -h]); j -= h) {
                        exch(a,j, j-h);    
                    }
                }
                h /= 3;
            }
        }
        
        // less()、show()、exch()和main()方法见Selection.java
    }
    4.归并排序(基于归并的一种递归排序算法,即将两个有序的数组归并成一个更大的有序数组)
    原理:要将一个数组排序,可先(递归的)将它等分成两半分别排序,然后将结果归并起来。递归发生在处理整个数据之前。
    优点:将任意长度为N的数组排序的排序时间和NlogN成正比
    缺点:实现比较复杂,排序需要额外空间且它所需的额外空间和N成正比
    适用场景:稳定性很重要而空间不是问题时,归并排序可能是最好的
    (自顶向下的)归并排序源码:Merge.java
     
    @SuppressWarnings("unchecked")
    public class Merge
    {
        // This class should not be instantiated.
        private Merge() { }
        
        /**
         * Rearranges the array in ascending order, using the natural order.
         * @param a the array to be sorted
         */
        public static void sort(Comparable[] a) {
            Comparable[] aux = new Comparable[a.length];
            sort(a, aux, 0, a.length-1);
        }
        
        // mergesort a[lo..hi] using auxiliary array aux[lo..hi]
        private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi) {
            if (hi <= lo) return;
            int mid = lo + (hi - lo) / 2;
            sort(a, aux, lo, mid);
            sort(a, aux, mid + 1, hi);
            merge(a, aux, lo, mid, hi);
        }
        
        // stably merge a[lo .. mid] with a[mid+1 ..hi] using aux[lo .. hi]
        private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {
            // copy to aux[]
            for (int k = lo; k <= hi; k++) {
                aux[k] = a[k]; 
            }
    
            // merge back to a[]
            int i = lo, j = mid+1;
            for (int k = lo; k <= hi; k++) {
                if (i > mid){              
                    a[k] = aux[j++];
                } else if (j > hi) {              
                    a[k] = aux[i++];
                } else if (less(aux[j], aux[i])) {
                    a[k] = aux[j++];
                } else {                           
                    a[k] = aux[i++];
                }
            }
        }
        
        // less()、show()、exch()和main()方法见Selection.java
    }
    5.快速排序(是一种分治的排序算法,是最流行使用最广泛的排序算法,推荐)
    原理:与归并排序不同之处是快速排序切分(partition)的位置取决于数组的内容而归并排序是等分成两半。先将一个数组切分成两个子数组,然后将两部分独立排序。递归发生在处理整个数组之后。
    特点:原地排序(只需一个很小的辅助栈)
    优点:实现简单,原地排序且将长度为N的数组排序所需的时间和NlgN成正比
    缺点:非常脆弱,实现时要非常小心才能避免低劣的性能,多种错误能使它在实际中的性能只有平方级别
    适用场景:适用无重复元素的数组排序。运行时间至关重要而稳定性要求不是很高时,快速排序可能是最好的
    快速排序源码:Quick.java
     打乱数组源码:StdRandom.java
    @SuppressWarnings("unchecked")
    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); } // 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); } // 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; } // less()、show()、exch()和main()方法见Selection.java }
    import java.util.Random;
    public final class StdRandom {
    
        private static Random random;    // pseudo-random number generator
        private static long seed;        // pseudo-random number generator seed
    
        // static initializer
        static {
            // this is how the seed was set in Java 1.4
            seed = System.currentTimeMillis();
            random = new Random(seed);
        }
    
        // don't instantiate
        private StdRandom() { }
    
        /**
         * Returns a random real number uniformly in [0, 1).
         *
         * @return a random real number uniformly in [0, 1)
         */
        public static double uniform() {
            return random.nextDouble();
        }
    
        /**
         * Returns a random integer uniformly in [0, n).
         * 
         * @param n number of possible integers
         * @return a random integer uniformly between 0 (inclusive) and {@code n} (exclusive)
         * @throws IllegalArgumentException if {@code n <= 0}
         */
        public static int uniform(int n) {
            if (n <= 0) throw new IllegalArgumentException("argument must be positive: " + n);
            return random.nextInt(n);
        }
    
    
        /**
         * Returns a random long integer uniformly in [0, n).
         * 
         * @param n number of possible {@code long} integers
         * @return a random long integer uniformly between 0 (inclusive) and {@code n} (exclusive)
         * @throws IllegalArgumentException if {@code n <= 0}
         */
        public static long uniform(long n) {
            if (n <= 0L) throw new IllegalArgumentException("argument must be positive: " + n);
            long r = random.nextLong();
            long m = n - 1;
    
            // power of two
            if ((n & m) == 0L) {
                return r & m;
            }
    
            // reject over-represented candidates
            long u = r >>> 1;
            while (u + m - (r = u % n) < 0L) {
                u = random.nextLong() >>> 1;
            }
            return r;
        }
    
        /**
         * Returns a random integer uniformly in [a, b).
         * 
         * @param  a the left endpoint
         * @param  b the right endpoint
         * @return a random integer uniformly in [a, b)
         * @throws IllegalArgumentException if {@code b <= a}
         * @throws IllegalArgumentException if {@code b - a >= Integer.MAX_VALUE}
         */
        public static int uniform(int a, int b) {
            if ((b <= a) || ((long) b - a >= Integer.MAX_VALUE)) {
                throw new IllegalArgumentException("invalid range: [" + a + ", " + b + ")");
            }
            return a + uniform(b - a);
        }
    
        /**
         * Returns a random real number uniformly in [a, b).
         * 
         * @param  a the left endpoint
         * @param  b the right endpoint
         * @return a random real number uniformly in [a, b)
         * @throws IllegalArgumentException unless {@code a < b}
         */
        public static double uniform(double a, double b) {
            if (!(a < b)) {
                throw new IllegalArgumentException("invalid range: [" + a + ", " + b + ")");
            }
            return a + uniform() * (b-a);
        }
    
        /**
         * Rearranges the elements of the specified array in uniformly random order.
         *
         * @param  a the array to shuffle
         * @throws IllegalArgumentException if {@code a} is {@code null}
         */
        public static void shuffle(Object[] a) {
            validateNotNull(a);
            int n = a.length;
            for (int i = 0; i < n; i++) {
                int r = i + uniform(n-i);     // between i and n-1
                Object temp = a[i];
                a[i] = a[r];
                a[r] = temp;
            }
        }
    
        /**
         * Rearranges the elements of the specified array in uniformly random order.
         *
         * @param  a the array to shuffle
         * @throws IllegalArgumentException if {@code a} is {@code null}
         */
        public static void shuffle(double[] a) {
            validateNotNull(a);
            int n = a.length;
            for (int i = 0; i < n; i++) {
                int r = i + uniform(n-i);     // between i and n-1
                double temp = a[i];
                a[i] = a[r];
                a[r] = temp;
            }
        }
    
        /**
         * Rearranges the elements of the specified array in uniformly random order.
         *
         * @param  a the array to shuffle
         * @throws IllegalArgumentException if {@code a} is {@code null}
         */
        public static void shuffle(int[] a) {
            validateNotNull(a);
            int n = a.length;
            for (int i = 0; i < n; i++) {
                int r = i + uniform(n-i);     // between i and n-1
                int temp = a[i];
                a[i] = a[r];
                a[r] = temp;
            }
        }
    
        /**
         * Rearranges the elements of the specified array in uniformly random order.
         *
         * @param  a the array to shuffle
         * @throws IllegalArgumentException if {@code a} is {@code null}
         */
        public static void shuffle(char[] a) {
            validateNotNull(a);
            int n = a.length;
            for (int i = 0; i < n; i++) {
                int r = i + uniform(n-i);     // between i and n-1
                char temp = a[i];
                a[i] = a[r];
                a[r] = temp;
            }
        }
    
        // throw an IllegalArgumentException if x is null
        // (x can be of type Object[], double[], int[], ...)
        private static void validateNotNull(Object x) {
            if (x == null) {
                throw new IllegalArgumentException("argument is null");
            }
        }
    
        /**
         * Unit tests the methods in this class.
         *
         * @param args the command-line arguments
         */
        public static void main(String[] args) {
            String[] a = "A B C D E F G".split(" ");
            StdRandom.shuffle(a);
            for (String s : a){
                System.out.print(" "+s);
            }
            System.out.println("");
        }
    
    }
    6.三向切分的快速排序(快速排序的基础上进行改进的排序算法)
    原理:从左到右遍历数组一次,维护3个指针。一个指针lt,使得a[lo..lt-1]中的元素都小于v;一个指针gt,使得a[gt+1..hi]中的元素都大于v;一个指针i,使得a[lt..i-1]中的元素都等于v;a[i..gt]中的元素都还未确定。
    优点:对于包含大量重复元素的数组,排序时间是线性的
    缺点:数组中重复元素不多时比标准的二分法多使用很多次交换,最坏的情况是所有元素均不重复时
    适用场景:适用大量重复元素的数组排序,如企业可能需要将大量人员资料按照生日或性别排序
    三向切分的快速排序源码:Quick3Way.java
     
    @SuppressWarnings("unchecked")
    public class Quick3Way
    {
        // This class should not be instantiated.
        private Quick3Way() { }
        
        /**
         * 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);
        }
    
        // quicksort the subarray a[lo .. hi] using 3-way partitioning
        private static void sort(Comparable[] a, int lo, int hi) { 
            if (hi <= lo) return;
         int lt = lo, i = lo + 1, gt = hi;
            Comparable v = a[lo];while (i <= gt) {
                int cmp = a[i].compareTo(v);
                if (cmp < 0) {
                    exch(a, lt++, i++);
                } else if (cmp > 0) {
                    exch(a, i, gt--);
                } else {              
                    i++;
                }
            }
    
            // a[lo..lt-1] < v = a[lt..gt] < a[gt+1..hi]. 
            sort(a, lo, lt-1);
            sort(a, gt+1, hi);
        }
        
        // less()、show()、exch()和main()方法见Selection.java
    }
    7.堆排序(基于插入排序的基础上进行改进的排序算法)
    原理:堆排序分两个阶段:堆的构造阶段和下沉排序阶段。
       堆的构造阶段将原始数组重新组织安排进一个堆中;
        下沉排序阶段从堆中按降序取出所有元素并得到排序结果(类似选择排序,只是选择排序是升序,而堆是降序取出所有元素,因为堆提供了一种从未排序部分找到最大元素的有效方法,所以它所需的比较            次数较选择排序要少得多)
    优点:插入操作和删除最大元素操作混合的动态场景时运行时间能保证是对数级别的
    缺点:无法利用缓存,数组元素很少和相邻的其他元素进行比较,因此缓存未命中的次数要远高于大多数比较都在相邻元素间进行的排序算法(如快速排序、归并排序、希尔排序等)
    适用场景:插入操作和删除最大元素操作混合的动态场景(此时运行时间能保证是对数级别的)
    堆排序源码:Heap.java
     
    @SuppressWarnings("unchecked")
    public class Heap
    {
        // This class should not be instantiated.
        private Heap() { }
        
        /**
         * Rearranges the array in ascending order, using the natural order.
         * @param pq the array to be sorted
         */
        public static void sort(final Comparable[] pq) {
            int n = pq.length;
            for (int k = n/2; k >= 1; k--){
                sink(pq, k, n);
            }
            while (n > 1) {
                exch(pq, 1, n--);
                sink(pq, 1, n);
            }
        }
    
       /***************************************************************************
        * Helper functions to restore the heap invariant.
        ***************************************************************************/
    
        private static void sink(Comparable[] pq, int k, int n) {
            while (2*k <= n) {
                int j = 2*k;
                if (j < n && less(pq[j-1], pq[j])){
                    j++;
                }
                if (!less(pq[k-1], pq[j-1])) {
                    break;
                }
                exch(pq, k, j);
                k = j;
            }
        }
        
        // less()、show()、exch()和main()方法见Selection.java
    }

     二.实际应用中如何选择何种算法

    Java的系统程序员对原始数据类型使用(三向切分的)快速排序(速度快),对引用类型使用归并排序(稳定性高)。见Array.sort()实现

     总结:实际应用中如何选择使用何种排序

    ———————————————————————————————————————————————————————————————————————
     算法    是否稳定   是否为原地排序    N个元素排序的复杂度       备注                          适用场景
                                时间复杂度   空间复杂度
    ———————————————————————————————————————————————————————————————————————
    选择排序    否        是          N*N        1                                  适合小规模数组
    插入排序    是        是       介于N和N*N之间   1    取决于输入元素的排列情况                  适合插入排序对部分有序的数组十分高效,也很适合小规模数组
    希尔排序    否        是         NlogN?        1                                适合大规模乱序数组
    快速排序    否        是         NlogN       lgN  运行效率由概率保证          适用无重复元素的数组排序。运行时间至关重要而稳定性要求不是很高时,快速排序可能是最好的
    三向快速排序  否        是       介于N和NlogN之间 lgN  运行效率由概率提供保证,也取决于输入元素的分布情况 适用大量重复元素的数组排序,如企业可能需要将大量人员资料按照生日或性别排序
    归并排序    是        否         NlogN       N                               稳定性很重要而空间不是问题时,归并排序可能是最好的
    堆排序        否        是         NlogN       1                           插入操作和删除最大元素操作混合的动态场景(此时运行时间能保证是对数级别的)

    三.各常用算法耗时比较

    见SortCompare.java

    Stopwatch.java为耗时类

    /******************************************************************************
     *  Compilation:  javac SortCompare.java
     *  Execution:    java SortCompare Insertion Selection 1000 100
     *  1000 means the Length of automatically generating arrays 
     *    100 means repeats times
     *  Compare the running time of these algorithms.
     *
     *
     *  % java SortCompare Insertion Selection 1000 100
     *  For 1000 random Doubles Insertion takes 0.125 seconds
     *  For 1000 random Doubles Selection takes 0.125 seconds
     *
     *
     *  % java SortCompare Insertion Selection Shell Merge Quick Heap 1000 100
     *  For 1000 random Doubles Insertion takes 0.094 seconds
     *  For 1000 random Doubles Selection takes 0.094 seconds
     *  For 1000 random Doubles Shell takes 0.109 seconds
     *  For 1000 random Doubles Merge takes 0.062 seconds
     *  For 1000 random Doubles Quick takes 0.078 seconds
     *  For 1000 random Doubles Heap  takes 0.032 seconds
     *
     *
     *  % java SortCompare Insertion Selection Shell Merge Quick Heap 100000 100
     *  For 100000 random Doubles Insertion takes 1447.799 seconds
     *  For 100000 random Doubles Selection takes 1217.424 seconds
     *  For 100000 random Doubles Shell takes 3.613 seconds
     *  For 100000 random Doubles Merge takes 2.467 seconds
     *  For 100000 random Doubles Quick takes 1.973 seconds
     *  For 100000 random Doubles Heap  takes 2.812 seconds
     *
     ******************************************************************************/
    
    
    import java.util.Arrays;
    import java.util.ArrayList;
    import java.util.List;
    public class SortCompare
    {
        private static final String[] ALG = {"Insertion", "Selection", "Shell", "Merge", "Quick", "Heap"};
        
        /**
         * time
         * @param alg  algorithm name
         * @param a  the array
         */
        public static double time(String alg, Double[] a){
            Stopwatch timer = new Stopwatch();
            
            // printBeforeSort(alg, a);    // Print the original array 
    
            if(alg.equals("Insertion")){
                Insertion.sort(a);
            } else if(alg.equals("Selection")){
                Selection.sort(a);
            } else if(alg.equals("Shell")){
                Shell.sort(a);
            } else if(alg.equals("Merge")){
                Merge.sort(a);
            } else if(alg.equals("Quick")){
                Quick.sort(a);
            } else if(alg.equals("Heap")){
                Heap.sort(a);
            }
            
            // printAfterSort(alg, a);        // Print the sorted array 
            
            return timer.elapsedTime();
        }
        
        /**
         * total elapsed time
         * @param alg  algorithm name
         * @param N  the length of the array 
         * @param T  repeats times
         */
        public static double timeRandomInput(String alg, int N, int T)
        {
            // Sort T arrays of length N by using algorithm 
            double total = 0.0;
            Double[] a = new Double[N];
            for(int t = 0; t < T; t++)
            {
                // generate and sort 
                for(int i = 0; i < N; i++)
                {
                    a[i] = StdRandom.uniform();
                }
                total += time(alg, a);
            }
            return total;
        }
        
        public static void main(String[] args)
        {    
            testDataFromArgs(args);
            
            //testDataFromFile(args);
        }
        
        /**
         * 
         * % java SortCompare Insertion Selection 1000 100
         */
        private static void testDataFromArgs(String[] args){
            if(args == null || args.length < 3){
                System.out.println("Incorrect number of arguments,the mininum mumber is 3!!!");
                return;
            }
            
            int len = args.length -2;
            List<String> al = new ArrayList<String>(Arrays.asList(ALG));
            for(int i = 0; i < len;i++){
                if(!al.contains(args[i]))
                {
                    System.out.println("Contains unknown algorithm names!!!");
                    return;
                }
            }
            
            int N = Integer.parseInt(args[len]);
            int T = Integer.parseInt(args[len + 1]);
            
            double t = 0.0;
            for(int i = 0; i < len;i++){
                t = timeRandomInput(args[i], N, T);// total time of algorithm 
                System.out.format("For %d random Doubles %s takes %.3f seconds 
    ", N, args[i], t);
            }
        }
        
        /**
         *  
         * % more test.txt
         * 
         * % java SortCompare < test.txt
         */
        private static void testDataFromFile(String[] args){
            double[] b = StdIn.readAllDoubles();
            int N = b.length;
            int T = 100;
            Double[] a = new Double[N];
            
            for(int i = 0;i < N;i++){
                a[i] = b[i];
            }
                
            int len = ALG.length;
            double t = 0.0;
            for(int i = 0; i < len;i++){
                t = timeRandomInput(ALG[i], a, T);// total time of algorithm 
                System.out.format("For %d random Doubles %s takes %.3f seconds 
    ", N, ALG[i], t);
            }
        }
        
        private static double timeRandomInput(String alg, Double[] a, int T)
        {
            // Sort T arrays of length N by using algorithm 
            double total = 0.0;
            for(int t = 0; t < T; t++)
            {
                total += time(alg, a);
            }
            return total;
        }
        
        private static void printBeforeSort(String alg, Double[] a){
            if(a.length > 50){
                return;
            }
            System.out.format("
    %s --- before sort
    ", alg);
            show(a);
        }
        
        private static void printAfterSort(String alg, Double[] a){
            if(a.length > 50){
                return;
            }
            System.out.format("
    %s --- after sort
    ", alg);
            show(a);
        }
        
        private static void show(Comparable[] a) {
            for (int i = 0; i < a.length; i++) {
                System.out.print(a[i]+" ");
            }
            System.out.println();
        }
    }

    Stopwatch.java源码如下:

    public class Stopwatch {
        private final long start;
        /**
         * Initializes a new stopwatch.
         */
        public Stopwatch() {
            start = System.currentTimeMillis();
        }

        /**
         * Returns the elapsed CPU time (in seconds) since the stopwatch was created.
         *
         * @return elapsed CPU time (in seconds) since the stopwatch was created
         */
        public double elapsedTime() {
            long now = System.currentTimeMillis();
            return (now - start) / 1000.0;
        }
       
        /**
         * Unit tests the {@code Stopwatch} data type.
         * Takes a command-line argument {@code n} and computes the
         * sum of the square roots of the first {@code n} positive integers,
         * first using {@code Math.sqrt()}, then using {@code Math.pow()}.
         * It prints to standard output the sum and the amount of time to
         * compute the sum. Note that the discrete sum can be approximated by
         * an integral - the sum should be approximately 2/3 * (n^(3/2) - 1).
         *
         * @param args the command-line arguments
         */
        public static void main(String[] args) {
            int n = Integer.parseInt(args[0]);
            // sum of square roots of integers from 1 to n using Math.sqrt(x).
            Stopwatch timer1 = new Stopwatch();
            double sum1 = 0.0;
            for (int i = 1; i <= n; i++) {
                sum1 += Math.sqrt(i);
            }
            double time1 = timer1.elapsedTime();
          System.out.format("%e (%.2f seconds) ", sum1, time1);
      
            // sum of square roots of integers from 1 to n using Math.pow(x, 0.5).
            Stopwatch timer2 = new Stopwatch();
            double sum2 = 0.0;
            for (int i = 1; i <= n; i++) {
                sum2 += Math.pow(i, 0.5);
            }
            double time2 = timer2.elapsedTime();
          System.out.format("%e (%.2f seconds) ", sum2, time2);
        }
    }
  • 相关阅读:
    Node.js配置And HelloWorld
    谷歌浏览器扩展插件
    C#异步编程简单的运用
    C#中的特性基本理解
    JavaScript 字符 &quot;转换
    IHttpModule
    LinqToXml
    C#使用ajaxForm进行上传图片
    python 中的 __getitem__, __iter__ 和__next__
    python中的装饰器
  • 原文地址:https://www.cnblogs.com/bravestarrhu/p/Algorithms--sort--Java.html
Copyright © 2011-2022 走看看