归并排序是 Divide-and-Conquer 编程思想一个简单例子,其逻辑核心主要有以下几点。
(1) 将两个有序数列合并的时间复杂度为 O(n),参见函数 void merge(int *src, int st, int md, int ed, int *sorted);
(2) 数列中只有一个数的时候,数列处于有序状态。
下面是归并排序的示例代码。
#include <stdio.h>
#include <stdlib.h>
void merge(int *src, int st, int md, int ed, int *sorted){
int i=st, j=md;
int k=0;
while(i<md && j<ed){
if(src[i]<src[j]){
sorted[k++]=src[i++];
}else{
sorted[k++]=src[j++];
}
}
while(i<md){
sorted[k++]=src[i++];
}
while(j<ed){
sorted[k++]=src[j++];
}
i=st;
k=0;
while(i<ed){
src[i++] = sorted[k++];
}
}
void merge_sort(int *src, int st, int ed, int *sorted){
if(st+1<ed){
int md = (st+ed)/2;
merge_sort(src, st, md, sorted);
merge_sort(src, md, ed, sorted);
merge(src, st, md, ed, sorted);
}
}
int main(){
int to_sort[15] = {2, 8, 12, 1, 4, 3, 6, 12, 15, 1, 4, 7, 19, 10, 9};
int *src = to_sort;
int i = 0;
printf("The array before sorting is:\n");
for(i=0; i<15; ++i){
printf("%d ", src[i]);
}
printf("\n");
int *sorted = (int *)malloc(15*sizeof(int));
merge_sort(src, 0, 15, sorted);
printf("The array after sorting is:\n");
for(i=0; i<15; ++i){
printf("%d ", sorted[i]);
}
printf("\n");
free(sorted);
sorted = NULL;
return 0;
}
使用动态内存实现归并排序时,可以使逻辑更加清晰,但在递归过程中反复申请、释放内存,会频繁产生内存的缺页中断,增加程序执行时间,降低性能。
#include <stdio.h>
#include <stdlib.h>
void merge(int *target, int st, int md, int ed){
if(st > md || md > ed){
return;
}
int llen = md - st;
int rlen = ed - md;
int *left = (int*) malloc(llen*sizeof(int));
int *right = (int*) malloc(rlen*sizeof(int));
int i=0, j=0, k=0;
for(i=0; i<llen; ++i){
left[i] = target[st+i];
}
for(i=0; i<rlen; ++i){
right[i] = target[md+i];
}
i=0;
j=0;
for(k=st; k<ed; ++k){
if(i<llen && j<rlen){
if(left[i]<=right[j]){
target[k] = left[i];
++i;
}else{
target[k] = right[j];
++j;
}
}else{
break;
}
}
while(i<llen){
target[k++] = left[i++];
}
while(j<rlen){
target[k++] = right[j++];
}
free(left);
left = NULL;
free(right);
right = NULL;
}
void merge_sort(int *target, int st, int ed){
if(st>ed || st<0){
return;
}
int md = (st+ed)/2;
if(st+1<ed){
merge_sort(target, st, md);
merge_sort(target, md, ed);
merge(target, st, md, ed);
}
}
int main(){
int to_sort[15] = {2, 8, 12, 1, 4, 3, 6, 12, 15, 1, 4, 7, 19, 10, 9};
int *target = to_sort;
int i = 0;
printf("The array before sorting is:\n");
for(i=0; i<15; ++i){
printf("%d ", target[i]);
}
printf("\n");
merge_sort(target, 0, 15);
printf("The array after sorting is:\n");
for(i=0; i<15; ++i){
printf("%d ", target[i]);
}
printf("\n");
return 0;
}