#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void display(int* a, size_t size)
{
for(int i = 0; i<=size-1; i++)
printf("%d ", a[i]);
printf("\n");
}
void Merge(int* a, int lo, int mid, int hi)
{
int* tmp = (int*)malloc((hi-lo+1)*sizeof(int));
int left_lo = lo;
int left_hi = mid;
int right_lo = mid+1;
int right_hi = hi;
int k = 0;
for(; (left_lo<=left_hi)&&(right_lo<=right_hi); k++)
{
if(a[left_lo]<=a[right_lo])
tmp[k] = a[left_lo++];
else
tmp[k] = a[right_lo++];
}
if(left_lo<=left_hi)
memcpy(tmp+k, a+left_lo, (left_hi-left_lo+1)*sizeof(int));
if(right_lo<=right_hi)
memcpy(tmp+k, a+right_lo, (right_hi-right_lo+1)*sizeof(int));
memcpy(a+lo, tmp, (hi-lo+1)*sizeof(int));
display(tmp, (hi-lo+1));
}
void MergeSort(int* a, int lo, int hi)
{
if (lo == hi)
return;
int mid = (lo+hi)/2;
MergeSort(a, lo, mid);
MergeSort(a, mid+1, hi);
Merge(a, lo, mid, hi);
return;
}
int main()
{
int a[] = {1,3,5,2,4,6,7,2,3,5,9};
display(a, sizeof(a)/sizeof(int));
MergeSort(a, 0, sizeof(a)/sizeof(int)-1);
display(a, sizeof(a)/sizeof(int));
}
递归函数调用过程:
以输入A[] = {2,3,1,9,5}为例,函数的调用过程如下:
A = [2,3,1,9,5]
MergeSort(A, 0, 4)
{
mid = 4/2 = 2
MergeSort(A, 0, 2);
{
mid = 2/2 = 1
MergeSort(A, 0, 1);
{
mid = 1/2=0;
MergeSort(A, 0, 0)
{
return;
}
MergeSort(A, 1,1);
{
return;
}
Merge(A, 0, 0, 1);
}
MergeSort(A, 2, 2);
{
return;
}
Merge(A, 0, 1, 2);
}
MergeSort(A, 3, 4)
{
mid = 7/3 = 3;
MergeSort(A, 3, 3)
{
return;
}
MergeSort(A, 4,4)
{
return;
}
Merge(A, 3,3,4);
}
Merge(A, 0, 2, 4);
}
因此它是一边分解一边合并的。
在网上看到一张图很形象:
时间复杂度:
分解过程:前四行, 时间复杂度为O(logn)+1
合并过程:后四行, 时间复杂度计算:
由第四行到第五行:一共需要合并(1/2)*n次, 每次合并时,都有一次比较操作和一次append操作,操作数为2, 因此,复杂度为2*(1/2)*n = O(n)
由第五行到第六行:合并(1/4)*n次, 每次合并时, 有两次比较操作和两个append操作,操作数为4, 因此复杂度仍然为O(n).
由此类推,每层合并过程的时间复杂度都为O(n), 合并过程一共有(logn+1)层,因此整个合并过程的时间复杂度为:O(nlogn)
O(nlogn+logn) = O(nlogn)