可以用來求逆序數對的排序(歸併排序)

時間複雜度:O(n log n)

 空間複雜度:O(n)

算法 流程:

設n爲待排序列元素的個數,a[i]爲其中第i個元素,merge_sort爲歸併排序的函數名,b[i]爲兩個相鄰 子序列合併完的臨時有序的序列。

第一步: 將所有的元素 進行二分,直到每個區間 只有一個元素。

然後開始  兩兩區間 進行合併(有序的合併)。

void build(int l,int r)
{
    if(l<r)
    {
        int mid=(l+r)/2;
        //printf("%d %d %d---->\n",l,r,mid);
        build(l,mid);
        //printf("%d %d %d*****\n",l,r,mid);
        build(mid+1,r);
        //printf("%d %d %d>>>>\n",l,r,mid);
        merge_sort(l,mid,r);
    }
}

第二步:將已有序的子序列合併(二分到最後的時候,一個元素一定是有序的),得到完全有序的序列

具體代碼:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int a[500010];
int b[500010];
long long ans;
void merge_sort(int l,int mid,int r)
{
    int i=l;//i從l開始的,因爲現在的排序是1~r的區間且要二分合並
    int j=mid+1;//j從mid+1開始到r。
    int k=l;//數組b的下標,數組b存的是1~r區間排完序的值
    while(i<=mid&&j<=r)
    {
        if(a[i]<=a[j])
            b[k++]=a[i++];
        else
        {
            ans+=j-k;
            b[k++]=a[j++];
        }
    }
    while(i<=mid) b[k++]=a[i++];//把剩餘的元素存進去
    while(j<=r) b[k++]=a[j++];
    for(int i=l;i<k;i++)//把有序序列b賦值到a中
        a[i]=b[i];
}
void build(int l,int r)
{
    if(l<r)
    {
        int mid=(l+r)/2;
        //printf("%d %d %d---->\n",l,r,mid);
        build(l,mid);
        //printf("%d %d %d*****\n",l,r,mid);
        build(mid+1,r);
        //printf("%d %d %d>>>>\n",l,r,mid);
        merge_sort(l,mid,r);
    }
}
int main()
{
    int n;
    while(~scanf("%d",&n)&&n)
    {
        ans=0;
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        build(0,n-1);
        printf("%lld\n",ans);
    }
    return 0;
}

模擬過程:(圖解)

>>>>>進行二分

>>>>>進行合併

------------------------------------------------------------------------我是分界線----------------------------------------------------------------------

 

 

------------------------------------------------------------------------I am a 分界線----------------------------------------------------------------------

 ------------------------------------------------------------------************分界線*************--------------------------------------------------------------

 

 ------------------------------------------------------------------************分界線*************--------------------------------------------------------------

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章