歸併排序的基本思想是分治法。先將無序序列分為若干個無序子串行,然後對無序子串行進行排序,最後合併有序子串行,得到完全有序的序列。這就是分解,求解,合併的過程。
將待排序序列data[0,1,2….n-1]看成是n個長度為一的序列,將相鄰序列進行合併,得到n/2個長度為2的有序序列;
將相鄰序列再次進行合併,得到n/4個長度為4的有序序列
重複第一步和第二步,直到得到長度為n的乙個有序序列,此時的序列為已排序序列
關鍵就在於如何合併序列,每次合併的過程都是對兩個有序序列進行合併,由於這兩個是相鄰的,因此我們可以將兩個序列表示為data[start, mid], data[mid + 1, end]。我們需要乙個end-start+1長度的temp輔助資料配合合併。
從data[start, mid]和data[mid + 1, end]中各取出乙個數字進行比較,將較小的數字放入到temp中,並且將數字對應的陣列游標加一
重複第一步,知道其中乙個陣列遍歷完
將另外乙個未遍歷完的陣列直接填入temp末尾
將temp拷貝回data[start, end]中
依舊對[2 8 1 5 3]這個陣列進行模擬,得到下面的結果:
gap=1 start28
1532
8153
gap=1 finish
gap=2 start28
1531
2583
gap=2 finish
gap=4 start12
5831
2358
gap=4 finish
@override
public
int sort(int data)
for (int gap = 1; gap < data.length; gap *= 2)
if (i + gap - 1
< data.length)
printlnarray(data);
system.out.println(string.format(locale.china, "gap=%d finish", gap));
}return data;
}
merge方法沒有貼上來,具體實現可看
github/mergesort
注意,如果最後乙個子串行不能正好整除的時候需要特殊處理,將其和倒數第二個子串行合併。
歸併排序是一種穩定的排序演算法,平均,最壞和最好的時間複雜度都為o(nlogn)。但是由於其需要o(n)的輔助空間,因此在一些對記憶體敏感的機器上,或者資料特別大時有所限制。
從穩定性來說,歸併排序相對於快速排序來說是乙個既快又穩定的排序方式。但是如果綜合考慮到空間和效能來說,快速排序是優於歸併排序的。
對於小陣列可使用插入或者選擇排序,不必使用合併的方式。
合併之前如果data[middle] < data[middle + 1]可以不需要合併直接返回。因為左邊子串行的最大值小於右邊子串行的最小值。
排序演算法(六) 歸併排序
對於歸併排序,與快速排序一樣,巧妙的應用了分治演算法的核心思想,它將整個序列分成若干組子串行,對這些子串行進行排序後,在一步一步進行合併有序子串行,從而使得整個序列達到有序。但針對於歸併排序,有著兩種不同的排序方式,一是通過整個序列進行著手,將這個序列進行一步一步的劃分,自頂向下進行處理,主要步驟包...
排序演算法(六) 歸併排序
歸併排序 merge sort 又稱二路歸併排序,是指將乙個陣列一分為二,對每乙個子陣列遞迴排序,最後將排好的子陣列合併為乙個有序陣列的過程。歸併排序,是 分治法 應用的完美實現。1.歸併排序圖示 2.歸併排序流程 通過圖示,可以發現歸併排序一共只需要兩個步驟 3.實現 歸併排序的 邏輯還是很容易看...
六 歸併排序
要將乙個陣列排序,可以先 遞迴的 將它分成層兩半分別排序,然後將結果歸併起來。它能保證任意長度為n的陣列排序所需時間和nlogn成正比 它的缺點則是它所需的額外空間和n成正比。實現歸併的一種直截了當的辦法是將兩個不同的有序陣列歸併到第三個陣列中,兩個陣列中的元素應該都實現了comparable藉口。...