归并排序(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 }