步骤
- 假设我们要对数组a[1…n]排序。初始化左端点l=1,右端点r=n。
- 下面假设我们对l到r子段内的数字进行划分。取l和r的中点mid,将l到mid的元素看成第一个子段的部分,将mid+1到r的部分看成第二个子段的部分。两边分别进入下一层,重复调用上面的过程。直到子段长度为1,返回上一层。
- 当算法阶段返回到当前层时,使用归并操作合并下一层的左右两个有序序列,形成本层的有序序列,继续返回上一层。
- 当整个过程结束以后,整个序列排序完毕。
.
稳定排序
依然依赖于实现的细节, 如有两个相等的元素在相邻的两个子序列中,需要保证在合并两个子序列时保证其相对位置不变。 在本实现中,要求 ass[i] <= ass[j]
语句带等号。
合并的实现
合并两个子序列需要一个辅助数组,在本实现中是数组 ass[100005] 。
复杂度
时间复杂度为
O
(
n
log
n
)
O(n\log n)
O(nlogn)
由于要借助辅助数组,所以空间复杂度为O(n)。
代码
#include <bits/stdc++.h>
using namespace std;
int arr[100005], ass[100005];
void merge_sort (int l, int r){
if (l >= r) return;
int mid = (l + r) / 2;
merge_sort (l, mid);
merge_sort (mid + 1, r);
//合并
for (int i = l; i <= r; i++){
ass[i] = arr[i];
}
int i = l, j = mid + 1;
for (int k = l; k <= r; k++){
if (j > r || i <= mid && ass[i] <= ass[j]){
arr[k] = ass[i++];
}else{
arr[k] = ass[j++];
}
}
}
int main(){
int n;
cin >> n;
for (int i = 0; i < n; i++){
cin >> arr[i];
}
merge_sort (0, n - 1);
for (int i = 0; i < n; i++){
printf ("%d ", arr[i]);
}
return 0;
}
参考:青舟智学