歸並算法的中心是歸並兩個已經有序的數組。歸並兩個有序數組A和B,就生成了第三個數組C,數組C包含數組A和B的所有數據項,並且使它們有序的排列在數組C中。首先我們來看看歸並的過程,然後看它是如何在排序中使用的。
假設有兩個有序數組,不要求有相同的大小。設數組A有4個數據項,數組B有6個數據項,它們要被歸並到數組C中,開始時數組C有10個存儲空間,歸並過程如下圖所示:

歸並排序的思想是把一個數組分成兩半,排序每一半。然後用merge方法將數組的兩半歸並成一個有序的數組。被分的每一半使用遞歸,再次劃分排序,直到得到的子數組只含有一個數據項為止。正如上面所說的,歸並排序需要額外的一個和AB兩個數組總和相等的空間,如果初始數組幾乎沾滿了整個存儲器,那麼歸並排序就不能工作了。
歸並排序的思想很簡單,下面我們來看看具體實現:
public void mergeSort(int[] source) {
int[] workSpace = new int[source.length];
recMergeSort(source,workSpace, 0, source.length-1);
}
private void recMergeSort(int[] source, int[] workSpace, int lowerBound, int upperBound) {
if(lowerBound == upperBound) {
return;
}
else {
int mid = (lowerBound + upperBound) / 2;
recMergeSort(source, workSpace, lowerBound, mid); //左邊排
recMergeSort(source, workSpace, mid+1, upperBound); //右邊排
merge(source, workSpace, lowerBound, mid+1, upperBound);//歸並
}
}
private void merge(int[] a, int[] workSpace, int lowPtr, int highPtr, int upperBound) {
int j = 0;
int lowerBound = lowPtr;
int mid = highPtr - 1;
int n = upperBound - lowerBound + 1;
while(lowPtr <= mid && highPtr <= upperBound) {
if(a[lowPtr] < a[highPtr]) {
workSpace[j++] = a[lowPtr++];
}
else {
workSpace[j++] = a[highPtr++];
}
}
while(lowPtr <= mid) {
workSpace[j++] = a[lowPtr++];
}
while(highPtr <= upperBound) {
workSpace[j++] = a[highPtr++];
}
for(j = 0; j < n; j++) {
a[lowerBound + j] = workSpace[j];
}
}
算法分析:歸並排序的運行時間最差、最好和平均都是O(NlogN),但是它需要額外的存儲空間,這在某些內存緊張的機器上會受到限制。歸並算法是由分割和歸並兩部分組成的,對於分各部分,如果我們使用二分查找,時間是O(NlogN),在最後歸並的時候時間是O(N),所以總時間是O(NlogN)。空間復雜度為O(N)。
歸並排序就寫這麼多,如有錯誤之處,歡迎留言指正~
_____________________________________________________________________________________________________________________________________________________