归并排序

归并排序体现了分治思想,时间复杂度是O(nlogn),空间复杂度是O(n)。

归并排序是将序列不断二分,最终分成单个元素,再两两合并,最终达到整个序列有序。

 1 void msort(int l,int r) {
 2     if(l==r) return; //划分到单个元素就返回
 3     int m=l+(r-l)/2,p=l,q=m+1,k=l;
 4     msort(l,m); //划分左右序列
 5     msort(m+1,r);
 6     while(p<=m||q<=r) //将左右序列合并成有序序列
 7         if(q>r||(a[p]<a[q]&&p<=m)) T[k++]=a[p++];
 8         else T[k++]=a[q++];
 9     for(k=l;k<=r;++k) a[k]=T[k]; //将合并后的序列放到原序列中
10 }
归并排序

归并排序的效率很高,而且不像快排那样会被特殊数据卡掉,只不过需要辅助内存。归并排序还有一种用途,就是统计逆序对。逆序对是指在一个序列中位置与值不对应的数对,如:1 3 2 4 7,就有(3,2),(3,4),(3,7)这三对逆序对。朴素的算法需要两层循环,复杂度是O(n^2)的,而归并排序本身的特性却可以让我们方便地统计逆序对。由于合并左右两个序列时,两个序列已有序,因此当出现右边元素大于左边元素时,此时左边序列剩余元素个数就是逆序对个数的一部分。

 1 void msort(int l,int r) {
 2     if(l==r) return; //划分到单个元素就返回
 3     int m=l+(r-l)/2,p=l,q=m+1,k=l;
 4     msort(l,m); //划分左右序列
 5     msort(m+1,r);
 6     while(p<=m||q<=r) //将左右序列合并成有序序列
 7         if(q>r||(a[p]<a[q]&&p<=m)) T[k++]=a[p++];
 8         else T[k++]=a[q++],cnt+=m-p+1; //顺便统计逆序对个数
 9     for(k=l;k<=r;++k) a[k]=T[k]; //将合并后的序列放到原序列中
10 }
归并排序(统计逆序对)

 

posted @ 2018-08-18 16:08  Mr^Kevin  阅读(175)  评论(0编辑  收藏  举报