1. 程式人生 > >【資料結構和演算法14】歸併排序

【資料結構和演算法14】歸併排序

        歸併演算法的中心是歸併兩個已經有序的陣列。歸併兩個有序陣列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)。

        歸併排序是穩定的,由於沒有發生資料交換,所有當a=b的時候,a一開始如果在b前面,則其每一次合併後仍然在b前面,故該排序演算法是穩定的。

        歸併排序就寫這麼多,如有錯誤之處,歡迎留言指正~

        文末福利:“程式設計師私房菜”,一個有溫度的公眾號~ 
        程式設計師私房菜

_____________________________________________________________________________________________________________________________________________________

-----樂於分享,共同進步!