现在我们已经实现了两种排序算法,我们很自然地想知道选择排序和插入排序哪种更快。这里我们第一次用实践说明我们解决这个问题的办法。
性质:对于随机排序的无重复主键的数组,插入排序和选择排序的运行时间是平方级别的,两者之比应该是一个较小的常数。
例证:这个结论在过去的半个世纪中已经在许多不同类型的计算机上经过了验证。在1980年本书第一版完成之时插入排序就比选择排序快一倍,现在仍然是这样,尽管那时这些算法将10万条数据排序需要几个小时而现在只需要几秒钟。在你的计算机上插入排序也比选择排序快一些吗?可以通过SortCompare类来检测。它会使用由命令行参数指定的排序算法名称所对应的sort()方法进行指定次数的实验(将指定大小的数组排序),并打印出所观察到的各种算法的运行时间的比例。
我们使用Stopwatch来计时。
随机数组的输入模型由SortCompare类中的timeRandom-Input()方法实现。这个方法会生成随机的Double值,将它们排序,并返回指定次测试的总时间。
用命令行参数指定重复次数的好处是能够运行大量的测试(测试次数越多,每遍测试所需的平均时间就越接近于真实的平均数据)并且能够减小系统本身的影响。
/** * 比较两种排序算法 * @author huazhou * */ public class SortCompare { public static double time(String alg, Comparable[] a){ Selection selection = new Selection(); Insertion insertion = new Insertion(); Stopwatch timer = new Stopwatch(); if(alg.equals("Selection")){ selection.sort(a); } if(alg.equals("Insertion")){ insertion.sort(a); } return timer.elapsedTime(); } public static double timeRandomInput(String alg, int N, int T){ //使用算法1将T个长度为N的数组排序 double total = 0.0; Double[] a = new Double[N]; for (int t = 0; t < T; t++) { //进行一次测试(生成一个数组并排序) for (int i = 0; i < N; i++) { a[i] = StdRandom.uniform(); } total += time(alg, a); } return total; } public static void main(String[] args){ String alg1 = args[0]; String alg2 = args[1]; int N = Integer.parseInt(args[2]); int T = Integer.parseInt(args[3]); double t1 = timeRandomInput(alg1, N, T);//算法1的总时间 double t2 = timeRandomInput(alg2, N, T);//算法2的总时间 StdOut.printf("For %d random Doubles\n %s is", N, alg1); StdOut.printf(" %.1f times faster than %s\n", t2/t1, alg2); } }
这个用例会运行由前两个命令行参数指定的排序算法,对长度为N(由第三个参数指定)的Double型随机数组进行排序,元素值均在0.0到1.0之间,重复T次(由第四个参数指定),然后输出总运行时间的比例。
【源码下载】
时间: 2024-12-21 02:07:52