归并排序 逆序对

Posted sulfurdioxidehippocampus

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了归并排序 逆序对相关的知识,希望对你有一定的参考价值。

昨晚本来在做化学...结果闲的没事开始读买来就没看过的《算法导论》...就这个专注度,看来期末又要挂科了

连读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)。【大概?

算法导论的伪代码答案就不放出来了,因为是英文而且就是用了一个参数的传递而已。

路漫漫其修远兮...这是算法导论的第二章啊...

以上是关于归并排序 逆序对的主要内容,如果未能解决你的问题,请参考以下文章

归并排序 逆序对

归并排序(归并排序求逆序对数)--16--归并排序--Leetcode面试题51.数组中的逆序对

poj2299--归并排序求解逆序对

归并排序求逆序对

归并排序&&逆序对(codves1688,4163)

C++归并排序求逆序对_模板