1. 程式人生 > >C++資料結構 7 歸併排序

C++資料結構 7 歸併排序

歸併排序演算法採用的是分治演算法,即把兩個(或兩個以上)有序表合併成一個新的有序表,即把待排序的序列分成若干個子序列,每個子序列都是有序的,然後把有序子序列合併成整體有序序列,這個過程也稱為2-路歸併.一般來說,n個數據大致會分為logN層,每層執行merge的總複雜度為O(n), 所以總的複雜度為O(nlogn)。

歸併排序包含不相鄰元素的比較,但並不會直接交換。在合併兩個已排序的陣列時,如果遇到了相同的元素,只要保證前半部分陣列優先於後半部分陣列,相同元素的順序就不會顛倒,所以歸併排序屬於穩定的排序演算法。

歸併排序演算法雖然高效且穩定,但在處理過程中除了用於 儲存輸入資料的陣列外,還要臨時佔用一部分的記憶體空間。

C++迭代法:

#include <iostream>
#include <algorithm>
using namespace std;

  /*歸併排序:兩兩排序好的數進行重新組排,歸併排序是建立在歸併操作上的一種有效的排序演算法,
  //該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。
  //將已有序的子序列合併,得到完全有序的序列;
  //即先使每個子序列有序,再使子序列段間有序。
  若將兩個有序表合併成一個有序表,稱為二路歸併。 */
template <class T>
void Merge(T *initList,T *mergList,const int l,const int m,const int n)
{//initList初始陣列  mergList歸併好的陣列 , l是第一個陣列的下標,m是第二個陣列的下標,n是陣列個數
  int i1,i2,result;
  for(i1=l,i2=m+1,result=l;(i1<=m )&& (i2<=n); result++)
  {
      //進行比較
      if(initList[i1]<=initList[i2])  //小的放進合併數組裡面
      {
          mergList[result]=initList[i1];
          i1++;
      }
      else
      {
        mergList[result]=initList[i2];
        i2++;
      }
  }
  copy(initList+i1,initList+m+1,mergList+result);  //把剩下的直接拷貝到mergList裡面
  copy(initList+i2,initList+n+1,mergList+result);
}
template <class T>
void MergPass(T *initList,T *resultList,const int n,const int s)//n為元素個數,s為陣列迴圈次數
{//一個數合併成兩個數,這個過程中s=1,依次類推s=2....
    int i;
    for(i=1;i<n-2*s+1;i+=2*s)//進行合併
      Merge(initList,resultList,i,i+s-1,i+2*s-1);
    if((i+s-1)<n)  //如果沒有剩餘的,就進行歸併
      Merge(initList,resultList,i,i+s-1,n);
    else  //如果有剩餘的,就把剩下的複製下來
     copy(initList+i,initList+n+1,resultList+i);
}
template<class T>
void MergeSort(T *a,const int n)  //進行歸併 n為陣列個數
{
    T *templist=new int[n+1];  //templist[0]不用
    for(int l=1;l<n;l*=2)   //l每次取值都是1,2,4,8...
    {
       MergPass(a,templist,n,l); //第一次歸併
       l*=2;
       MergPass(templist,a,n,l); //迴圈使用陣列a,不會資源浪費
    }
    delete []templist;  //刪除臨時變數
}
int main()
{
    //int a[]={0,23,47,81,95,7,14,39,55,62,74};
    int x[]={0,23,47,81,95,7,14,39,55,62,74};
    MergeSort(x,10);
    for(int i=1;i<11;i++)
    {
        cout<<x[i]<<" ";
    }
    cout<<endl;
    return 0;
}