算法理解:
一个数组长度为n,他的前m个元素是升序的,后n-m个元素升序的,怎么使整个数组变成一个升序数组?
如n=6,m=3
| 1 | 3 | 5 | 2 | 4 | 6 |
| 1 | 2 | 3 | 4 | 5 | 6 |
排序前
排序后
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <cmath>
#include <queue>
using namespace std;
const int maxn=1e5+1;
int A[maxn];
int T[maxn];//辅助数组。
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
scanf("%d",&A[i]);
}
int p=0,q=m,i=0;
while(p<m||q<n){
if(q>=n||(p<m&&A[p]<=A[q]))T[i++]=A[p++];
else T[i++]=A[q++];
}
for(int i=0;i<n;i++){
A[i]=T[i];
}
for(int i=0;i<n;i++){
printf("%d ",A[i]);
}
printf("\n");
return 0;
}
归并排序采用了分治的想法,一个数组如果左边有序,右边有序则进行合并,如果左边无序递归处理,同理右边也递归处理。
由于归并排序每次使严格二分,所以时间复杂度是O(nlogn)
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <cmath>
#include <queue>
using namespace std;
const int maxn=1e5+1;
int n;
int A[maxn];
int T[maxn];//辅助数组。
void merge_sort(int *A,int x,int y,int *T){
if(y-x>1){
int m=x+(y-x)/2;
int p=x,q=m,i=x;
merge_sort(A,x,m,T);
merge_sort(A,m,y,T);
while(p<m||q<y){
if(q>=y||(p<m&&A[p]<=A[q]))T[i++]=A[p++];
else T[i++]=A[q++];
}
for(int i=x;i<y;i++){
A[i]=T[i];
}
}
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&A[i]);
}
merge_sort(A,0,n,T);
for(int i=0;i<n;i++){
printf("%d ",A[i]);
}printf("\n");
return 0;
}
例一:求逆序对对数
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <cmath>
#include <queue>
using namespace std;
const int maxn=1e5+1;
int n;
int A[maxn];
int T[maxn];//辅助数组。
int cnt;
void merge_sort(int *A,int x,int y,int *T){
if(y-x>1){
int m=x+(y-x)/2;
int p=x,q=m,i=x;
merge_sort(A,x,m,T);
merge_sort(A,m,y,T);
while(p<m||q<y){
if(q>=y||(p<m&&A[p]<=A[q]))T[i++]=A[p++];
else T[i++]=A[q++],cnt+=m-p;
}
for(int i=x;i<y;i++){
A[i]=T[i];
}
}
}
int main(){
scanf("%d",&n);
cnt=0;
for(int i=0;i<n;i++){
scanf("%d",&A[i]);
}
merge_sort(A,0,n,T);
printf("%d\n",cnt);
return 0;
}