1. 程式人生 > >歸併排序演算法 遞迴及迴圈實現

歸併排序演算法 遞迴及迴圈實現

第一步合併相鄰長度為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;
}