浅谈归并排序
这是一个一(hu)本(shuo)正(ba)经(dao)的浅谈:
首先归并排序是什么?
归并排序就是归并排序啊!(天天瞎bb的我)
简单说一下我的理解:
这是分开的部分(以上)。
这是合并的部分(以上)。
为什么要用它呢?
因为我闲得慌。
归并排序可以说是最稳定的一种排序,并且它的时间复杂度为O()。
相较于其他的排序,归并排序也有它的优点,即在处理大数据时。
并且还可以用归并排序来计算逆序对。
它的套路是什么呢?
瞎几把乱打就对了。
归并排序有着分治的思想,即先把无序对中间折半,分成左右两份子序对,再分解,直到每个子序对中只剩一个元素。
逆序对就是数列中任意两个数满足大的在前,小的在后的组合。如果将这些逆序对都调整成顺序(即小的在前,大的在后),那么整个数列就会显得有序。冒泡排序就是
通过消除这些逆序对来排序的,那么交换的次数就是逆序对的个数。
如果你看懂了,恭喜,你已经异于常人。
可以A掉这两道可爱的luogu题了:
主要就是更改一下输出方式就可以啦~
1.SP9722 CODESPTB - Insertion Sort
AC代码:
#include<bits/stdc++.h> using namespace std; int k,n,ans=0; int a[500100],b[500100]; void merge_sort(int l,int r) { if(l==r)return ;//一个数不用排 int m=(l+r)>>1; merge_sort(l,m); merge_sort(m+1,r); int i=l,j=m+1,k=0;//i左边最小位置,j右边最小位置 while(i<=m&&j<=r) if(a[i]<=a[j])b[++k]=a[i++]; else ans+=m-i+1,b[++k]=a[j++];//加入右半段时,逆序对数增加 while(i<=m)b[++k]=a[i++];//加入左边剩余的数 while(j<=r)b[++k]=a[j++];//加入右边剩余的数 for(i=1; i<=k; i++)a[l+i-1]=b[i]; } int main() { scanf("%d",&k); for(int i=1; i<=k; i++) { ans=0; scanf("%d",&n); for(int i=1; i<=n; i++) scanf("%d",&a[i]); merge_sort(1,n); printf("%d\n",ans); } return 0; }
2.SP25784 BUBBLESORT - Bubble Sort
AC代码:
#include<bits/stdc++.h> using namespace std; int k,n,ans=0; int a[50010],b[50010];//a原数组,b暂存数组 void merge_sort(int l,int r) {//归并 if(l==r)return ;//一个数不用排 int m=(l+r)>>1; merge_sort(l,m);//排序左边 merge_sort(m+1,r);//排序右边 int i=l,j=m+1,k=l;//i左边最小位置,j右边最小位置 while(i<=m&&j<=r){ if(a[i]<=a[j])b[k++]=a[i++]; else b[k++]=a[j++],ans= (ans+m-i+1)%10000007;//加入右半段时,逆序对数增加 } while(i<=m)b[k++]=a[i++];//加入左边剩余的数 while(j<=r)b[k++]=a[j++];//加入右边剩余的数 for(int p=l; p<=r; ++p) a[p]=b[p],b[p]=0;//从暂存数组中赋值 } int main() { scanf("%d",&k); for(int j=1; j<=k; ++j) { scanf("%d",&n); for(int i=1; i<=n; ++i) scanf("%d",&a[i]); ans=0; merge_sort(1,n); printf( "Case %d: %d\n", k, ans ); } return 0; }
排序只用猴排。
树只用八叉树。