歸併排序
歸併排序(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;
}