题目描述
给定你一个长度为n的整数数列。
请你使用归并排序对这个数列按照从小到大进行排序。
并将排好序的数列按顺序输出。
输入格式
输入共两行,第一行包含整数 n。
第二行包含 n 个整数(所有整数均在1~109范围内),表示整个数列。
输出格式
输出共一行,包含 n 个整数,表示排好序的数列。
数据范围
1≤n≤100000
输入样例:
5
3 1 2 4 5
输出样例:
1 2 3 4 5
思路
1.确定分界点 mid=(l+r)/2
2.先递归排序两边
3.归并,将两个合成一个※
双指针算法:
(1).用两个指针分别指向两个已经排好序的数组的开始
(2).开一个新的数组res用来记录结
(3).因为每一个数组是由小到大排好序的,所以每一个指针指向的数,就分别是每一个序列最小的值
(4).将这两个指针比较大小,较小的那个就是两个序列总共的最小值,所以将这个数存入res数组
(5).将这个指针后移一位,因为挪完之后依然保持这个性质(分别为两个序列的最小值),所以再进行比较大小,存入比
较小的那个数
(6).用循环执行第4,5步,直到有一个指针走到终点为止
(7).如果另一个序列没有完全遍历完,那么直接将后面的部分存入res
代码$O(nlogn)$
#include<iostream>
using namespace std;
int n;
int q[100010],tmp[100010];
void merge_sort(int q[],int l,int r)
{
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;
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(int i=l,k=0;i<=r;i++,k++)
{
q[i]=tmp[k];//复制
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>q[i];
}
merge_sort(q,0,n-1);
for(int i=0;i<n;i++)
{
cout<<q[i]<<' ';
}
return 0;
}