歸併排序 2020-09-20

CJX222發表於2020-09-27


歸併演算法

通過不斷的進行二分法進行分組,直到分到每組只有一個元素以後,進行遞迴。在遞迴過程中,每次遞迴回上一個組別時,每次在執行自身這個組的排序方法之前,都會先將它以下的組別傳入到排序方法中,按照有序排序順序排列好.


一、程式碼

/**  
 * @param a 需要進行遞迴的陣列
 * @param start 每次遞進的左陣列開始位置
 * @param right 每次遞進的右邊陣列結束位置
 * @param temp 臨時陣列
 */
public static void mergeSort(int[] a, int start, int right, int[] temp) {
    //當start不比right小的時候,說明已經分組到了只剩一個了
    if (start < right) {
        int mid = (start + right) / 2;
        //左邊遞進
        mergeSort(a,start,mid,temp);
        //右邊遞進
        mergeSort(a,mid + 1, right,temp);
        //歸還,第一次執行這裡的時候,已經完全分好了
        merge(a, start, mid, right, temp);
    }
}
/**
 * @param a     需要排序的陣列
 * @param start 左邊一個陣列開始的位置
 * @param mid   左邊一個陣列結束位置
 * @param right   右邊一個陣列結束位置
 * @param temp  臨時陣列,用來暫時存放排序好的陣列
 */
public static void merge(int[] a, int start, int mid, int right, int[] temp) {
    int t = 0; //記錄臨時陣列的下標
    int l = start; //用來記錄左邊陣列當前位置
    int r = mid + 1; //來記錄右邊陣列的當前位置

    //判斷這兩個陣列是否有一個陣列已經遍歷完了
    while (l <= mid && r <= right) {
        //看左邊的那個陣列的當前下標的值是否比後面的大
        if (a[l] < a[r]) {
            //如果大就存入臨時陣列中
            temp[t] = a[l];
            //讓前面的那個陣列下標+1,當作遍歷
            l++;
            //臨時陣列下表也要+1
            t++;
        } else {
            //如果比那個小的話
            temp[t] = a[r];
            r++;
            t++;
        }
    }

    //判斷左邊是否還有殘留資料.
    while (l <= mid) {
        temp[t] = a[l];
        t++;
        l++;
    }
    while (r <= right) {
        temp[t] = a[r];
        t++;
        r++;
    }
    //temp每次都是從0開始存的,但a陣列不是
    t = 0;
    //將臨時陣列的值給回原陣列
    for (int i = start; i <= right; i++) {
        a[i] = temp[t];
        t++;
    }
}

二、注意

2.1

right的值是隨著傳入的mid的值進行的改變的,只有(0+1)/2等於0的時候,說明已經分的只有最後一個了.

   //當start不比right小的時候,說明已經分組到了只剩一個了
    if (start < right)

2.2

向左遞進的時候會先遞進到只有一個元素了才會結束,而這時的mid值是0,right值經過上次傳入的mid為1,而這時開始進行向右遞進,因此導致了第一次的時候只有兩個元素在進行排列.
當左邊的第一次歸還完成的時候,便會退出返回到上一次遞進中,而這次的遞進,就只完成了左遞進,於是便要完成右遞進。而當右遞進完成了之後,便開始自己的排序了。
如此往上,因此,每次向大的陣列遞迴的時候,左右兩邊都已經是有序的了

        //左邊遞進
        mergeSort(a,start,mid,temp);
        //右邊遞進
        mergeSort(a,mid + 1, right,temp);
        //歸還,第一次執行這裡的時候,已經完全分好了
        merge(a, start, mid, right, temp);

2.2

start和right是用來確定a陣列中具體排列的位置的。

//temp每次都是從0開始存的,但a陣列不是,每次都是是分一點合一點
t = 0;
//將臨時陣列的值給回原陣列
for (int i = start; i <= right; i++) {
    a[i] = temp[t];
    t++;
}

相關文章