分治法,字面意思是“分而治之”
把一个问题分成两个或者多个相似的子问题再把子问题分成更小的子问题……直到最后子问题可以简单的直
接求解,原问题的解即子问题的解的合并。这就是分治法,当然这些肯定是我从百度上抄的。
分治法分为以下三个步骤:
(1)将原问题分解为多个子问题。
(2)对子问题递归求解。
(3)将子问题合并为原问题的解
例如:使用分治法求解数组中的最大值:
#define Type int;
Type FindMax(Type arr[], int left, int right) {
assert(arr);
int mid = left + (right - left) / 2;
//递归出口
if(left >= right) {
return arr[l];
}
Type a = FindMax(arr, left, mid);
Type b = FindMax(arr, mid + 1, right);
if(a > b) {
return a;
}
else {
return b;
}
}
这个函数是把数组分为两部分,(0, mid), (mid + 1, right)两部分然后求出这两部分的最大值,再进行比较得出最大值,这就是分治法的典型,把N个问题分成两个独立(非空)部分去处理,分而治之
还有使用分治法给一个尺子画刻度值:
void Rule(int left, int right ,int high) {
int mid = left + (right - left) / 2;
if(h <= 0) {
return;
}
rule(left, mid ,high - 1);
Mark(mid, high);
rule(mid + 1, high, high - 1);
}
差不多是这样了,画的有点丑,凑合着看,这个函数通过递归,先画(0, 4)范围的刻度,再画(5, 8)范围的刻度,然后再这样递归,先左边再右边,最后整个刻度就画好了,这就是分治法
其实分治法在计算机科学中应用十分广泛,包括二分查找,归并排序,快速排序,画一个Koch星等等,应用十分广泛。
这是我总结的排序算法的博客,里面有快速排序,归并排序的代码及思路:
http://blog.csdn.net/Qregi/article/details/79470632
这是我总结的关于经典问题汉诺塔的博客:
http://blog.csdn.net/qregi/article/details/79518303
这些都是跟分治法的思想有关
分治法因为具体处理的方法不同,分为以下两种:
(1)自顶向下方法
自顶向下很好理解,一般分治法的思路都是如此,把一个大问题分成若干个相同的子问题,循环的去处理若干个子问题,最后子问题解一合并就是原问题的解。
例如上面的求数组中的最大值和给尺子画刻度都是自顶向下的方法
(2)自底向上方法
而自底向上,则是先解决平凡的子问题,然后把这些子问题的解合起来解决稍大的问题直到解决整个问题,这样的方法称为——组合-分治法
例如下面的程序:
void Rule(int left, int right, int high) {
if(left > right || high <= 0) {
//非法输入
return;
}
int i = 0;
int j = 1;
int t = 1;
for(; t <= high; j += j, t++) {
for(; l + j + i <= r; i += j + j) {
Mark(l + j + i, t);
}
}
}
图太难画了,就不画具体的图了,这个程序是交替画长度为1的刻度线,跳过一些位置,然后交替画长度为2的刻度线,跳过一些位置,然后交替画长度为3的刻度线,跳过一些保留的位置,以此类推,最后一个尺子的刻度线就完成了, Mrak是画刻度的函数,第一个参数是刻度的位置,第二个参数是刻度的高度。
一开始上面的程序是,先画左半部分,再画右半部分,这个程序是依次画最短的刻度,再画较长的,直到合格刻度尺被画完了,就成功了。
以上就是我对分治法的一些了解,其实分治法主要是一种思想,具体的应用很多,如何应用到处理问题中才是重中之重。