归并排序算法原理:
相较于快速排序,归并排序主要应用于总体无序,但各子数列有序的数组排序,其算法思想为:将待排数列分为若干子数列,先使各子数列有序,然后将各子数列合并为一个有序数列,详细的归并算法流程为:
- 取待排序数组q[]的中间点为分界点x=mid=(l+r)/2 ,分成left区域和right区域,递归排序left数组和right数组;
- 使用双指针算法将上面两个子数组进行合并;其中双指针算法的详细合并流程为:
- 因为上面left数组和right数组的数都是按照从小到大排好序的数组,通过设置两个指针,使这两个指针分别指向这两个数组中的min值,比较这两个min值的大小,将较小者放入新创建的数组ans[]中用来记录答案,同时该指针向后移动一位;直到有一数组为空,并将另一非空数组中所有的数直接写入ans[]中 。
归并排序的代码实现:
//C++实现
#include<iostream>
using namespace std;
const int N = 1000010;
int n;
int q[N], ans[N]; //定义两个数组,q[N]用来存储待排序数组,ans[N]用来存储经归并排序的数组
void merge_order(int q[], int l; int r){ //q[]时用来排序的数组,l是数组的左边界,r是数组的右边界,闭区间
if(l <= r) return; //如果数组中没数或者只有一个数,则直接返回
int mid = (l + r) >> 1; //第一步,取中间点为分界点,
merge_order(q, l , mid), merge_order(q, mid +1, r); //递归排序mid的left数组和right数组
int k = 0, i = 1, j = mid +1; //用i和j两个指针分别指向两个数组中的min值
while(i <= mid && j <= r){ //比较两个min值的大小,并将其中的较小者放入新创建的数组ans[]中,直到有一数组为空,则终止循环
if(q[i] <= q[j]) ans[k++] = q[i++];
else ans[k++] = q[j++];
}
while(i <= mid) ans[k ++] = q[i ++]; //将不空数组中的所有数直接写入ans[]中
while(j <= r) ans[k++] = q[j++];
for(i = l, j = 0;i <= r;i ++, j ++) q[i] = ans[j]; //将ans[]中的数再传入q[l~r]中,注意i是从l开始的
}
int main(){
scanf("%d",&n);
for(int i = 0;i < n;i++) scanf("%d",&q[i]);
merge_order(q, 0, n - 1);
for(int i = 0;i < n;i++) printf("%d",q[i]);
return 0;
}