一、简单介绍
- 说分治法之前我先来讲讲递归,那么,什么是递归呢?递归是指函数直接或者间接的调用自己,是一种解决问题的常见的方法;一般来说,递归有两个基本要素:第一个就是递归体,即大问题如何分解成小问题;第二个便是边界条件,即什么时候递归结束。
- 而分治算法的思想就是将一个难以直接解决的问题分成规模较小的相同问题也就是子问题,然后各个击破,分而治之。
- 由分治法产生的子问题与原问题类型一致,,但是规模却不断缩小,最终缩小到可以直接求得其解,这就导致递归的产生。
- 分治法的基本步骤:
1、分—将原问题分解成若干个小规模的子问题,如果子问题不够小,则继续分解,递归下去,一直到子问题足够小能够很容易的求解即可;
2、治—求出规模足够小的子问题的解;
3、合—将求出的小规模问题的解合并成更大规模的问题的解,然后自底而上的求出原问题的解。
二、举例说明
- 说到分治法首先想到的就是归并排序(Mergesort),是一个非常典型的分治法的应用。
- 将两个已排好序的数组合并成一个有序的数组,称为归并排序。
- 它的基本思想是将待排序的元素分成大小相同的两个子序列,然后分别对这两个子序列排序,然后将拍好的子序列合并成所要求的序列;
- 步骤:
1、分—将n个元素分成各含n/2个元素的子序列;
2、解—用归并排序递归的对两个子序列排序;
3、合—合并两个已经排好序的子序列,得到排序结果 - 时间复杂度为 O(nlogn).
- 代码块
void MergeSort(int a[], int l,int r){
int mid;
if(l<r){
mid=(l+r)/2;
MergeSort(a,l,mid) ;
MergeSort(a,mid+1,r);
Merge(a,l,mid,r);
}
}
void Merge(int a[],int l,int mid,int r){
int x=mid-l+1, y=r-mid, i,j,k;
int left[100],right[100];
for( i=0;i<x;i++ ){
left[i]=a[l+i];
}
for(j=0;j<y;j++){
right[i]=a[mid+j+1];
}
left[x]=INT_MAX;
right[y]=INT_MAX;
i=0; j=0;
for(k=l;k<r+1;k++){
if(left[i]<right[j]){
a[k]=left[i];
i++;
}
else{
a[k]=right[j];
j++;
}
}
}
三、小结
- 分治是一种思想,递归是一种手段;
- 归并排序比较占内存,但是是一种高效稳定的排序方法;它的速度仅次于快速排序,一般适用于总体无序,但是各子项有序的序列。