算法思想
同快排一样,归并排序同样利用了递归、分而治之的思想来突破O( n 2 n^2 n2)的限制。
”归并“的含义是将两个或两个以上的有序表组合成一个新的有序表。假定待排序表含有n个记录,则可将其视为n个有序的子表,每个子表的长度为1,然后两两归并,得到 [ n / 2 ] [n/2] [n/2]个长度为2或1的有序表;继续两两归并。。。如此重复,直到合并成一个长度为n的有序表为止,这样的排序方法称之为2路归并排序。
实现
Python实现:
def merge(lyst,copyBuffer,low,middle,high):
i1 = low
i2 = middle+1
for i in range(low,high+1):
if i1> middle:
copyBuffer[i] = lyst[i2]
i2 +=1
elif i2>high:
copyBuffer[i] = lyst[i1]
i1+=1
elif lyst[i1]<=lyst[i2]:
copyBuffer[i] = lyst[i1]
i1+=1
else:
copyBuffer[i] = lyst[i2]
i2+=1
for i in range(low,high+1):
lyst[i] = copyBuffer[i]
def mergeSortHelper(lyst,copyBuffer,low,high):
if low<high:
middle = (low+high)//2
mergeSortHelper(lyst,copyBuffer,low,middle)
mergeSortHelper(lyst,copyBuffer,middle+1,high)
merge(lyst,copyBuffer,low,middle,high)
def mergeSort(lyst: list)->None:
copyBuffer = [None]*(len(lyst))
mergeSortHelper(lyst,copyBuffer,0,len(lyst)-1)
lyst = [9,7,2,5,5,4,8,6,3,5]
mergeSort(lyst)
print(lyst)
C++实现:
#include <iostream>
#include <vector>
using namespace std;
void merge(vector<int>& lyst,vector<int>& copyBuffer,int low,int middle,int high){
int i1 = low;
int i2 = middle+1;
for(int i =low; i <= high;i++){
if(i1>middle){
copyBuffer[i] = lyst[i2];
i2++;
}
else if(i2>high){
copyBuffer[i] = lyst[i1];
i1++;
}
else if(lyst[i1]<=lyst[i2]){
copyBuffer[i]=lyst[i1];
i1++;
}
else{
copyBuffer[i]=lyst[i2];
i2++;
}
}
for(int i =low;i<=high;i++){
lyst[i]=copyBuffer[i];
}
}
void mergeSortHelper(vector<int>& lyst,vector<int>& copyBuffer,int low,int high){
if(low<high){
int middle = (low+high)/2;
mergeSortHelper(lyst,copyBuffer,low,middle);
mergeSortHelper(lyst,copyBuffer,middle+1,high);
merge(lyst,copyBuffer,low,middle,high);
}
}
vector<int> mergeSort(vector<int>& lyst){
vector<int> copyBuffer (lyst.size());
mergeSortHelper(lyst, copyBuffer, 0, lyst.size() - 1);
return lyst;
}
int main() {
vector<int> test = {9,4,6,7,2,8,2};
vector<int> res = mergeSort(test);
for (int i = 0; i < res.size(); i++){
cout << res[i] << " ";
}
return 0;
}
算法分析
时间: 每趟归并的时间复杂度为O(n),共需进行[
l
o
g
2
n
log_2n
log2n]趟归并,所以算法时间复杂度为O(n
l
o
g
2
n
log_2n
log2n)。
空间: Merge操作中,辅助空间刚好为n个单元,所以算法的空间复杂度为O(n)。
稳定性: 当merge的时候lyst[i1]<=lyst[i2]的时候复制lyst[i1],因此不会改变相同关键字记录的相对次序,所以2路归并排序是稳定的。
参考链接:https://cuijiahua.com/blog/2018/01/algorithm_7.html