思路:
使用分治思想,将问题分成一些小问题然后递归求解,再将各个小问题的解归并到一起。
使用递归,将一个数组不断分为两个更小的子数组,递归对更小的子数组排序。然后将已排序的两个子数组合并到一个新数组(这里需要额外使用一个同样大小的新数组),再将排序好的新数组中的元素拷贝回原数组。
基本操作是合并两个已经排序的数组,使用三个计数器Apos,Bpos,Cpos 初始值分别位三个数组的A,B,C的开始位置,比较A[Apos]和B[Bpos]的大小,并将较小者输出到C[Cpos ],然后计数器增加。当两个数组A和B有一个为空,则将另一个数组剩余部分拷贝到C中。
如果在merge方法中声明一个临时数组,由于merge会被递归调用很多次,在递归期间就会生成很多临时数组,占用一部分内存;另一个方面,在声明数组的过程中调用malloc 和free 分配并释放内存,也会占用一些时间。所以这里在排序算法的驱动程序中就申请一个同样大小的临时数组,在后面递归调用merge方法中共享使用。
时间复杂度:
平均: ,最好:
,最坏:
程序:
void merge(int array[],int tmp_array[],int left,int center,int right)
{
int i,left_pos,right_pos,tmp_pos,length;
length=right-left+1;
left_pos=left;
right_pos=center+1;
tmp_pos=left;
while(left_pos<=center&&right_pos<=right) //将两个数组中的较小者输出到第三个数组
if(array[left_pos]<array[right_pos])
tmp_array[tmp_pos++]=array[left_pos++];
else
tmp_array[tmp_pos++]=array[right_pos++];
while(left_pos<=center) //将第一个数组中剩余元素拷贝到第三个数组
tmp_array[tmp_pos++]=array[left_pos++];
while(right_pos<=right)
tmp_array[tmp_pos++]=array[right_pos++]; //将第二个数组中剩余元素拷贝到第三个数组
for(i=0;i<length;i++) //将第三个数组中的元素拷贝回原数组中
array[left+i]=tmp_array[left+i];
}
void merge_sort_recurise(int array[],int tmp_array[],int left,int right)
{
int center;
if(left<right)
{
center=(left+right)/2;
merge_sort_recurise(array,tmp_array,left,center);
merge_sort_recurise(array,tmp_array,center+1,right);
merge(array,tmp_array,left,center,right);
}
}
void merge_sort(int array[],int array_size)
{
int *tmp_array=calloc(array_size,sizeof(int));
if(tmp_array==NULL)
{
printf("No full space for array!\n");
return;
}
merge_sort_recurise(array,tmp_array,0,array_size-1);
free(tmp_array);
}
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
int array[]={100,96,88,75,63,52,41,36,28,19,6,0,-19,-105};
int array_size=sizeof(array)/sizeof(int);
printf("Original array:\n");
for(i=0;i<array_size;i++)
printf(" %d, ",array[i]);
printf("\n");
merge_sort(array,array_size);
printf("Sorted array:\n");
for(i=0;i<array_size;i++)
printf(" %d, ",array[i]);
printf("\n");
return 0;
}