一、步骤
1.确定分界点:取区间的中点
2.递归排序:以中点为分界点的左右两段分别排序
3.归并:合二为一
二、举例
左半段:1 3 5 7 9
右半段:2 4 5 8 10
res:1 2 3 4 5 5 7 8
归并排序具有稳定性,快排不稳定
1.如何定义稳定性呢?
合并过程中我们可以保证如果两个当前元素相等时,我们把处在前面的序列的元素保存在结果序列的前面,这样就保证了稳定性(例如举例中的5,一般来说先取左半段的5再取右半段的5),
2.快排如何变稳定?
存成PII,即存a[i]和下标i,从而保证每个元素都不相同
三、时间复杂度
O(n):左指针扫描左半段,右指针扫描右半段,因此每个元素仅会被扫描一次
四、代码
#include<iostream>
using namespace std;
const int N = 1000010;
int n;
int q[N], tmp[N];
void merge_sort(int q[], int l, int r)
{
if (l >= r)return;
int mid = l + r >> 1;//这里相当于(l+r)/2 步骤一
merge_sort(q, l, mid), merge_sort(q, mid + 1, r); 步骤二
步骤三
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r)
if (q[i] <= q[j])tmp[k++] = q[i++];
else tmp[k++] = q[j++];
while (i <= mid)tmp[k++] = q[i++];
while (j <= r)tmp[k++] = q[j++];
for (i = l, j = 0; i <= r; i++, j++)q[i] = tmp[j];
}
int main()
{
scanf_s("%d", &n);
for (int i = 0; i < n; i++)scanf_s("%d", &q[i]);
merge_sort(q, 0, n - 1);
for (int i = 0; i < n; i++)printf("%d ", q[i]);
return 0;
}