11:归并排序(重要)

11:归并排序(重要)

  时间复杂度:O(N * logN)

 

 与O(N^2)排序算法的比较:

  1、O(N^2)大量浪费了比较行为。

  2、归并排序,当左组和右组的排序排好后,在merge的时候,

     左组数之间是没有比较的。

     是左组数与右组数的比较。

       每一次比较行为都变成了结果并且再传递下去。

 

  算法流程:

  f(arr, L, R)

  1、求中点M

  2、左部分有序f(arr, L, M);

  3、右部分有序f(arr, M+1, R);

  4、想办法让左右两部分合并有序,也就是merge过程;

  

  从Master公式的角度来看,时间复杂度:分为左右等规模的2部分

          T(N) = 2 * T(N/2) + O(N)   

      a = 2,  b = 2,  d = 1

         O(N * logN)

 

 

  递归写的Merge

 1 // 递归方法实现
 2     public static void mergeSort1(int[] arr) {
 3         if (arr == null || arr.length < 2) {
 4             return;
 5         }
 6         process(arr, 0, arr.length - 1);
 7     }
 8 
 9     // 请把arr[L..R]排有序
10     // l...r N
11     // T(N) = 2 * T(N / 2) + O(N)
12     // O(N * logN)
13     public static void process(int[] arr, int L, int R) {
14         if (L == R) { // base case
15             return;
16         }
17         int mid = L + ((R - L) >> 1);
18         process(arr, L, mid);
19         process(arr, mid + 1, R);
20         merge(arr, L, mid, R);
21     }

 

 1     public static void merge(int[] arr, int L, int M, int R) {
 2         int[] help = new int[R - L + 1];
 3         int i = 0;
 4         int p1 = L;
 5         int p2 = M + 1;
 6         while (p1 <= M && p2 <= R) {
 7             help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
 8         }
 9         // 要么p1越界了,要么p2越界了
10         while (p1 <= M) {
11             help[i++] = arr[p1++];
12         }
13         while (p2 <= R) {
14             help[i++] = arr[p2++];
15         }
16         for (i = 0; i < help.length; i++) {
17             arr[L + i] = help[i];
18         }
19     }

 

O(N2)的排序,大量浪费比较行为。

而O(N * logN)merge过程:

  左组的比较过程,固定化

  右组的比较过程,固定化,

在merge的时候,左组和左组,右组和右组内部是没有比较的,

是左组某个指针对右组某个指针的比较,所以比较行为每次都变成结果再传递。

 

posted @ 2022-05-10 16:25  yzmarcus  阅读(18)  评论(0编辑  收藏  举报