分治策略
分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。
分治算法的特征
1.该问题的规模缩小到一定的程度就可以容易地解决
2.该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质
3.利用该问题分解出的子问题的解可以合并为该问题的解
4.该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共子问题
这条特征涉及到分治法的效率,如果各子问题不独立,
则分治法要做很多不必要的工作,重复解公共的子问题,
此时虽然也可以用分治法,但一般用动态规划比较好
分治算法的设计模式
divide-and-conquer(P)
{
if(|P|<=n0) adhoc(P); //解决规模较小的子问题
divide P into smaller subinstances P1,P2...PK; //分解原问题
for(i=1;i<=k;i++)
yi=divide-and-conquer(Pi); //递归求解子问题
return merge(y1,y2,...yk); //合并子问题的解
}
二分搜索问题
**算法基本思想**
将n个元素分成个数大致相同的两半,取a[n/2]与x比较。
如果x=a[n/2],则找到x,算法终止;
如果x<[n/2],则在数组a的左半部分继续搜索x;
如果x>[n/2],则在数组a的右半部分继续搜索x。
具体代码如下:
template<class Type>
int BinarySearch(Type a[ ],const Type &x, int n)
{
int j,left = 0;
int right = n-1;
while(left<=right)
{
int middle = (left + right) /2;
if(x<a[middle]) right = middle-1;
if(x>a[middle]) left = middle+1;
else j=middle;
return
}
j=0;
return -1;
}
**算法复杂度分析**
每执行一次算法的while循环,待搜索数组的大小减少一半
在最坏情况下while循环被执行了O(logn)次,循环体内运算需要O(1)时间
因此整个算法在最坏情况下的计算时间复杂性为O(logn)
W(n) = W(n/2)+1
W(1) = 1
解出
W(n) = logn+1
归并排序问题
**算法基本思想**
首先将待排序的n个元素分成大小大致相同的两个子集合,
然后分别对这两个子集合进行排序,
最后将排好序的子集合归并成为所要求的排好序的集合
具体代码如下:
template<class Type>
void MergeSort(Type a[ ],int left, int right)
{
if(left<right) //至少有两个元素
{
int i = (left+right)/2 //取中点
MergeSort(a,left,i);
MergeSort(a,i+1,right);
Merge(a,b,left,i,right); //归并到辅助数组b[ ]
Copy(a,b,left,right); //将数组b[ ]中已经排好的元素复制回原数组a[ ]中
}
}
算法时间复杂度分析
W(n)= 2W(n/2)+n-1
W(1)= 0
可以解出
W(n)= nlogn-n+1