歸併排序與逆序對

2021-08-29 22:55:57 字數 1992 閱讀 9528

最近學習逆序對,發現竟然要學習歸併排序,於是只好學了一下(之前一直用c++ stl的sort函式),發現思想和線段樹竟然驚人的相似,先放一張圖你們就懂了:

怎麼樣,是不是發現這就是一棵線段樹!其實歸併排序利用了二分的思想,即分而治之。

歸併排序是一種穩定的方法,時間複雜度:o(nlogn),空間複雜度:o(n)

是不是很優秀啊,現在我們就來講解一下演算法的流程:

void gb_sort(int l,int r)
1.不斷二分區間,直到將他們分到只有兩個數後在返回時不斷歸併2.從底向上歸併,由此我們才可以將乙個個排序好的小區間歸併成大區間

void hb_sort(int l,int mid,int r)

else

}while(left <= mid)

while(right <= r)

while(!que.empty())

}

假如我們要合併的兩個序列為1,5,15,16和4,8,9,10。

然後將數值小的下標加一,往後移。就便成了

這裡4比5小,所以4入隊,一直重複操作

直到完成,而這時還剩下兩個,再將他們入隊

然後再將佇列裡的數拷貝回原陣列

由於我們每次要合併的區間由小到大,即從底向上合併,而且合併的區間長度大於2,也就是下圖的紅色區間:

3.這樣我們就得到了乙個有序的區間,之後的每次合併都這樣操作,每一層合併為o(n),共有logn層,所以總的時間複雜度為

o(nlogn)

先看一道題:逆序對

在本題中我們要求的是當ia[j]的個數,不難想到歸併排序,而且只需在原來的**上做一點小小的改動,

我們只需要記錄每次後半段的數入隊時,前半段有多少個數比他大,用乙個ans統計就好了。

是不是很妙蛙!

下面我們直接來看**:

#include #include #include using namespace std;

int n,ans;

int a[40005];

queueque;

void hb_sort(int l,int mid,int r)

else

}while(left <= mid)

while(right <= r)

while(!que.empty())}

void gb_sort(int l,int r)

int main()

歸併排序與逆序對

歸併問題按照分治三步法進行介紹 劃分問題 把序列分成元素個數盡量相等的兩半 遞迴求解 把兩半元素分別排序 合併問題 把兩個有序表合併成乙個 借鑑乙個部落格的圖 排序演算法 四 之歸併排序 可以看到這種結構很像一棵完全二叉樹,本文的歸併排序我們採用遞迴去實現 也可採用迭代的方式去實現 分階段可以理解為...

歸併排序與逆序對

題目描述 給定你乙個長度為n的整數數列。請你使用歸併排序對這個數列按照從小到大進行排序。並將排好序的數列按順序輸出。輸入格式 輸入共兩行,第一行包含整數 n。第二行包含 n 個整數 所有整數均在1 109範圍內 表示整個數列。輸出格式 輸出共一行,包含 n 個整數,表示排好序的數列。資料範圍 1 n...

歸併排序與逆序對

歸併排序在於把序列拆分再合併起來,使用分治法來實現,這就意味這要構造遞迴演算法 將兩個列表是s1,s2按順序融合為乙個列表s,s為原列表 j和i就相當於兩個指向的位置,i指s1,j指s2 i j 0while i j len s j len s2 時說明s2走完了,或者s1沒走完並且s1中該位置是最...