自頂向下的原地歸併排序

2021-10-05 05:02:44 字數 1255 閱讀 1184

歸併排序是一種簡單的遞迴排序演算法。

思路:歸併排序即是將兩個有序的陣列歸併成乙個更大的有序陣列。那麼我們要將乙個陣列排序,我們可以先將這個陣列分成兩半分別排序,然後將結果歸併起來。其:

歸併排序的速度非常快,但是卻需要額外的空間。為什麼需要額外的空間尼?

因為我們使用歸併排序時是將兩個不同的有序陣列歸併到第三個陣列中去,這就導致了如果我們對乙個大陣列進行歸併,會進行很多次歸併,而每次歸併的時候都會建立乙個新的陣列來儲存結果。

如何解決?

我們希望做到一種原地歸併的方法。即對陣列的前後兩部分分別排序,然後就在陣列中對元素進行移動,而不需要建立新的陣列,來節省建立陣列的空間。

自頂向下是什麼意思?

從原陣列開始,對原陣列進行遞迴的拆分排序,一直拆到最下層。在最下層排序完成之後,又從最下層開始,一步一步的歸併回來。

例項:

public class merge 

public static void sort(comparable a, int start, int end)

private static void merge(comparable a, int start, int mid, int end)

for (int k = start; k <= end; k++)

}//less(),each(),show()以及測試**見博主其他排序文章,篇幅有限,這裡不給出//}

在**中我們可以看見,最關鍵的歸併方法merge()中,有四個判斷。這四個判斷代表的意義和產生的效果分別是:

上文提到,我們整個流程是將大陣列拆分成小陣列,然後將小陣列排序,最後歸併。在**中的sort()方法裡可以看見,我們每次是將陣列進行對半拆分,這樣拆分會不斷的將陣列縮小,直到縮小到陣列只有兩個元素(乙個元素時就直接返回)。對這只有兩個元素的陣列進行merge()方法,其實就相當於對兩個只有乙個元素的陣列進行歸併。在這個過程中,通過上文提到的四個判斷,讓這個有兩個元素的小陣列達到有序。

假如有乙個長度為16的陣列,那麼整個拆分過程如下:

我們可以看到,拆分到最後一層時,每個小陣列已經只有兩個元素。我們對最下層的每個小陣列進行歸併時,是將陣列中的兩個元素分成兩部分,通過排序歸併到原陣列中。最下層完成排序之後,兩兩歸併成倒數第二層…一直到最上層,即完成排序過程。

歸併排序 自頂向下 陣列實現

歸併 即merge函式 二路歸併排序舉例 分為有序子表a,有序子表b。a中首個元素與b中首個元素比較 若a1小於b1,取出a1,比較a2與b1 若a1大於b1,取出b1,比較a1與b2。依次類推。遞迴 即mergesort函式 分解問題 include include 對應malloc函式與free...

自頂向下和自底向上的歸併排序區別

歸併排序中最基本的操作是 歸併 即將兩個 2 路歸併 或兩個以上的有序陣列組合成乙個更大的有序陣列。按照歸併順序的不同,歸併排序可以分為自頂向下和自底向上兩類。自頂向下的歸併排序進行的操作主要就是對陣列的拆分與合併。通過層層拆分得到單元素陣列,天生有序,然後歸併兩個單元素陣列得到乙個較大的有序陣列,...

演算法 歸併排序(自頂向下 自底向上)

思路 實現 兩種實現方式 自頂向下和自底向上 實現 自頂向下 mergesort.h 1 include 2 include 3 include insertionsort.h 4 5using namespace std 67 template8 將arr l.mid 和arr mid 1.r 兩...