/* 分治法简介 分治法的设计思想是,将一个难以直接解决的大问题,分割成一 分治策略是:对于一个规模为n的问题,若该问题可以容易地解决 如果原问题可分割成k个子问题,1<k≤n ,且这些子问题都可解 分治法所能解决的问题一般具有以下几个特征: 上述的第一条特征是绝大多数问题都可以满足的,因为问题的计算复 分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的 解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题 合并:将各个子问题的解合并为原问题的解。 它的一般的算法设计模式如下: 根据分治法的分割原则,原问题应该分为多少个子问题才较适宜? 答: 但人们从大量实践中发现,在用分治法设计算法时,最好使子问题的规模 出处:网络 */ /*** 编译环境TC ***/ #include <stdio.h> /* 分治法获取最优解 */ if(e-s <= 1){ /* 获取局部解,并更新全局解 */ printf("The array's element as followed:\n\n");
任何一个可以用计算机求解的问题所需的计算时间都与其规模
有关。问题的规模越小,越容易直接求解,解题所需的计算时间也
越少。例如,对于n个元素的排序问题,当n=1时,不需任何计算。
n=2时,只要作一次比较即可排好序。n=3时只要作3次比较即可,…。
而当n较大时,问题就不那么容易处理了。要想直接解决一个规模
较大的问题,有时是相当困难的。
些规模较小的相同问题,以便各个击破,分而治之。
(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的
子问题,这些子问题互相独立且与原问题形式相同,递归地解这些
子问题,然后将各子问题的解合并得到原问题的解。这种算法设计
策略叫做分治法。
并可利用这些子问题的解求出原问题的解,那么这种分治法就是可行
的。由分治法产生的子问题往往是原问题的较小模式,这就为使用递
归技术提供了方便。在这种情况下,反复应用分治手段,可以使子问
题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容
易直接求出其解。这自然导致递归过程的产生。分治与递归像一对孪
生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法。
1) 该问题的规模缩小到一定的程度就可以容易地解决
2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子
结构性质。
3) 利用该问题分解出的子问题的解可以合并为该问题的解;
4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公
共的子子问题。
杂性一般是随着问题规模的增加而增加;第二条特征是应用分治法的前提
它也是大多数问题可以满足的,此特征反映了递归思想的应用;第三条特
征是关键,能否利用分治法完全取决于问题是否具有第三条特征,如果具
备了第一条和第二条特征,而不具备第三条特征,则可以考虑用贪心法或
动态规划法。第四条特征涉及到分治法的效率,如果各子问题是不独立的
则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然可用
分治法,但一般用动态规划法较好。
分治法的基本步骤
分治法在每一层递归上都有三个步骤:
子问题;
Divide-and-Conquer(P)
1. if |P|≤n0
2. then return(ADHOC(P))
3. 将P分解为较小的子问题 P1 ,P2 ,...,Pk
4. for i←1 to k
5. do yi ← Divide-and-Conquer(Pi) △ 递归解决Pi
6. T ← MERGE(y1,y2,...,yk) △ 合并子问题
7. return(T)
其中|P|表示问题P的规模;n0为一阈值,表示当问题P的规模不超过n0时,问
题已容易直接解出,不必再继续分解。ADHOC(P)是该分治法中的基本子算法,
用于直接解小规模的问题P。因此,当P的规模不超过n0时直接用算法ADHOC(P)
求解。算法MERGE(y1,y2,...,yk)是该分治法中的合并子算法,用于将P的子问
题P1 ,P2 ,...,Pk的相应的解y1,y2,...,yk合并为P的解。
各个子问题的规模应该怎样才为适当?
大致相同。换句话说,将一个问题分成大小相等的k个子问题的处理方法是行之
有效的。许多问题可以取 k = 2。这种使子问题规模大致相等的做法是出自一
种平衡(balancing)子问题的思想,它几乎总是比子问题规模不等的做法要好。
实践题目:
给定一个顺序表,编写一个求出其最大值和最小值的分治算法。
分析:
由于顺序表的结构没有给出,作为演示分治法这里从简顺序表取一整形数组
数组大小由用户定义,数据随机生成。我们知道如果数组大小为 1 则可以
直接给出结果,如果大小为 2则一次比较即可得出结果,于是我们找到求解
该问题的子问题即: 数组大小 <= 2。到此我们就可以进行分治运算了,只要
求解的问题数组长度比 2 大就继续分治,否则求解子问题的解并更新全局解
以下是代码。
#include <stdlib.h>
#include <limits.h>
#define M 40
void PartionGet(int s,int e,int *meter,int *max,int *min){
/* 参数:
* s 当前分治段的开始下标
* e 当前分治段的结束下标
* meter 表的地址
* max 存储当前搜索到的最大值
* min 存储当前搜索到的最小值
*/
int i;
if(meter[s] > meter[e]){
if(meter[s] > *max)
*max = meter[s];
if(meter[e] < *min)
*min = meter[e];
}
else{
if(meter[e] > *max)
*max = meter[s];
if(meter[s] < *min)
*min = meter[s];
}
return ;
}
i = s + (e-s)/2; /* 不是子问题继续分治,这里使用了二分,也可以是其它 */
PartionGet(s,i,meter,max,min);
PartionGet(i+1,e,meter,max,min);
}
int main(){
int i,meter[M];
int max = INT_MIN; /* 用最小值初始化 */
int min = INT_MAX; /* 用最大值初始化 */
randomize(); /* 初始化随机数发生器 */
for(i = 0; i < M; i ++){ /* 随机数据填充数组 */
meter[i] = rand()%10000;
if(!((i+1)%10)) /* 输出表的随机数据 */
printf("%-6d\n",meter[i]);
else
printf("%-6d",meter[i]);
}
PartionGet(0,M - 1,meter,&max,&min); /* 分治法获取最值 */
printf("\nMax : %d\nMin : %d\n",max,min);
system("pause");
return 0;
}
正文
分治法2007-03-20 10:37:00
【评论】 【打印】 【字体:大 中 小】 本文链接:http://blog.pfan.cn/lingdlz/24118.html
阅读(5737) | 评论(0)
版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!
评论