1. 程式人生 > >分治算法-歸並排序、快速排序

分治算法-歸並排序、快速排序

tle lin 其中 有序 歸並 != 元素 2個 只需要

分治算法:把一個任務,分成形式和原任務相同,但規模更小的幾個部分任務(通常是兩個部分),分別完成,或只需要選一部完成。然後再處理完成後的這一個或幾個部分的結果,實現整個任務的完成。

分治的典型應用:歸並排序、快速排序


歸並排序動態圖:

技術分享圖片

 1 package com.inbreak.cnblogs.sort;
 2 
 3 import com.inbreak.cnblogs.Helper;
 4 
 5 /**
 6  * 歸並排序:
 7  * 分別前一半、後一半排序
 8  * 將前半部分、後半部分歸並到一個有序數組,再拷貝到原數組中。
 9  *
10  * @author inbreak
11 * @create 2018-07-19 12 */ 13 public class MergeSort { 14 15 public static void main(int[] a, int size) { 16 Helper.printArray(a); 17 int[] tmp = new int[size]; 18 mergeSort(a, 0, size - 1, tmp); 19 Helper.printArray(a); 20 } 21 22 public static void mergeSort(int
[] a, int s, int e, int[] tmp) { 23 if (s < e) { 24 int m = (s + e) / 2; 25 mergeSort(a, s, m, tmp); 26 mergeSort(a, m + 1, e, tmp); 27 merge(a, s, m, e, tmp); 28 } 29 } 30 31 public static void merge(int[] a, int s, int m, int
e, int[] tmp) { 32 //將s~m和m+1~e合並到tmp數組 33 int pt = 0; 34 int pi = s; 35 int pj = m + 1; 36 //先把左半邊或者右半邊的拷貝完 37 while (pi <= m && pj <= e) { 38 if (a[pi] < a[pj]) { 39 tmp[pt++] = a[pi++]; 40 } else { 41 tmp[pt++] = a[pj++]; 42 } 43 } 44 //上面的while循環結束,其中的一半全部復制完成,下面的2個while循環只有一個會走 45 //這趟歸並的左半部分 46 while (pi <= m) { 47 tmp[pt++] = a[pi++]; 48 } 49 //這趟歸並的右半部分 50 while (pj <= e) { 51 tmp[pt++] = a[pj++]; 52 } 53 //將tmp復制到原數組 54 for (int i = 0; i < e - s + 1; i++) { 55 a[s + i] = tmp[i]; 56 } 57 } 58 59 }


快速排序:

技術分享圖片

 1 package com.inbreak.cnblogs.sort;
 2 
 3 import com.inbreak.cnblogs.Helper;
 4 
 5 /**
 6  * 快速排序:
 7  * 1)設k=a[0], 將k挪到適當位置,使得比k小的元素都在k左邊,比k大的元素都在k右邊,和k相等的,不關心在k左右出現均可 (O(n)時間完成)
 8  * 2) 把k左邊的部分快速排序
 9  * 3) 把k右邊的部分快速排序
10  *
11  * @author inbreak
12  * @create 2018-07-19
13  */
14 public class QuickSort {
15 
16     public static void main(int[] a, int size) {
17         Helper.printArray(a);
18         quickSort(a, 0, size - 1);
19         Helper.printArray(a);
20     }
21 
22     public static void quickSort(int[] a, int s, int e) {
23         if (s >= e) {
24             return;
25         }
26         int k = a[s];
27         int pi = s;
28         int pj = e;
29         //while循環結束 pi == pj 後的這個就是a[pi] == k,確定這個左邊數都比k小,右邊都比k大
30         while (pi != pj) {
31             //先從右指針pj往左遍歷
32             while (pj > pi && a[pj] >= k) {
33                 pj--;
34             }
35             //pj循環結束後 pj中的值a[pj] < k,此時交換內容,因為默認第一個就是k也就是a[pi]
36             Helper.swap(a, pi, pj);
37             //從左指針pi往右遍歷
38             while (pj > pi && a[pi] <= k) {
39                 pi++;
40             }
41             //交換
42             Helper.swap(a, pi, pj);
43         }
44         //針對左、右半部分的遞歸
45         quickSort(a, s, pi - 1);
46         quickSort(a, pi + 1, e);
47 
48     }
49 }

分治算法-歸並排序、快速排序