<!-- /* Font Definitions */ @font-face {font-family:Wingdings; panose-1:5 0 0 0 0 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;} @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"/@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:宋体; mso-font-kerning:1.0pt;} p.MsoBodyTextIndent, li.MsoBodyTextIndent, div.MsoBodyTextIndent {margin-top:0cm; margin-right:0cm; margin-bottom:6.0pt; margin-left:21.0pt; mso-para-margin-top:0cm; mso-para-margin-right:0cm; mso-para-margin-bottom:6.0pt; mso-para-margin-left:2.0gd; text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:宋体; mso-font-kerning:1.0pt;} /* Page Definitions */ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page Section1 {size:595.3pt 841.9pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:42.55pt; mso-footer-margin:49.6pt; mso-paper-source:0; layout-grid:15.6pt;} div.Section1 {page:Section1;} /* List Definitions */ @list l0 {mso-list-id:1085105504; mso-list-type:hybrid; mso-list-template-ids:-799214760 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} @list l0:level1 {mso-level-tab-stop:21.0pt; mso-level-number-position:left; margin-left:21.0pt; text-indent:-21.0pt;} @list l1 {mso-list-id:1095444230; mso-list-type:hybrid; mso-list-template-ids:427086508 619207814 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} @list l1:level1 {mso-level-tab-stop:18.0pt; mso-level-number-position:left; margin-left:18.0pt; text-indent:-18.0pt;} @list l2 {mso-list-id:1303386913; mso-list-type:hybrid; mso-list-template-ids:309083194 366651248 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} @list l2:level1 {mso-level-number-format:alpha-lower; mso-level-text:"/(%1/)"; mso-level-tab-stop:18.75pt; mso-level-number-position:left; margin-left:18.75pt; text-indent:-18.75pt;} ol {margin-bottom:0cm;} ul {margin-bottom:0cm;} -->
分治法
讲解人:
一 、分治法是什么 : 分治法就是把原问题分成若干子问题 , 对每个子问题分别求解 , 然后把这些解连结成原问题的解。 如果子问题依然复杂 , 则我们可以使用递归 , 来简化问题。
二 、使用分治法的难处 : a. 哪些问题使用分治法并没有明确的准则 b. 分成多少的子问题 ? 子问题的尺度多大 ? 也不易确定。
三 、例子 :
例 6 设集合 S 有 n 个元素 , 求 S 的最大和最小元素。为简单起见 , 设 n = 2m , m>=0 。
求集合 S 的最大元素 , 可以采用下述算法。
-----------------------------------------------------------------------------------------------------
Procedure MAX(S)
begin
MAX ß S 中的任一元素
for S 中的所有其它元素 x do
It X > MAX then MAX ß x
end
-----------------------------------------------------------------------------------------------------
结论 : 利用此算法 , 进行 n - 1 次比较后就可以求出 S 的最大元素。用 n - 2 次比较就可以求出剩下的 n - 1 个元素的最小元素。所以如果要找出 S 中的最大和最小元素 , 总共要进行 ( n – 1 ) + ( n – 2 ) = 2n - 3 次比较。
* 如果我们使用分治法来改善此算法 , 则可以减少比较的次数。
(a) 把 S 分成大小相等的两个子集 S1 和 S2 , 所以 S1 与 S2 各有 n / 2 = 2m-1 个元素。
(b) 对 S1 和 S2 分别反复使用分治法 , 求出最大及最小元素。
(c) 比较 S1 和 S2 所求出的最大及最小元素 , 就可以得到 S 的最大及最小元素。
-----------------------------------------------------------------------------------------------------
produce MAXMIN(S)
begin
1. if ||S|| = 2 then
begin
2. let S = {a, b}
3. return (MAX(a, b), MIN(a, b))
end
else
begin
4. 分 S 成两个子集 S1 和 S2 , 且 ||S1 || = ||S2 || = 1/2||S||
5. (max1, min1) ß MAXMIN(S1 )
6. (max2, min2) ß MAXMIN(S2 )
7. return (MAX(max1, max2), MIN(min1, min2))
end
end
-----------------------------------------------------------------------------------------------------
结论 : 如果 S 只有两个元素 , 那就在第 3 行进行一次比较 , 如果 S 有两个以上的元素 , 则至第四行将 S 分成两个子集 , 并在 5, 6 行递归使用 MAXMIN, 第 7 行比较 max1, max2 及 min1, min2 。设 S 有 n 个元素 , 则 n = 2 时 , T(2) = 1, n > 2 时 , T(n) = 3/2n - 2 , 就是说明了在 n 个元素的集合中寻找最大及最小元素至少要进行 (3/2n – 2) 次 , 所以使用分治法可以减少比较的次数 , 优于上一个算法。
|
T(n) = aT(n/c) + bn n > 1
|
O(n) a < c
|
O(n ) a > c
例 7 :两个无向图的同构问题
同构概念: G=(V,E), G’=(V’,E’) 同构,记成 G ≌ G’ ,则从 v ∈V到v ’ ∈ V’ 存在一一对应关系 f ,且 (u,v) ∈ E < —— > (f(u),f(v)) ∈E ’
方法一:穷举法
设两个无向图各有 n 个结点,则需要一一对应函数 10! 个,逐一对其进行计算
方法二:通过考查图的不变量来证明
不变量(包括结点的数目,边的数目,度数的序列表,边的方向)是图的一个重要性质,凡是与图 G 同构的图均有相同的不变量,只要有一个不变量不同,则不同构。
但注意:对所列不变量经过比较发现都相等,不能断定两图是同构的(如下图)。
因此,判定不变量也不是一件容易的事情
方法三:考虑邻接矩阵
如果两个无向图 G1 , G2 是同构的, G1 →A( G1 ), G2 →A( G2 ), 则存在 G1 结点的某一置换,使 A(G1 ) 和 A(G2 ) 相同,但寻找这一置换,在最坏情况下要 O(n!) 次运算。
方法四:邻接矩阵幂匹技术( APM 技术)
计算 A2 (Gi ) , I=1 、 2 。对所得两个矩阵 A2 (Gi ) 的行和列的次序同时进行重新排列,使主对角线上的元素以递减次序排列。如果两者的主对角线上元素对应相同,则求 A3 (Gi ),…Ak (Gi ),I=1 、 2 。当某一对 Ai (G1 ), Ai (G2 ) 主对角线上出现的元素不相同时,则可断定 G1 和 G2 不同构
如上例:
例 9 分析:
问题:给定两个 N-1 阶多项式(有 N 项) P(x) 和 Q(x) ,求 P(x)*Q(x) 。
算法分析:
1. 采用一般的算法:做两个 N 次的循环的乘法, M(N2 ) ,再进行归并、加法。
2. 采用分治算法:算法的思想是:利用分治法,将 P 、 Q 两个 N 项的多项式分别分解为在形式上一致的两个 N/2 (或 N/2+1 )项的多项式,即 P->P1 , P2 ; Q->Q1 , Q2 ,就是把 P 、 Q 的一半高 N/2 阶的多项式降阶。分治后,算式变为:
P(x)=P0 (x)+xN/2 P1 (x)
Q(x)=Q0 (x)+xN/2 Q1 (x)
P(x)*Q(x)=P0 (x)*Q0 (x)+(P0 (x)*Q1 (x)+P1 (x)*Q0 (x))*xN/2 +P1 (x)*Q1 (x)*xN ………(1)
对 P0 (x)*Q1 (x)+P1 (x)*Q0 (x) 做变换,用一个乘法和四个加法代替了两个乘法和一个加法,这样就大大节省了乘法的计算时间。
R0 (x)= P0 (x)*Q0 (x) , R1 (x)= P1 (x)*Q1 (x) , R2 =( P0 (x)+ P1 (x))*( Q0 (x)+ Q1 (x))
P(x)*Q(x)=R0 (x)+R1 (x)xN +(R2 (x)-R1 (x)-R0 (x))*xN/2 ……………………...(2)
现在让我们重新观察 (2) 式,发现 R0 , R1 , R2 实际上是三个 N/2 (或 N/2+1 )项的多项式,既然是这样,那么分别对 R0 , R1 , R2 再使用分治法,进一步降阶;。。。。。。
如此递归循环,当多项式分解为 0 阶时,就可以求出最终的结果。
设两个 N-1 阶多项式相乘需要的整数乘法次数为 M(N) ,由 (2) 式可以看出, M(N) 是两个 N/2-1 阶多项式相乘所需要的整数乘法次数的 3 倍,即 M(N)=3M(N/2) ,运用自然归纳法, M(N)=3 log2 N =N log2 3 =N1.58 <N2
可见,分治法对算法的较大改进。
采用分治法计算的过程实例请参见书 P61~P62 。
例 10 ―矩阵乘法
一、问题提出 :普通方法求解 n × n 矩阵需要 n3 次整数乘法和 n3 -n2 次加法。
二、思想方法 :减少乘法次数,斯特拉森提出分治法求解矩阵乘法的方法,给定 n × n 并设 n=2m ,分成 4 个
×
矩阵,不断分下去,一直分到 2 × 2 的矩阵乘积。如用一般方法,求两个 2 × 2 矩阵要 8 次乘法,如果减少到 7 次,则
和
比较 说明 :分治法比普通法快
备注: 7 次乘法不能减小到更少
三、方法( 8 次减少到 7 次):
思想: C11 和 C22 , C12 和 C21 每个要经过 2 个乘法,我们考虑能否其中 1 个乘法由别的已经做的乘法来替代,这样乘法的总数就能减少到 7 个。
变形
变形
通过观察:
和
脚标对称
设想:如果
和
中的某一项乘法不受脚标影响,也就是说进行脚标变换后,其中某一项的乘积还是不变,则值不变的项可以不计算了,从而减少一次计算。
脚标变换后,乘积不变的项:
改写
使之含
,
(※)
脚标变换(※)式
(只增加了一项
)
总结: 这样完成 2 × 2 矩阵相乘用了 7 次乘法, 18 次加法和减法
缺点: 因为可以证明在 120 阶以上才比一般算法快,在 40 阶以下不如普通算法。