歸併排序 之 求逆序數

2021-06-21 04:29:39 字數 2142 閱讀 1452

前幾天看樹狀陣列,昨天做求逆序數的題,發現歸併排序求逆序數更快一點,或者說是排序的時候順便把逆序數給求了,於是學了一下,順便整理一下。。。。。。

歸併排序:說白了就是把一列數  遞迴  的分解為多個有序的子串行,然後再把子序列合併 為一列有序的數。

這就涉及兩個過程:

1,遞迴劃分:把序列分成個數盡量相等的兩部分,兩邊的元素分別排好序;

2,合併求解:把兩個有序表合成乙個;

下面來說明上面兩個過程:

第一步:假如給定乙個序列:,第一次劃分後分為兩個子串行,,當然現在兩邊的序列依舊無序,現在我們要做的使序列有序(當然我們不能直接用排序函式直接對兩部分排序,要不還要歸併排序幹嘛),那就繼續第一步,把兩個子串行繼續遞迴分解,當遞迴到每個子串行中只包含乙個元素時,呵呵,這個子串行當然就是有序的了,當第一步結束後我們得到如下七個子串行,,,,,,,並且每個子串行有序。

第二步:分別對兩個有序子串行合併,對上面七個子串行第一次合併後是,,,,第二次合併後是,;第三次合併後就是,排序完成。

現在我們來說如何把兩個有序子串行合併為乙個有序序列:對序列1和序列2;我們先比較序列1的第乙個元素和序列2的第乙個元素,小的元素存入序列3中,計數器向後加1,重複上面步驟,直到其中乙個子串行為空,此時把另外乙個未空序列中剩餘元素複製到3中即可完成合併。詳見**:

//將有序陣列a和b合併到c中

void merge(int a, int n, int b, int m, int c)

while (i < n)

c[k++] = a[i++];

while (j < m)

c[k++] = b[j++];

}

當然上面的只是對於兩個陣列a,b的操作,我們所要合併的兩個子串行在乙個序列中,以mid分開,所以**如下:

//將a的兩部分有序數列a[first...mid]和a[mid+1...last]合併

void merge(int a, int first, int mid, int last, int c)

while (i <= m)

c[k++] = a[i++];

while (j <= n)

c[k++] = a[j++];

for (i = 0; i < k; i++)

a[first + i] = c[i];//因為合併的序列是從first開始的,所以把合併後的序列c賦給原序列應該從first位置開始

}

由上面**可見,合併操作只需遍歷一遍兩個子串行,故時間複雜度為o(n);

當然上面**簡單易懂但略顯繁瑣,稍微精簡的如下:

int merge(int a,int first,int mid,int last,int c)

//求逆序數時只需改為左邊,下面解釋

}for(i=0;i上面的看完應該會序列合併了,那現在就用遞迴實現序列劃分與合併,**如下:

void merge_sort(int a,int first,int last,int c)

{ if(first由於遞迴分解子串行,相當於二分子序列,故時間複雜度為o(logn);

故總時間複雜度為nlogn;

至此,歸併排序已經說完,下面是更加簡潔的**,一氣呵成:

//歸併排序

void merge_sort(int a,int first,int last,int c)

{ if(last-first>1)//

{int mid=first+(last-first)/2;

int p=first,q=mid,i=first;//從中間劃分為盡量相等兩部分

merge_sort(a,first,mid,c);//遞迴呼叫使左邊有序

merge_sort(a,mid,last,c);//遞迴呼叫使右邊有序

while(p=last||(p

為什麼歸併排序就順便把逆序數給求了呢?其實很簡單,因為我們要合併的兩個子串行是排好序的,當右邊子串行中的數a[i]複製給c陣列時,左邊子串行中沒來的及複製到c中的那些數就是所有比a[i]大的數,故此時在累加器中加上左邊剩餘元素個數即可,在**中有標記。

終於整理完了,我想說一句,歸併排序除了方便理解遞迴和求逆序數(樹狀陣列也行),不知道幹嘛,排序速度不如c++ stl中的sort,穩定排序也不如stable_sort方便,呵呵~~~

求逆序數 逆序數 歸併排序

求排列的逆序數 分治 一 題目描述 總時間限制 1000ms 記憶體限制 65536kb 描述 在internet上的搜尋引擎經常需要對資訊進行比較,比如可以通過某個人對一些事物的排名來估計他 或她 對各種不同資訊的興趣,從而實現個性化的服務。對於不同的排名結果可以用逆序來評價它們之間的差異。考慮1...

歸併排序 求逆序數

首先需要了解逆序對的概念 如果在乙個序列 數列中,滿足 則ax和ay稱為一對逆序對。現在考慮乙個問題 對乙個大小為n 即有n個元素 元素隨機無序且唯一的整數序列中,平均有多少個逆序對?乙個構造證明的方法如下 設乙個隨機無序且元素唯一的整數序列為 我們令lr為l的反向序列,即 然後在lr中任取兩個數,...

歸併排序求逆序數

輸入 n 陣列中元素個數 x 最後所存在的每對逆序對所需要花費的錢 y 按任意順序交換陣列中相鄰兩個元素所要花費的錢 n個陣列中元素 輸出 求使陣列變為公升序所需要的最少 即求該陣列的逆序數 按陣列順序 任意順序交換次數均為該陣列的逆序數次 歸併排序求逆序數 歸併排序採用分治策略 ex 重點在於合併...