十大經典排序演算法(五、歸併排序)
阿新 • • 發佈:2020-12-29
歸併排序(Merge sort)是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。
作為一種典型的分而治之思想的演算法應用,歸併排序的實現由兩種方法:
- 自上而下的遞迴(所有遞迴的方法都可以用迭代重寫,所以就有了第 2 種方法);
- 自下而上的迭代;
和選擇排序一樣,歸併排序的效能不受輸入資料的影響,但表現比選擇排序好的多,因為始終都是 O(nlogn) 的時間複雜度。代價是需要額外的記憶體空間。
演算法步驟
-
申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合併後的序列;
-
設定兩個指標,最初位置分別為兩個已經排序序列的起始位置;
-
比較兩個指標所指向的元素,選擇相對小的元素放入到合併空間,並移動指標到下一位置;
-
重複步驟 3 直到某一指標達到序列尾;
-
將另一序列剩下的所有元素直接複製到合併序列尾。
JavaScript
1 function mergeSort(arr) { // 採用自上而下的遞迴方法 2 var len = arr.length; 3 if(len < 2) { 4 return arr; 5 } 6 var middle = Math.floor(len / 2), 7 left = arr.slice(0, middle),8 right = arr.slice(middle); 9 return merge(mergeSort(left), mergeSort(right)); 10 } 11 12 function merge(left, right) 13 { 14 var result = []; 15 16 while (left.length && right.length) { 17 if (left[0] <= right[0]) { 18 result.push(left.shift());19 } else { 20 result.push(right.shift()); 21 } 22 } 23 24 while (left.length) 25 result.push(left.shift()); 26 27 while (right.length) 28 result.push(right.shift()); 29 30 return result; 31 }
Python
1 def mergeSort(arr): 2 import math 3 if(len(arr)<2): 4 return arr 5 middle = math.floor(len(arr)/2) 6 left, right = arr[0:middle], arr[middle:] 7 return merge(mergeSort(left), mergeSort(right)) 8 9 def merge(left,right): 10 result = [] 11 while left and right: 12 if left[0] <= right[0]: 13 result.append(left.pop(0)) 14 else: 15 result.append(right.pop(0)); 16 while left: 17 result.append(left.pop(0)) 18 while right: 19 result.append(right.pop(0)); 20 return result
C語言
1 void merge_sort_recursive(int arr[], int reg[], int start, int end) { 2 if (start >= end) 3 return; 4 int len = end - start, mid = (len >> 1) + start; 5 int start1 = start, end1 = mid; 6 int start2 = mid + 1, end2 = end; 7 merge_sort_recursive(arr, reg, start1, end1); 8 merge_sort_recursive(arr, reg, start2, end2); 9 int k = start; 10 while (start1 <= end1 && start2 <= end2) 11 reg[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++]; 12 while (start1 <= end1) 13 reg[k++] = arr[start1++]; 14 while (start2 <= end2) 15 reg[k++] = arr[start2++]; 16 for (k = start; k <= end; k++) 17 arr[k] = reg[k]; 18 } 19 20 void merge_sort(int arr[], const int len) { 21 int reg[len]; 22 merge_sort_recursive(arr, reg, 0, len - 1); 23 }
C++
1 void Merge(vector<int> &Array, int front, int mid, int end) { 2 vector<int> LeftSubArray(Array.begin() + front, Array.begin() + mid + 1); 3 vector<int> RightSubArray(Array.begin() + mid + 1, Array.begin() + end + 1); 4 int idxLeft = 0, idxRight = 0; 5 LeftSubArray.insert(LeftSubArray.end(), numeric_limits<int>::max()); 6 RightSubArray.insert(RightSubArray.end(), numeric_limits<int>::max()); 7 // Pick min of LeftSubArray[idxLeft] and RightSubArray[idxRight], and put into Array[i] 8 for (int i = front; i <= end; i++) { 9 if (LeftSubArray[idxLeft] < RightSubArray[idxRight]) { 10 Array[i] = LeftSubArray[idxLeft]; 11 idxLeft++; 12 } else { 13 Array[i] = RightSubArray[idxRight]; 14 idxRight++; 15 } 16 } 17 } 18 19 void MergeSort(vector<int> &Array, int front, int end) { 20 if (front >= end) 21 return; 22 int mid = (front + end) / 2; 23 MergeSort(Array, front, mid); 24 MergeSort(Array, mid + 1, end); 25 Merge(Array, front, mid, end); 26 }