這是一個一(hu)本(shuo)正(ba)經(dao)的淺談:c++
首先歸併排序是什麼?數組
歸併排序就是歸併排序啊!(每天瞎bb的我)大數據
簡單說一下個人理解:spa
這是分開的部分(以上)。code
這是合併的部分(以上)。blog
爲何要用它呢?排序
由於我閒得慌。get
歸併排序能夠說是最穩定的一種排序,而且它的時間複雜度爲O()。it
相較於其餘的排序,歸併排序也有它的優勢,即在處理大數據時。io
而且還能夠用歸併排序來計算逆序對。
它的套路是什麼呢?
瞎幾把亂打就對了。
歸併排序有着分治的思想,即先把無序對中間折半,分紅左右兩份子序對,再分解,直到每一個子序對中只剩一個元素。
逆序對就是數列中任意兩個數知足大的在前,小的在後的組合。若是將這些逆序對都調整成順序(即小的在前,大的在後),那麼整個數列就會顯得有序。冒泡排序就是
經過消除這些逆序對來排序的,那麼交換的次數就是逆序對的個數。
若是你看懂了,恭喜,你已經異於常人。
能夠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; }
排序只用猴排。
樹只用八叉樹。