归并排序理解
归并排序的主要操作如下:
(1)分解。把初始序列分成长度相同的左、右两个子序列,然后把每个子序列再分成更小的两个子序列,直到子序列只包含一个数。这个过程用递归实现。
(2)求解子问题,对子序列排序。最底层的子序列只包含一个数,其实不用排序。
(3)合并。归并两个有序的子序列,这是归并排序的主要操作。比如下面举例,把a[ ]分成两个子序列,比较后存进b[ ],假设两个子序列已经分别排好序。
过程如下(有点丑…将就一下):
只要有一个子序列结束,就可以把另一个子序列后面的都放进去,因为是排好序的
归并排序的时间复杂度:对n个数进行排序:
- 需要log2(n)趟归并。
- 在每一趟归并中有很多次合并操作。共需O(n)次比较。所以时间复杂度为
归并排序模板
输入n个数,对n个数进行排序。
#include<iostream>
using namespace std;
const int N=1e6 + 10;
int n;
int q[N],temp[N];
void merge(int q[],int l,int r)
{
if(l >= r) return;//满足条件不再往下进行
int mid = (l + r)/2;
merge(q,l,mid),merge(q,mid+1,r);//左右分开递归
int k=0,i=l,j=mid+1;//k表示temp里个数,i指向左子序开头,j指向右子序开头
while(i <= mid && j<= r)
if(q[i] <= q[j]) temp[k++]=q[i++];
else temp[k++]=q[j++];
while(i <= mid) temp[k++ ]=q[i++ ];//若左半边没循环完 全部拿出来
while(j <= r) temp[k++ ] = q[j++ ];//若右半边没循环完 全部拿出来
for(i = l,j = 0;i <= r;i++,j++) q[i]=temp[j];//把temp排好的赋给q[]
}
int main()
{
cin>>n;
for(int i = 0;i < n; i++) cin>>q[i];
merge(q,0,n-1);//从0~n-1
for(int i = 0;i < n; i++) cout<<q[i]<<" ";
return 0;
}