插入排序、归并排序、快速排序的比较

清疚 2022-04-15 05:11 309阅读 0赞

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0RYSDkyNA_size_16_color_FFFFFF_t_70

为了获取每种排序算法实际的运行时间,我们可以为每种排序算法创建一个类,通过测试类调用它们,用Java自带的System.nanoTime()来获取算法运行的时间(1微秒=1000纳秒)。

整个过程需要以下API:

  1. /* 返回 v<w */
  2. private static boolean less(Comparable v, Comparable w){
  3. return v.compareTo(w)<0;
  4. }
  5. /* 交换a[i]与a[j]的位置 */
  6. private static void exch(Comparable[] a, int i, int j){
  7. Comparable temp = a[i];
  8. a[i] = a[j];
  9. a[j] = temp;
  10. }

插入排序:

  1. /* 插入排序 InsertSort */
  2. public class IS {
  3. private static long S = 0;
  4. public static void sort(Double[] a){
  5. int N = a.length;
  6. for (int i = 1; i < N; i++){
  7. for (int j = i; j > 0 && less(a[j], a[j-1]); j--){
  8. exch(a, j, j-1);
  9. }
  10. }
  11. }
  12. }

自顶向下归并排序:

  1. /* 自顶向下归并排序 Top-DownMergeSort */
  2. public class TDM {
  3. private static Comparable[] aux;
  4. public static void merge(Comparable[] a, int lo, int mid, int hi){
  5. int i=lo, j=mid+1;
  6. for (int k=lo; k<=hi; k++)
  7. aux[k]=a[k];
  8. for (int k=lo; k<=hi; k++){
  9. if (i>mid)
  10. a[k]=aux[j++];
  11. else if (j>hi)
  12. a[k]=aux[i++];
  13. else if (less(aux[j], aux[i]))
  14. a[k]=aux[j++];
  15. else
  16. a[k]=aux[i++];
  17. }
  18. }
  19. public static void sort(Comparable[] a){
  20. aux=new Comparable[a.length];
  21. sort(a, 0, a.length-1);
  22. }
  23. private static void sort(Comparable[] a, int lo, int hi){
  24. if (hi<=lo)
  25. return;
  26. int mid=lo+(hi-lo)/2;
  27. sort(a, lo, mid);
  28. sort(a, mid+1, hi);
  29. merge(a, lo, mid, hi);
  30. }
  31. }

自底向上归并排序

  1. /* 自底向上归并排序 Bottom-UpMergeSort */
  2. public class BUM {
  3. private static Comparable[] aux;
  4. public static void merge(Comparable[] a, int lo, int mid, int hi){
  5. int i=lo, j=mid+1;
  6. for (int k=lo; k<=hi; k++)
  7. aux[k]=a[k];
  8. for (int k=lo; k<=hi; k++){
  9. if (i>mid)
  10. a[k]=aux[j++];
  11. else if (j>hi)
  12. a[k]=aux[i++];
  13. else if (less(aux[j], aux[i]))
  14. a[k]=aux[j++];
  15. else
  16. a[k]=aux[i++];
  17. }
  18. }
  19. public static void sort(Comparable[] a){
  20. int N=a.length;
  21. aux=new Comparable[N];
  22. for (int sz=1; sz<N; sz=sz+sz)
  23. for (int lo=0; lo<N-sz; lo+=sz+sz)
  24. merge(a, lo, lo+sz-1, Math.min(lo+sz+sz-1, N-1));
  25. }
  26. }

随机快速排序

  1. /* 随机快速排序 RandomQuickSort */
  2. import edu.princeton.cs.algs4.StdRandom;
  3. public class RQ {
  4. private static int partition(Comparable[] a, int lo, int hi){
  5. int i=lo, j=hi+1;
  6. while (true){
  7. while (less(a[++i],a[lo]))
  8. if (i==hi)
  9. break;
  10. while (less(a[lo], a[--j]))
  11. if (j==lo)
  12. break;
  13. if (i>=j)
  14. break;
  15. exch(a, i, j);
  16. }
  17. exch(a, lo, j);
  18. return j;
  19. }
  20. public static void sort(Comparable[] a){
  21. StdRandom.shuffle(a);
  22. sort(a, 0, a.length-1);
  23. }
  24. }

Dijkstra 3-路划分快速排序

  1. /* Dijkstra 3-路划分快速排序 Quicksort with Dijkstra3-wayPartition */
  2. import edu.princeton.cs.algs4.StdRandom;
  3. public class QD3P {
  4. public static void sort(Comparable[] a){
  5. StdRandom.shuffle(a);
  6. sort(a, 0, a.length-1);
  7. }
  8. private static void sort(Comparable[] a, int lo, int hi){
  9. if (hi<=lo)
  10. return;
  11. int lt=lo, i=lo+1, gt=hi;
  12. Comparable v=a[lo];
  13. while (i<=gt){
  14. int cmp=a[i].compareTo(v);
  15. if (cmp<0)
  16. exch(a, lt++, i++);
  17. else if (cmp>0)
  18. exch(a, i, gt--);
  19. else
  20. i++;
  21. }
  22. sort(a, lo, lt-1);
  23. sort(a, gt+1, hi);
  24. }
  25. }

测试

  1. import edu.princeton.cs.algs4.*;
  2. public class Test {
  3. public static long t[] = new long[5];
  4. public static double time(String alg, Double[] a){
  5. long startns, endns;
  6. startns = System.nanoTime();
  7. if (alg.equals("IS")) IS.sort(a);
  8. else if (alg.equals("TDM")) TDM.sort(a);
  9. else if (alg.equals("BUM")) BUM.sort(a);
  10. else if (alg.equals("RQ")) RQ.sort(a);
  11. else if (alg.equals("QD3P")) QD3P.sort(a);
  12. endns = System.nanoTime();
  13. return (endns-startns)/1000;
  14. }
  15. public static void SORT(int i, String alg, int N, int T){
  16. long time = 0;
  17. Double[] a = new Double[N];
  18. for (int t = 0; t < T; t++){
  19. for (int j = 0; j < N; j++){
  20. a[j] = StdRandom.uniform();
  21. }
  22. time += time(alg, a);
  23. }
  24. t[i] = time / T;
  25. }
  26. public static void main(String[] args){
  27. String alg[] = {"IS", "TDM", "BUM", "RQ", "QD3P"};
  28. int N = 2000;
  29. int T = 10;
  30. for (int i=0; i<6; i++, N*=2){
  31. System.out.println("N = " +N+", T = "+T);
  32. System.out.println("\tRunning Time");
  33. for (int j = 0; j < 5; j++){
  34. SORT(j, alg[j], N, T);
  35. System.out.print(alg[j]+"\t");
  36. System.out.println(t[j]+"\tμs");
  37. }
  38. System.out.println();
  39. }
  40. }
  41. }

N为排序的规模,T为运行次数

设N=2000,当N翻倍时,测试结果为

  1. N = 2000, T = 10
  2. Running Time
  3. IS 4409 μs
  4. TDM 1299 μs
  5. BUM 1039 μs
  6. RQ 992 μs
  7. QD3P 963 μs
  8. N = 4000, T = 10
  9. Running Time
  10. IS 10654 μs
  11. TDM 4556 μs
  12. BUM 6111 μs
  13. RQ 3777 μs
  14. QD3P 6086 μs
  15. N = 8000, T = 10
  16. Running Time
  17. IS 41219 μs
  18. TDM 1835 μs
  19. BUM 1809 μs
  20. RQ 2542 μs
  21. QD3P 1935 μs
  22. N = 16000, T = 10
  23. Running Time
  24. IS 180119 μs
  25. TDM 3760 μs
  26. BUM 3715 μs
  27. RQ 3122 μs
  28. QD3P 4094 μs
  29. N = 32000, T = 10
  30. Running Time
  31. IS 810361 μs
  32. TDM 8284 μs
  33. BUM 8136 μs
  34. RQ 7053 μs
  35. QD3P 9210 μs
  36. N = 64000, T = 10
  37. Running Time
  38. IS 3478466 μs
  39. TDM 17989 μs
  40. BUM 17470 μs
  41. RQ 15105 μs
  42. QD3P 20712 μs
五种排序算法比较






































算法 时间复杂度(平均) 空间复杂度 稳定性
IS O(N^2) O(1) 稳定
TDM O(NlogN) O(N) 稳定
BUM O(NlogN) O(N) 稳定
RQ O(NlogN)  O(NlogN) 不稳定
QD3P O(NlogN) O(NlogN) 不稳定

发表评论

表情:
评论列表 (有 0 条评论,309人围观)

还没有评论,来说两句吧...

相关阅读