归并排序:顾名思义,就是不断的将两个有序的子序列归并成一个大的序列。所以核心操作就是有序子列的归并,如果有两个子列,共有N个元素,那么归并的时间复杂度是T(N)=O(N)。有了归并算法,我们采用易于理解的方式,分而治之的思想,也就是不断地递归将大的序列划分成小的序列,当序列只有一个元素的时候(自身有序),就是递归终止条件。
//归并排序-递归实现
//O(nlogn) O(n)
#include<bits/stdc++.h>
using namespace std;
void merge(vector<int>& arr,vector<int>& aux,int L,int R,int RightEnd) {
//将有序的A[L]-A[R-1]和A[R]-A[RightEnd]归并成一个有序序列
int LeftEnd = R - 1; //左边终点位置
int i = L; //有序序列起始位置
int count = RightEnd - L + 1; //本次归并元素总个数
while (L<=LeftEnd && R<=RightEnd) {
if (arr[L] <= arr[R])
aux[i++] = arr[L++]; //将左边元素复制到aux
else
aux[i++] = arr[R++]; //将右边元素复制到aux
}
while (L <= LeftEnd)
aux[i++] = arr[L++]; //直接复制左边剩下的
while (R <= RightEnd)
aux[i++] = arr[R++]; //直接复制右边剩下的
for (i = 0; i < count; i++,RightEnd--) //将有序序列aux复制回arr
arr[RightEnd] = aux[RightEnd];
}
void MSort(vector<int>& arr,vector<int>& aux,int L,int RightEnd) {
int mid = 0;
if(L<RightEnd) {
mid = L + (RightEnd - L) / 2;
MSort(arr,aux,L,mid); //递归解决左边
MSort(arr,aux,mid+1,RightEnd); //递归解决右边
merge(arr,aux,L,mid+1,RightEnd); //合并两端有序序列
}
}
void mergeSort(vector<int>& arr) { //归并排序对外接口,使得排序接口一致
int n = arr.size();
vector<int> aux(n,0);
MSort(arr,aux,0,n-1);
}
int main() {
vector<int> arr = { 8,6,10,7,9,4,3,2,5,1 };
mergeSort(arr);
for (auto x : arr) {
cout << x << " ";
}
cout << endl;
system("pause");
return 0;
}
1 2 3 4 5 6 7 8 9 10
请按任意键继续. . .
性能分析:分而治之,T(N)=T(N/2)+T(N/2)+O(N) → T(N)=O(N logN);merge过程严格保证序列1小于等于序列2,使之稳定。
- 时间复杂度:O(N logN)
- 空间复杂度:O(N)
- 稳定性:稳定
归并排序非递归算法:比递归算法更快速,也是稳定的
//归并排序-循环实现
//O(nlogn) O(n)
#include<bits/stdc++.h>
using namespace std;
void merge(vector<int>& arr,vector<int>& aux,int L,int R,int RightEnd) {
//将有序的A[L]-A[R-1]和A[R]-A[RightEnd]归并成一个有序序列
int LeftEnd = R - 1; //左边终点位置
int i = L; //有序序列起始位置
int count = RightEnd - L + 1; //本次归并元素总个数
while (L<=LeftEnd && R<=RightEnd) {
if (arr[L] <= arr[R])
aux[i++] = arr[L++]; //将左边元素复制到aux
else
aux[i++] = arr[R++]; //将右边元素复制到aux
}
while (L <= LeftEnd)
aux[i++] = arr[L++]; //直接复制左边剩下的
while (R <= RightEnd)
aux[i++] = arr[R++]; //直接复制右边剩下的
//for (i = 0; i < count; i++,RightEnd--) //将有序序列aux复制回arr
// arr[RightEnd] = aux[RightEnd]; //因为两次mergePass操作使得无需这一步
}
void mergePass(vector<int>& arr,vector<int>& aux,int n,int length) {
int i, j;
for (i = 0; i <= n-2*length; i+=2*length) {
merge(arr,aux,i,i+length,i+2*length-1);
}
if (i + length < n) //归并最后2个子列
merge(arr, aux, i, i + length, n - 1);
else //最后只剩一个
for (j = i; j < n; j++) aux[j] = arr[j];
}
void mergeSort(vector<int>& arr) {
int n = arr.size();
vector<int> aux(n,0);
int length = 1;
while (length<n) {
mergePass(arr,aux,n,length); //arr-->aux
length *= 2;
mergePass(aux,arr,n,length); //aux-->arr
length *= 2;
}
}
int main() {
vector<int> arr = { 8,6,10,7,9,4,3,2,5,1 };
mergeSort(arr);
for (auto x : arr) {
cout << x << " ";
}
cout << endl;
system("pause");
return 0;
}
1 2 3 4 5 6 7 8 9 10
请按任意键继续. . .