歸併排序[從入門到放棄]

1. 歸併排序

歸併排序,是建立在歸併操做上的一種有效的排序算法,效率爲O(nlogn)。1945年由約翰·馮·諾伊曼首次提出。該算法是採用分治法(Divide and Conquer)的一個很是典型的應用,且各層分治遞歸能夠同時進行。速度僅次於快速排序,爲穩定排序算法,通常用於對整體無序,可是各子項相對有序的數列,歸併排序的比較次數小於快速排序的比較次數,移動次數通常多於快速排序的移動次數。算法

2. 歸併操做

歸併操做,也叫歸併算法,指的是將兩個已經排序的序列合併成一個序列的操做。數組

image

3. 歸併排序原理

既然歸併排序採用的是分治法,而且依託于歸並操做,那麼其思想確定是分而治之。咱們知道歸併操做是將兩個有序的數列合併到一個有序的序列,那麼對於一個無序的長序列,能夠把它分解爲若干個有序的子序列,而後依次進行歸併。若是咱們說每個數字都是單獨有序的序列,那麼只要把原始長序列依次分解,直到每一個子序列都只有一個元素的時候,再依次把全部的序列進行歸併,直到序列數爲1ide

4. 歸併排序的實現方法

遞歸法code

原理以下(假設序列共有n個元素):blog

  1. 將原始序列從中間分爲左、右兩個子序列,此時序列數爲2
  2. 將左序列和右序列再分別從中間分爲左、右兩個子序列,此時序列數爲4
  3. 重複以上步驟,直到每一個子序列都只有一個元素,可認爲每個子序列都是有序的
  4. 最後依次進行歸併操做,直到序列數變爲1

image

參考代碼排序

void Merge(int r[],int r1[],int s,int m,int t)
{
    int i=s;
    int j=m+1;
    int k=s;
    while(i<=m&&j<=t)
    {
        if(r[i]<=r[j])
            r1[k++]=r[i++];
        else
            r1[k++]=r[j++];
    }
    while(i<=m)
        r1[k++]=r[i++];
    while(j<=t)
        r1[k++]=r[j++];
    for(int l=0; l<8; l++)
        r[l]=r1[l];
}
 
void MergeSort(int r[],int r1[],int s,int t)
{
    if(s==t)
        return;
    else
    {
        int m=(s+t)/2;
        MergeSort(r,r1,s,m);
        MergeSort(r,r1,m+1,t);
        Merge(r,r1,s,m,t);
    }
}

迭代法遞歸

原理以下(假設序列共有n個元素):效率

  1. 將序列每相鄰兩個數進行歸併操做,造成ceil(n/2)個序列,排序後每一個序列包含兩/一個元素
  2. 將序列每相鄰的兩個有序子序列進行歸併操做,造成ceil(n/4)個序列,每一個序列包含四/三個元素
  3. 重複步驟2,直到全部元素排序完畢,即序列數爲1個

參考代碼原理

void Merge(int*a,int low,int mid,int high)
{
    inti=low,j=mid+1,k=0;
    int *temp=(int*)malloc((high-low+1)*sizeof(int));
    while(i<=mid&&j<=high)
        a[i]<=a[j]?(temp[k++]=a[i++]):(temp[k++]=a[j++]);
    while(i<=mid)
        temp[k++]=a[i++];
    while(j<=high)
        temp[k++]=a[j++];
    memcpy(a+low,temp,(high-low+1)*sizeof(int));
    free(temp);
}
void MergeSort(int*a,int n)
{
    int length;
    for(length=1; length<n; length*=2)
    {
        int i;
        for(i=0; i+2*length-1<=n-1; i+=2*length)
            Merge(a,i,i+length-1,i+2*length-1);
        if(i+length<=n-1)
             Merge(a,i,i+length-1,n-1);
    }
}

5. 複雜度

  • 時間複雜度:O(nlogn)
  • 空間複雜度:O(N),歸併排序須要一個與原數組相同長度的數組作輔助來排序
  • 穩定性:歸併排序是穩定的排序算法,temp[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];這行代碼能夠保證當左右兩部分的值相等的時候,先複製左邊的值,這樣能夠保證值相等的時候兩個元素的相對位置不變。
相關文章
相關標籤/搜索