歸併排序演算法(merge_Sort)

yangkuang發表於2021-02-17

一. 介紹:

歸併排序(Merge_Sort)是建立在歸併操作上的一種有效的排序演算法,該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合併,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。

  • 中文名

    歸併排序

  • 外文名

    Mergesort

  • 穩定性

    穩定

  • 時間複雜度

    O(nlogn)

  • 空間複雜度

    O(n)

  • 發明者

    約翰·馮·諾伊曼

二. 邏輯:

具體邏輯:分為兩個步驟
1.切分操作:將一組陣列切分成兩部分,運用分治思想(具體實現:遞迴),將切分的兩部分分別進行切分(再次將每部分一分為二),以此類推,直到陣列中的元素不能再進行切分(遞迴到底,直到切分到元素自身”l>=r”)。
2.歸併操作:然後將元素進行比較再依次歸併。
例子:陣列{5,3,2,1,7,4,8,0}進行排序

切分:

1.將陣列分為{5, 3, 2,1}和{,7, 4 ,8, 0}兩個陣列

2.將{5, 3, 2,1}和{7, 4 ,8, 0}兩個陣列分別進行切分,分為{5, 3}、{2, 1}、{7, 4}和{8, 0}

3.將5, 3}、{2, 1}、{7, 4}和{8, 0}陣列再進行分……

4.遞迴到{5}(此時不能分)最後

歸併

1.將5, 3}、{2, 1}、{7, 4}和{8, 0}陣列進行比較,得:{3, 5}、{1, 2}、{4, 7}和{0, 8}

2.將陣列3, 5}、{1, 2}和{4, 7}, {0, 8}中元素進行比較並歸併成{1, 2, 3, 5}和{0, 4, 7, 8}

3.重複”2”操作,最終排序完成,得出{0, 1, 2, 3, 4, 5, 7, 8}

三. 程式碼

  程式碼實現:
#include <iostream>

using namespace std;

// 將arr[l...mid]和arr[mid+1...r]兩部分進行歸併
template<typename  T> //使用模板
void __merge(T arr[], int l, int mid, int r){


    //* 這裡需要使用new申請空間, 不要忘了在__merge函式的最後, delete掉申請的空間:)
    T aux[r-l+1];
    //T *aux = new T[r-l+1];

    for( int i = l ; i <= r; i ++ )
        aux[i-l] = arr[i];

    // 初始化,i指向左半部分的起始索引位置l;j指向右半部分起始索引位置mid+1
    int i = l, j = mid+1;
    for( int k = l ; k <= r; k ++ ){

        if( i > mid ){  // 如果左半部分元素已經全部處理完畢
            arr[k] = aux[j-l]; j ++;
        }
        else if( j > r ){  // 如果右半部分元素已經全部處理完畢
            arr[k] = aux[i-l]; i ++;
        }
        else if( aux[i-l] < aux[j-l] ) {  // 左半部分所指元素 < 右半部分所指元素
            arr[k] = aux[i-l]; i ++;
        }
        else{  // 左半部分所指元素 >= 右半部分所指元素
            arr[k] = aux[j-l]; j ++;
        }
    }

    //delete[] aux;
}

// 遞迴使用歸併排序,對arr[l...r]的範圍進行排序
template<typename T>
void __mergeSort(T arr[], int l, int r){

    if( l >= r )
        return;

    int mid = (l+r)/2; //將陣列進行切分
    __mergeSort(arr, l, mid);
    __mergeSort(arr, mid+1, r);
    __merge(arr, l, mid, r);
}

template<typename T>
void mergeSort(T arr[], int n){

    __mergeSort( arr , 0 , n-1 );
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章