分治算法-歸並排序、快速排序
阿新 • • 發佈:2018-07-20
tle lin 其中 有序 歸並 != 元素 2個 只需要
分治算法:把一個任務,分成形式和原任務相同,但規模更小的幾個部分任務(通常是兩個部分),分別完成,或只需要選一部完成。然後再處理完成後的這一個或幾個部分的結果,實現整個任務的完成。
分治的典型應用:歸並排序、快速排序
歸並排序動態圖:
1 package com.inbreak.cnblogs.sort; 2 3 import com.inbreak.cnblogs.Helper; 4 5 /** 6 * 歸並排序: 7 * 分別前一半、後一半排序 8 * 將前半部分、後半部分歸並到一個有序數組,再拷貝到原數組中。 9 * 10 * @author inbreak11 * @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, inte, 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 }
分治算法-歸並排序、快速排序