分治的基本概念:
把一个任务,分成形式和原任务相同,但规模更小的几个部分任务(通常是两个部分),分别完成,或只需要选择一部完成。然后再处理完成后的这一个或几个部分的结果,实现整个任务的完成。
归并排序是典型的分治问题。
归并排序(Merge)是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。归并排序算法稳定,数组需要O(n)的额外空间,链表需要O(log(n))的额外空间,时间复杂度为O(nlog(n)),算法不是自适应的,不需要对数据的随机读取。
实现思想:
1、把前一半排序;
2、把后一半排序;
3、把两半归并到一个新的有序数组,然后再拷贝回原数组,排序完成。
算法实现:
void Merge(int a[],int s,int m,int e,int tmp[])//排序
{
int pb = 0;//tmp[]是周转数组,pb指向tmp[]
int p1 = s,p2 = m + 1;//p1指向前一半;p2指向后一半
while(p1 <= m && p2 <= e)
{
if(a[p1] < a[p2])//将相对小的放进tmp[]中
{
tmp[pb++] = a[p1++];
}
else
{
tmp[pb++] = a[p2++];
}
}
while(p1 <= m)
{
tmp[pb++] = a[p1++];
}
while(p2 <= e)
{
tmp[pb++] = a[p2++];
}
for(int i = 0;i < e - s + 1;i++)
{
a[s + i] = tmp[i];
}
}
void MergeSort(int a[],int s,int e,int tmp[])
{
if(s < e)
{
int m = s + (e - s)/2;
MergeSort(a,s,m,tmp);
MergrSort(a,m + 1,e,tmp);
Merge(a,s,m,e,tmp);
}
}