归并排序(分治):
思路:
1、确定分界点(
mid=(l+r)/2
)
2、递归排序left
、right
3、归并,合二为一
(将排好的序列组合起来)
算法:
1、首先以分界点为界限,将列表分成两段
2、以此方式递归,直至每个列表里只有一个数(此时认为该列表为有序)
3、然后在递归回退时进行归并(重难点)
图解:
合并方式(图解):
1、定义两个指针i,j
,用于指向两个有序序列
2、比较i,j
对应的元素,小的先进列表
3、当i
或j
指向的序列为空时,直接将i
或j
指向的序列放入列表中
代码示例;
#include<iostream>
using namespace std;
const int N = 1000010;
int n;
int ary[N],tem[N];
void merge_sort(int ary[],int l,int r){
if(l >= r) return ;
int mid = l + r >> 1;
merge_sort(ary,l,mid),merge_sort(ary,mid+1,r);
int k = 0, i = l , j = mid+1;
while(i <= mid && j <= r){
if(ary[i] <= ary[j]) tem[k++] = ary[i++];//判断两个有序序列的值,较小的放入列表中
else tem[k++] = ary[j++];
}
while(i <= mid) tem[k++] = ary[i++];//当一个序列为空时,直接将另一个序列放入列表中
while(j <= r) tem[k++] = ary[j++];
for(int i = l,j = 0;i <= r;i++,j++) ary[i] = tem[j];//将合并的元素放入原列表中
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d", &ary[i]);
merge_sort(ary,0,n-1);
for(int i=0;i<n;i++) printf("%d ",ary[i]);
return 0;
}
时间复杂度:O(nlogn)
空间复杂度: O(n)
如果数据量过大,内存使用过大,不推荐使用归并排序。