通用算法 -[排序算法] -歸併排序

1、算法思想

歸併排序的基本思想是,把大的數組劃分成兩個子數組,然後分別對這兩個子數組分別進行排序,之後在把這兩個排好序的子數組合併成一個有序的數組。由於兩個小的數組都是有序的,所以在合併的時候是很快的。

通過遞歸的方式將大的數組一直分割,直到數組的大小爲 1,此時只有一個元素,那麼該數組就是有序的了,之後再把兩個數組大小爲1的合併成一個大小爲2的,再把兩個大小爲2的合併成4的 …… 直到全部小的數組合並起來。

爲方便理解我還準備了動圖:
在這裏插入圖片描述

2、代碼實現

遞歸版本:

void mergeSort(int[] arr, int left, int right) {
        // 如果 left == right,表示數組只有一個元素,則不用遞歸排序
        if (left < right) {
            // 把大的數組分隔成兩個數組
            int mid = (left + right) / 2;
            // 對左半部分進行排序
            arr = mergeSort(arr, left, mid);
            // 對右半部分進行排序
            arr = mergeSort(arr, mid + 1, right);
            //進行合併
            merge(arr, left, mid, right);
        }
        return arr;
    }

    // 合併函數,把兩個有序的數組合並起來
    // arr[left..mif]表示一個數組,arr[mid+1 .. right]表示一個數組
void merge(int[] arr, int left, int mid, int right) {
        //先用一個臨時數組把他們合併彙總起來
        int[] a = new int[right - left + 1];
        int i = left;
        int j = mid + 1;
        int k = 0;
        while (i <= mid && j <= right) {
            if (arr[i] < arr[j]) {
                a[k++] = arr[i++];
            } else {
                a[k++] = arr[j++];
            }
        }
        while(i <= mid) a[k++] = arr[i++];
        while(j <= right) a[k++] = arr[j++];
        // 把臨時數組複製到原數組
        for (i = 0; i < k; i++) {
            arr[left++] = a[i];
        }
 }

非遞歸版本:

void mergeSort(int* arr,int length) {
        int n = length;
        // 子數組的大小分別爲1,2,4,8...
        // 剛開始合併的數組大小是1,接着是2,接着4....
        for (int i = 1; i < n; i += i) {
            //進行數組進行劃分
            int left = 0;
            int mid = left + i - 1;
            int right = mid + i;
            //進行合併,對數組大小爲 i 的數組進行兩兩合併
            while (right < n) {
                // 合併函數和遞歸式的合併函數一樣
                merge(arr, left, mid, right);
                left = right + 1;
                mid = left + i - 1;
                right = mid + i;
            }
            // 還有一些被遺漏的數組沒合併,千萬別忘了
            // 因爲不可能每個字數組的大小都剛好爲 i
            if (left < n && mid < n) {
                merge(arr, left, mid, n - 1);
            }
        }
        return arr;
    }
}

3、算法分析

  • 時間複雜度:O(nlogn)
  • 空間複雜度:O(n)
  • 穩定性:穩定的
  • 非原地排序
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章