基本思想
将待排序的元素序列分成两个长度相等的子序列,对每一个子序列排序,然后将他们合并成一个序列。合并两个子序列的过程称为二路归并
int array[] = {21, 25, 49, 25, 16, 8, 31, 41};
代码实现
void _MergeSort(int *a, int left, int right, int *tmp)
{
if (left >= right)
return;
if (right - left + 1 < 20)
{
InsertSort(a + left, right - left + 1);//小区间优化:当数据个数(闭区间需要加1)小于20时,直接插入排序
return;
}
int mid = left + (right - left) / 2;
_MergeSort(a, left, mid, tmp);//将左边划分为有序
_MergeSort(a, mid + 1, right, tmp);//将右边划分语序
int begin1 = left, end1 = mid;
int begin2 = mid + 1, end2 = right;
int index = left;
// begin1--end1是有序区间 begin2--end2是有序区间
//将两段有序区间合并为一段有序区间
while (begin1 <= end1 && begin2 <= end2)
{
//把小的数据放在tmp中
if (a[begin1] <= a[begin2])//等于号保证归并是稳定的
{
tmp[index] = a[begin1];
index++;
begin1++;
}
else
{
tmp[index] = a[begin2];
index++;
begin2++;
}
}
if (begin1 > end1)//说明begin2-end2还有数据
{
while (begin2 <= end2)
tmp[index++] = a[begin2++];
}
else //说明begin1 - end1还有数据
{
while (begin1 <= end1)
tmp[index++] = a[begin1++];
}
index = left;
while (index <= right)//由于tmp只是个临时数组,需要将有序数据重新放到数组a中
{
a[index] = tmp[index];
index++;
}
}
void MergeSort(int *a, int n)
{
assert(a);
int *tmp = (int *)malloc(sizeof(int)*n);
_MergeSort(a, 0, n - 1, tmp);//tmp是临时数组
free(tmp);
tmp = NULL;
}
时间复杂度及稳定性
由于归并排序不依赖于待排序元素序列的初始输入状态,每次划分时两个子序列的长度基本一致,所以归并排序的最好、最差和平均时间复杂度均为O( n*log2 n)
稳定性:稳定