归并排序

  1. 确定分界点 mid = (left+ right)/2
  2. 递归排序 left right
  3. 归并—合二为一

例子:

#include <iostream>
#include <cstdio>
using namespace std;
const int N = 1000010;
static int q[N], tmp[N];
// tmp是额外的辅助数组,用来储存排好的数据
// l = 0 r = n-1
void mergesort(int q[], int l, int r)
{
    // mid是左半边的边界,mid+1是右半边的边界
    if (l >= r) return;
    int mid = l + r >> 1;    //定义分界点
    mergesort(q, l, mid);
    mergesort(q, mid + 1, r); //递归排左右边
    // k表示已经合并 了多少个数,i是指向数组左半边的起点指针
    // j 是指向数组右半边的起点指针
    int k = 0, i = l, j = mid + 1;
    while (i <= mid && j <= r)
    {
        if (q[i] <= q[j])
        {
            tmp[k++] = q[i++]; //如果数组左边的值小于右边的值,就把左边的值存入tmp数组中
        }
        else
        {
            tmp[k++] = q[j++]; //反之,如果数组左边的值大于右边的值,就把右边的值存入tmp数组中
        }
        
    }
    while (i <= mid)
    {
        tmp[k++] = q[i++];
    }; //如果左半边没有排完,就把左边剩下的值直接放入tmp数组中
    while (j <= r)
    {
        tmp[k++] = q[j++];
    };//如果右半边没有排完,就把右边剩下的值直接放入tmp数组中
    for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}
int main(void)
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        scanf("%d", &q[i]);
    }
    mergesort(q, 0, n - 1);
    for (int i = 0; i < n; i++)
    {
        printf("%d ", tmp[i]);
    }
    return 0;
}