C++資料結構 7 歸併排序
阿新 • • 發佈:2018-12-14
歸併排序演算法採用的是分治演算法,即把兩個(或兩個以上)有序表合併成一個新的有序表,即把待排序的序列分成若干個子序列,每個子序列都是有序的,然後把有序子序列合併成整體有序序列,這個過程也稱為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; }