合並排序也可以用打牌的過程來說明,假設桌面上朝上放着兩摞已經排好序的牌,現在要將這兩摞已排好序的牌合成一摞,首先,取兩摞中位於最上面的兩張中最小的一張並將其加入到新的一摞中,然后接着從兩摞中再取一張最小的加入到新的一摞中,因為第二張,肯定比第一張要大,因此要加入到第一張的后面才行。
從上面可以看出,合並排序是利用分治法進行排序的算法,直觀地操作如下:
分解:將n個元素分成各含n/2個元素的子序列;
解決:用合並排序法對兩個子序列進行遞歸地排序;
合並:合並兩個已排序的子序列以得到排序結果。
我就不寫偽代碼了,直接用Java將其實現的代碼如下:
1 /** 2 * 合並兩個排好的序列 3 * @param A 4 * int數組 5 * @param p 6 * 起始位置 7 * @param q 8 * 中間位置 9 * @param r 10 * 終止位置 11 * @param isInc 12 * isInc 是否升序,true為升序,false為降序 13 */ 14 private void merge(int[] A, int p, int q, int r, boolean isInc) { 15 int nLeft = q - p + 1; 16 int nRight = r - q; 17 int[] left = new int[nLeft]; 18 int[] right = new int[nRight]; 19 int i = 0, j = 0, k = 0; 20 for (i = 0; i < nLeft; i++) { 21 left[i] = A[p + i]; 22 } 23 for (j = 0; j < nRight; j++) { 24 right[j] = A[q + j + 1]; 25 } 26 i = 0; 27 j = 0; 28 for (k = p; k <= r; k++) { 29 if (isInc ^ (left[i] <= right[j])) { 30 A[k] = right[j]; 31 j++; 32 } else { 33 A[k] = left[i]; 34 i++; 35 } 36 37 if (i == nLeft) { 38 k++; 39 for (; j < nRight; j++) { 40 A[k] = right[j]; 41 k++; 42 } 43 } 44 if (j == nRight) { 45 k++; 46 for (; i < nLeft; i++) { 47 A[k] = left[i]; 48 k++; 49 } 50 } 51 } 52 }
1 /** 2 * 合並排序 3 * @param A 4 * int數組 5 * @param p 6 * 起始位置 7 * @param r 8 * 終止位置 9 * @param isInc 10 * 是否升序,true為升序,false為降序 11 */ 12 private void mergeSort(int[] A, int p, int r, boolean isInc) { 13 int q = 0; 14 if (p < r) { 15 q = (p + r) / 2; 16 mergeSort(A, p, q, isInc); 17 mergeSort(A, q + 1, r, isInc); 18 merge(A, p, q, r, isInc); 19 } 20 }
合並排序不是原地進行排序的,時間復雜度為O(nlgn)。