一、中心思想:分治
- 以中间点为界:mid=(l+r)/2
- 递归排序分界点左边和右边
- 归并——合二为一
二、核心内容:合二为一
- 分界点左边从小到大排序:数组a,分界点右边从小到大排序:数组b,答案数组ans
- 指针i,j分别指向a、b的第一个数,如果i指向的数比j指向的数小,则将i指向的数移至ans,指针i向后移动,j指向的数比i指向的数小时同理。若i先到达末尾,则j及以后的数全部移至ans,若j先达到末尾同理
三、上代码!
void merge_sort(int q[], int l, int r)
{
int tmp[1000010];
if (l >= r)
return;
int mid = (l + r) / 2;
merge_sort(q, l, mid);
merge_sort(q, mid + 1, r); //递归排序左半边和右半边
int k = 0, i = l, j = mid + 1; //k用来标记存了多少答案
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
q[i] = tmp[j];
}
四、配套练习
AcWing787https://www.acwing.com/problem/content/789/AcWing788
https://www.acwing.com/problem/content/790/