Sort排序專題(7)歸併排序(MergeSort)(C++實現)

Hrbust-cxs發表於2020-11-08

歸併排序(MergeSort)

歸併排序(Merge Sort):是建立在歸併操作上的一種有效,穩定的排序演算法,該演算法是採用分治法的一個非常典型的應用。將已有序的子序列合併,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合併成一個有序表,稱為二路歸併。
思想:將陣列分解直到每個分組只有一個元素,在進行兩兩歸併,得到有序序列,在將有序序列進行兩兩歸併然後直到最終的合併得到有序序列。

圖解如下:
在這裡插入圖片描述
①先將總序列一分為二,再將各個子序列一分為二,直到每個分組只有一個元素10,4,6,3,8,2,5,7。
②在對其序列進行兩兩合併,10和4比較併合並,6和3…依此類推,得到4 10,3 6,2 8,5 7。
③再對有序序列4 10和3 6進行比較合併…依此類推得到3 4 6 10,2 5 7 8兩個有序序列
④最終對兩個有序序列進行比較合併3 4 6 10,2 5 7 8,得到最終有序序列2 3 4 5 6 7 8 10.
:先分解到每個分組只有一個元素,後進行比較合併,分解和合並都為遞迴。一直到最後合併為一個有序序列即可。

程式碼實現

#include<iostream>
#include<malloc.h>
using namespace std;

void Merge(int arr[],int l,int h)    //歸併函式
{
    int l1, l2, h1, h2,i = 0;
    l1 = l;             //最左邊指標,指下標
    h1 = l + (h - l) / 2;  //中間值指標,指下標
    l2 = h1 + 1;          //中間值+1指標,指下標
    h2 = h;                //最右邊指標,指下標
    int *pTmp = (int *)malloc(sizeof(int)*(h - l + 1));  //申請空間
    while(l1 <= h1 && l2 <= h2)
    {
        if(arr[l1] < arr[l2])     //比較arr[l1]和arr[l2],將較小的值放入pTmp中,並且移動指標,
        {
            pTmp[i] = arr[l1];
            l1++;
        }
        else
        {
            pTmp[i] = arr[l2];
            l2++;
        }
        i++;
    }
    while(l1 <= h1)             //將未遍歷完的一邊的元素按順序依次輸入pTmp中
    {
        pTmp[i] = arr[l1];
        l1++;
        i++;
    }
    while(l2 <= h2)
    {
        pTmp[i] = arr[l2];
        l2++;
        i++;
    }
    for(i = 0; i < h - l + 1;i++)    //將pTmp還給arr陣列,進行歸併。
    {
        arr[l + i] = pTmp[i];
    }
    free(pTmp);                    //釋放申請的空間
    pTmp = NULL;
}

void MergeSort(int arr[],int l,int h)
{
    if(arr == NULL || l >= h) return ;
    int Mid = l + (h - l)/2;    //找出中間值
    MergeSort(arr,l,Mid);       //分治中間值左邊   (遞迴直到2個元素)
    MergeSort(arr,Mid + 1,h);   //分治中間值右邊
    Merge(arr,l,h);             //歸併
}

int main()
{
    int *arr = NULL;                  //指標==陣列  指標需要初始化
    int n,len;
    cin>>n;
    arr = (int*)malloc(sizeof(int)*n);   //指標使用需要malloc空間(malloc空間虛擬地址連續,實體地址不一定連續)
    for(int i = 0; i < n; i++)
    {
        cin>>arr[i];
    }
    MergeSort(arr,0,n-1);
    for(int i = 0; i < n; i++)
    {
        cout<<arr[i]<<" ";
    }
    free(arr);
    arr = 0;
    return 0;
}

時間複雜度

歸併排序比較佔用記憶體,但卻是一種效率高且穩定的演算法。
時間複雜度無論好壞都是O(nlogn)。是一種相對穩定的排序演算法,分而治之是主要思想。

相關文章