歸併排序—非遞歸 / 遞歸(C語言)

歸併排序

歸併排序(MERGE-SORT)是建立在歸併操作上的一種有效的排序算法,該算法是採用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合併,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合併成一個有序表,稱爲二路歸併。

一、非遞歸實現

1.排序原理

歸併排序的非遞歸實現主要在於子序列的劃分;
1、首先需要一個臨時數組以及左右兩個子序列的區間
2、從區間長度爲1開始(遞增兩倍)將原數組劃分成多對左右兩個子序列;
3、依次將多對左右子序列進行比較,並按順序存入臨時數組中
4、再將臨時數組排序好的序列再複製到原數組中
5、最後區間長度兩倍增長,重複以上操作,即歸併
排序過程圖示
在這裏插入圖片描述

2.源代碼:

#include<stdio.h>
#include<stdlib.h>
#define N 10

void MergeSort(int num[],int len)
{
	int i,j;
	int *sort;
	int L_start=0,L_end=0;//初始化左區間的起點、終點下標
	int R_start=0,R_end=0;//初始化右區間的起點、終點下標

	sort=(int*)malloc(N*sizeof(int));//爲臨時數組分配空間

	for(i=1;i<N;i*=2)//區間長度兩倍遞增
	{
		for(L_start=0;L_start<len-i;L_start=R_end)
		{
			//確定左右區間兩邊的起點、終點下標		
			L_end   = L_start+i;
			R_start	= L_start+i;
			R_end	= R_start+i;

			if(R_end>len)//右區間終點不超過數組長度
			{
				R_end=len;
			}			
			j=0;	//臨時數組初始下標

			while(L_start<L_end && R_start<R_end)
			{
				//比較左右起點數據的大小,並將較小的數據依次存入臨時數組
				if(num[L_start]<num[R_start])	
					sort[j++]=num[L_start++];
				else
					sort[j++]=num[R_start++];
				//同時起點下標遞增
			}
	
			while(L_start<L_end)//將比較完剩餘的數據存入臨時數組
			{
				sort[j++]=num[L_start++];
			}	
			while(j>0)			//將已排好的臨時數組數據錄入原數組中
			{
				num[--R_start]=sort[--j];
			}

			//for(int k=0;k<len;k++)
			//	printf("%d ",num[k]);
			//printf("\n");
		}
	//printf("-------------\n");
	}
	free(sort);
}

int main()
{
	int num[N]={5,3,7,1,9,2,0,4,8,6};
	MergeSort(num,N);
	for(int i=0;i<N;i++)
		printf("%d ",num[i]);
	printf("\n");
	return 0;
}

二、遞歸實現

1.排序原理

歸併排序的遞歸實現主要在於遞歸分治,對於遞歸算法,我們都能用二叉樹來理解,對於一個序列,遞歸左右子序列,並對其子序列進行合併排序,即可得到排序好的序列
排序過程圖示
在這裏插入圖片描述

2.源代碼:

#include<stdio.h>
#include<stdlib.h>
#define N 10
void Merge(int sort[],int num[],int low,int mid,int high)
{
	int i=low;		//左子序列起點下標
	int j=mid+1;	//右子序列起點下標
	int k=low;		//臨時數組的初始化下標
	while(i<=mid&&j<=high)//在左右子序列中按從小到大順序存到臨時數組中
	{
		if(num[i]<num[j])
			sort[k++]=num[i++];
		else
			sort[k++]=num[j++];
	}
	//將左右子序列剩餘的數依次存入臨時數組
	while(i<=mid)
		sort[k++]=num[i++];
	while(j<=high)
		sort[k++]=num[j++];
	//將臨時數組的數據按位置複製到原數組對應位置上
	while(--k>=0)
		num[k]=sort[k];
}
void MergeSort(int sort[],int num[],int low,int high)
{
	if(low<high)
	{
		int mid=(low+high)/2;			//分爲左右子序列的中間下標
		MergeSort(sort,num,low,mid);	//遞歸左子序列
		MergeSort(sort,num,mid+1,high);	//遞歸右子序列
		Merge(sort,num,low,mid,high);	//排序
	}
}
int main()
{
	int *sort;
	int num[N]={5,3,7,1,9,2,0,4,8,6};
	sort=(int*)malloc(N*sizeof(int));
	MergeSort(sort,num,0,N-1);
	for(int i=0;i<N;i++)
		printf("%d ",num[i]);
	printf("\n");
	free(sort);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章