什么是归并排序?
归并排序采用了分治法(divide-and-conquer),将原问题分解为一些规模较小的相似子问题,然后递归解决这些子问题,最后合并其结果作为原问题的解。归并排序的算法通常用递归实现,将带排序的区间[a,b]二分,再二分,直至每个小区间只有一个元素,则每个小区间都是有序的,将小区间两两有序合并,直至成为一个区间,此时该区间是有序的。
完成归并排序主要有两个步骤:一是使用递归不断的二分区间
一是将两个有序区间合并为一个有序区间,需要一个临时变量tmp,两个区间的第一个数字进行比较,谁小,谁放在tmp的第一个位置,依次类推。
void _MergeSort(int* a,int left,int right,int* tmp)
{
if(left >= right)
return;
//不断二分区间
int mid = left + ((right-left)>>2);//移位操作比除法更高效
_MergeSort(a,left,mid-1,tmp);
_MergeSort(a,mid+1,right,tmp);
//合并区间:每次递归返回都进行合并两个区间
int begin1 = left, end1 = mid;
int begin2 = mid+1, end2 = right;
size_t index = left;
while(begin1 <= end1 && begin2 <= end2)
{
if(a[begin1] < a[begin2])
tmp[index++] = a[begin1++];
else
tmp[index++] = a[begin2++];
}
while(begin1 <= end1)
tmp[index++] = a[begin1++];
while(begin2 <= end2)
tmp[index++] = a[begin2++];
//将tmp中的数据拷贝到a中
memcpy(a+left,tmp+left,sizeof(int)*(right-left+1));
}
void MergeSort(int* a,size_t n)
{
int* tmp = new int[n];
_MergeSort(a,0,n-1,tmp);
delete[] tmp;
}
void TestMergeSort()
{
int a[] = {12,34,78,56,9,3,7,21};
MergeSort(a,sizeof(a)/sizeof(a[0]));
PrintArray(a,sizeof(a)/sizeof(a[0]));
}
运行结果:
时间复杂度:
设数列长度为N,将数列分为小数列共需:2^x = N , x = logN步,每步都是合并有序数列的过程,其时间复杂度为O(n),则总的时间复杂度为O(n*logn)。