昨晚本来在做化学...结果闲的没事开始读买来就没看过的《算法导论》...就这个专注度,看来期末又要挂科了
连读44页的酸爽...简单的看了一下算法时间复杂度的分析,毕竟不是很重要...(不只是我开玩笑的只是我不想看而已),O(nlgn)
所以莫名其妙地搞懂了归并排序和逆序对的计算...emmm果然还是圣经厉害...讲得超详细的
根据书上讲的写出了代码:【归并排序】
1 #include <iostream> 2 using namespace std; 3 const int MAXN = 2<<20; 4 int A[100]; 5 int B[51],C[51]; 6 void print(int*,int); 7 void MERGE(int* a,int l,int mid,int r) 8 { 9 int n1=mid-l+1; 10 int n2=r-mid; 11 for(int i=1;i<=n1;i++)B[i]=A[l+i-1]; 12 print(B,n1); 13 for(int i=1;i<=n2;i++)C[i]=A[mid+i]; 14 print(C,n2); 15 B[n1+1]=MAXN; 16 C[n2+1]=MAXN; 17 int i=1,j=1; 18 for(int k=l;k<=r;k++){ 19 if(B[i]<=C[j]){ 20 A[k]=B[i]; 21 i++; 22 } 23 else{ 24 A[k]=C[j]; 25 j++; 26 } 27 } 28 } 29 void Merge_sort(int *a,int l,int r) 30 { 31 if(l>=r)return; 32 int mid=(l+r)/2; 33 Merge_sort(a,l,mid); 34 Merge_sort(a,mid+1,r); 35 MERGE(a,l,mid,r); 36 } 37 void print(int *a,int n) 38 { 39 for(int i=1;i<=n;i++){ 40 if(i-1)cout<<" "; 41 cout<<a[i]; 42 } 43 cout<<endl; 44 } 45 int main() 46 { 47 cout<<MAXN<<endl; 48 int n;cin>>n; 49 for(int i=1;i<=n;i++){ 50 cin>>A[i]; 51 } 52 Merge_sort(A,1,n); 53 print(A,n); 54 return 0; 55 }
因为是测试用的,数组就没有开太大,这里数组A是整个序列,B是左序列,C是右序列
然后就是常规的一套,只不过把分治的部分单独写了个MERGE函数而已
还看了书上的习题2.4说实话一开始没做出来 然后上网下载了个答案...
读了之后感觉不错,稍加更改还写出来了:【逆序对】
1 #include <iostream> 2 using namespace std; 3 const int MAXN = 2<<20; 4 int A[100],cnt=0; 5 int B[51],C[51]; 6 void print(int*,int); 7 void MERGE(int* a,int l,int mid,int r) 8 { 9 int n1=mid-l+1; 10 int n2=r-mid; 11 for(int i=1;i<=n1;i++)B[i]=A[l+i-1]; 12 //print(B,n1); 13 for(int i=1;i<=n2;i++)C[i]=A[mid+i]; 14 //print(C,n2); 15 B[n1+1]=MAXN; 16 C[n2+1]=MAXN; 17 int i=1,j=1; 18 //int cnt=0; 19 bool counter=false; 20 for(int k=l;k<=r;k++){ 21 if(counter==false&&C[j]<B[i]){ 22 cnt=cnt+n1-i+1; 23 counter=true; 24 } 25 if(B[i]<=C[j]){ 26 A[k]=B[i]; 27 i++; 28 } 29 else{ 30 A[k]=C[j]; 31 j++; 32 counter=false; 33 } 34 } 35 //return cnt; 36 } 37 void Merge_sort(int *a,int l,int r) 38 { 39 if(l>=r)return; 40 int mid=(l+r)/2; 41 Merge_sort(a,l,mid); 42 Merge_sort(a,mid+1,r); 43 MERGE(a,l,mid,r); 44 } 45 void print(int *a,int n) 46 { 47 for(int i=1;i<=n;i++){ 48 if(i-1)cout<<" "; 49 cout<<a[i]; 50 } 51 cout<<endl; 52 } 53 int main() 54 { 55 cout<<MAXN<<endl; 56 int n;cin>>n; 57 for(int i=1;i<=n;i++){ 58 cin>>A[i]; 59 } 60 Merge_sort(A,1,n); 61 print(A,n); 62 cout<<cnt<<endl; 63 return 0; 64 }
是的确实非常的懒就是把归并排序给改了改而已,连变量名也没改,甚至直接用了全局变量...
其实分治部分主要就是设置一个bool的counter来判断是否正在数包括C[j]的逆序对,当这个C[j]是第一次出现,且B中比C[j]大的值也是第一次出现时,就把counter还原为false,并自增cnt,这样就数出了一个逆序对。
然后就是合并,很简单的Merge_sort(),由于这个逆序对算法只是在归并排序的基础上进行了一个自增操作,所以复杂度还是O(nlgn)。【大概?
算法导论的伪代码答案就不放出来了,因为是英文而且就是用了一个参数的传递而已。
路漫漫其修远兮...这是算法导论的第二章啊...