算法理解:
一个数组长度为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; }