定義
歸併排序(MERGE-SORT)是建立在歸併操作上的一種有效的排序算法,該算法是採用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合併,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合併成一個有序表,稱爲二路歸併。
思路描述
把一個數組細分成單個元素,每個元素看做一個數組,在把這些元素數組按順序不斷合併,1個和併成2個,2個合併成4個…直到全部合併完成。
如:
用途
1.排序 : 時間複雜度 O(n log n) ,空間複雜度 O(n) 。
2.求逆序對數:這也是歸併排序的主要用途
主要思想: 遞歸
優點比較: 歸併排序的比較次數小於快速排序的比較次數,移動次數一般多於快速排序的移動次數。 (速度僅次於快速排序,爲穩定排序算法,一般用於對總體無序,但是各子項相對有序的數列)
代碼如下(求逆序對數):
#include<cstdio>
const int MAXN=200005;
int n, a[MAXN], temp[MAXN];//數組a是輸入的數組,temp數組是最後排完序的數組
long long ans;
void count(int l, int r)
{
if(r == l)
return ;//結束條件
int m = (l + r) >> 1;//相當於m = (l + r) / 2;
count(l, m);//遞歸
count(m + 1, r);//二分查找(遞歸)
int i = l, j = m + 1, k = l;//i從左一半的第一個開始,j從右一半的第一個開始,k是數組temp的下表
while(j <= r || i <= m)
{
if(j > r || (i <= m && a[i] <= a[j]))//當右半邊沒有數了或左半邊有數並且它的數比右半邊小時,執行它
temp[k++] = a[i++];
else
temp[k++] = a[j++], ans += m - i + 1;
}
for(i = l; i <= r; i++)
a[i] = temp[i];
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
count(1, n);//調用函數
printf("%lld", ans);//輸出
return 0;
}