歸併排序演算法 遞迴及迴圈實現
阿新 • • 發佈:2018-12-23
第一步合併相鄰長度為1的子陣列段,這是因為長度為1的子陣列段是已經排好序的。
用一次對陣列arr的線性掃描就足以找出所有這些排好序的子陣列段。然後將相鄰的排好序的子陣列段兩兩合併,構成更大的排好序的子陣列段。
#include<stdio.h> #include<iostream> using namespace std; //遞迴思想歸併排序 //void MergeSort(int a[],int left,int right){ // if(left<right){ // int i=(left+right)/2;//取中點 // MergeSort(a,left,i); // MergeSort(a,i+1,right); // MergeSort(a,b,left,i,right);//合併到陣列b // Copy(a,b,left,right);//複製會陣列b // } //} //迴圈思想歸併排序 void Merge(int c[],int d[],int left,int mid,int right){ int i=left,j=mid+1,k=left; while(i<=mid&&j<=right){ if(c[i]<=c[j])d[k++]=c[i++]; else d[k++]=c[j++]; } if(i>mid)for(int q=j;q<=right;q++)d[k++]=c[q];//當i已經超過了mid時,說明跳出while迴圈時j可能<right,所以將剩餘的mid~right之間的資料賦值給d陣列 else for(int q=i;q<=mid;q++)d[k++]=c[q]; //說明i~mid之間可能有剩餘資料,將其賦值給d陣列 } void MergePass(int x[],int y[],int s,int n){ int i=0; while(i<=n-s*2){//即i+s*2<=n,以i+s為中點的左右兩邊的總長不能超過n Merge(x,y,i,i+s-1,i+s*2-1); i=i+s*2; } if(i+s<n)Merge(x,y,i,i+s-1,n-1); else for(int j=i;j<=n-1;j++) y[j]=x[j]; } void MergeSort(int a[],int n){ int b[n]; int s=1; while(s<n){ MergePass(a,b,s,n);//將a->b 一次排序中的結果儲存到b中 s+=s; MergePass(b,a,s,n);//將b->a 一次排序的結果儲存到a中 s+=s; } } int main(){ int arr[5]={23,12,2,5,3};//測試資料 MergeSort(arr,5); for(int i=0;i<5;i++){ printf("%d ",arr[i]); } return 0; }