归并操作的基本模式如下:
分解:把一个问题分解成与原问题相似的子问题
解决:递归的解各个子问题
合并:合并子问题的结果得到了原问题的解
分解,递归
void mergeSort(int data[],int low,int high)
{
if (high > low)
{
int mid = (high + low)/2;
mergeSort(data,low,mid);
mergeSort(data,mid+1,high);
merge(data,low,mid,high);
}
}
整个执行过程如上图。
代码如下:
/************************************************************************
*归并排序,是将数组分成二组A,B,然后将A,B组各自再分成二组,
*依次类推,直到每个数组元素单独成为一个数组为止。
*单个元素的数组,相当于数组已经有序。如果两组组内的数据都是有序的,
*那么就可以将二组有序数据进行合并排序。
*这样通过先递归的分解数列,再合并数组就完成了归并排序。
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
void merge(int[],int,int,int);
void mergeSort(int[],int,int);
void print(int[],int);
void mergeSort(int data[],int low,int high)
{//对整个数组进行分裂,直到每个子数组都只含有一个元素为止
if (high > low)
{//进行递归分裂操作
int mid = (high + low)/2;
mergeSort(data,low,mid);
mergeSort(data,mid+1,high);
merge(data,low,mid,high);
}
}
void merge(int data[],int low,int mid,int high)
{//进行归并操作
int lLen=mid-low+1;
int rLen=high-mid;
int *leftArr=(int*)malloc(sizeof(int)*(lLen+1));
int *rightArr=(int*)malloc(sizeof(int)*(rLen+1));
for (int i=0;i<lLen;i++)
{//用一个数组将分裂后的左数组存进来
leftArr[i]=data[low+i];
}
for (int j=0;j<rLen;j++)
{//用一个数组将分裂后的右数组存进来
rightArr[j]=data[mid+1+j];
}
int i=0,j=0;
int k=low;
while (i<lLen && j<rLen)
{//比较两个数组的元素,进行合并
if (leftArr[i]<rightArr[j])
{
data[k++]=leftArr[i++];
}else
{
data[k++]=rightArr[j++];
}
}
while (i<lLen)
{//当右数组已经全部存进data数组以后,左数组依然还有元素,将左数组剩余依次放到data数组最后
data[k++]=leftArr[i++];
}
while (j<rLen)
{//当左数组已经全部存进data数组以后,右数组依然还有元素,将右数组剩余依次放到data数组最后
data[k++]=rightArr[j++];
}
free(leftArr);
free(rightArr);
}
void print(int data[],int num)
{
for (int i=0;i<num;i++)
{
printf("%d ",data[i]);
}
printf("\n");
}
int main()
{
int data[]={0,9,8,7,6,5,4,3,2,1};
int num = sizeof(data)/sizeof(int);
printf("----------归并排序----------\n");
print(data,num);
mergeSort(data,0,num-1);
print(data,num);
return 0;
}