算法-分治法ppt课件
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第4章 分治法
分治法是最著名的算法设计技术。
4.1 概 述 4.2 排序问题中的分治法 4.3 组合问题中的分治法 4.4 几何问题中的分治法
2020/4/16
分治法
1/56
4.1 概 述
4.1.1 分治法的设计思想 4.1.2 数字旋转方阵
2020/4/16
分治法
2/56
4.1.1 分治法的设计思想
66的旋转方阵
2020/4/16
分治法
8/56
4.2 排序问题中的分治法
4.2.1 归并排序 4.2.2 快速排序
2020/4/16
分治法
9
4.3.1 归并排序
二路归并排序的分治策略是: (1)划分:将待排序序列r1, r2, …, rn划分为两个 长度相等的子序列r1, …, rn/2和rn/2+1, …, rn; (2)求解子问题:分别对这两个子序列进行排 序,得到两个有序子序列; (3)合并:将这两个有序子序列合并成一个有 序序列。
2020/4/16
分治法
5/56
分治法的典型情况
原问题 的规模是n
子问题1 的规模是n/2
子问题1的解
子问题2 的规模是n/2
子问题2的解
原问题的解
2020/4/16
分治法
6/56
例:计算an,应用分治技术得到如下计算方法:
分析时 间性能
an
a
=
a
n
2
a n 2
34
如果 n = 1 如果 n > 1
r[i]=r1[i];
}
}
2020/4/16
分治法
12/56
二路归并排序的合并步的时间复杂性为O(n), 所以,二路归并排序算法存在如下递推式:
T (n)
=
1
2T
(n
2)
+n
n =1 n >1
可得二路归并排序的时间代价是O(nlog2n)。
二路归并排序在合并过程中需要与原始记录序列同 样数量的存储空间,因此其空间复杂性为O(n)。
算法4.3——归并排序
void MergeSort(int r[ ], int s, int t)
{ int m, r1[1000]; if (s= =t) return;
else { m=(s+t)/2; Mergesort(r, s, m); //归并排序前半个子序列 Mergesort(r, m+1, t); //归并排序后半个子序列 Merge(r, r1, s, m, t); //合并两个已排序的子序列 for (int i=s; i<=t; i++) //将有序序列传回数组r中
2020/4/16
分治法
10/56
r1 … … rn/2 rn/2+1 … … rn r‘1<… …<r’n/2 r’n/2+1<… …<r’n
划分 递归处理
r''1<……<r''n/2<r''n/2+1 <……<r ''n
合并解
举例:8 3 2 6 7 1 5 4
2020/4/16
分治法
11/56
r1[k++]=r[j++]; }
2020/4/16
分治法
14/56
4.3.2 快速排序
快速排序的分治策略是: (1)划分:选定一个记录作为轴值,以轴值为基准 将整个序列划分为两个子序列;
(2)求解子问题:分别对划分后的每一个子序列 递归处理; (3)合并:由于对子序列r1 … ri-1和ri+1 … rn的排序 是就地进行的,所以合并不需要执行任何操作。
2020/4/16
分治法
18
算法4.5——一次划分
int Partition(int r[ ], int first, int end)
(2)右侧扫描过程:
(3)左侧扫描过程:
(4)重复(2)(3)步,直到i与j指向同一位置,即基准记 录最终的位置。
2020/4/16
分治法
17
一次划分示例
38 27 55 50 13 49 65
i
jj
j
13 27 55 50 38 49 65
i
ii
j
13 27 38 50 55 49 65
ij j j
2020/4/16
分治法
13/56
算法4.4——合并有序子序列
void Merge(int r[ ], int r1[ ], int s, int m, int t) {
i=s; j=m+1; k=s; while (i<=m && j<=t) {
if (r[i]<=r[j]) r1[k++]=r[i++]; //取r[i]和r[j]中较小者放入r1[k] else r1[k++]=r[j++]; } if (i<=m) while (i<=m) //若第一个子序列没处理完,则进行收尾处理 r1[k++]=r[i++]; else while (j<=t) //若第二个子序列没处理完,则进行收尾处理
32
32
分解问题
31
31
31
31
求解每个子问题Байду номын сангаас
3
3
3
3
9
9
合并子问题的解
81
❖ 不是所有的分治法都比简单的蛮力法更有效。
2020/4/16
分治法
7/56
4.1.2 数字旋转方阵
问题:输出NN(1N10)数字旋转方阵。
1 20 19 18 17 16 2 21 32 31 30 15 3 22 33 36 29 14 4 23 34 35 28 13 5 24 25 26 27 12 6 7 8 9 10 11
2020/4/16
分治法
15/56
[ r1 … … ri-1 ] ri [ ri+1 … … rn ] 均≤ri 轴值 均≥ri 位于最终位置
❖归并排序按照记录在序列中的位置对序列进行划分, ❖快速排序按照记录的值对序列进行划分。
2020/4/16
分治法
16/56
以第一个记录作为轴值,对待排序序列进行划分的过程为: (1)初始化:取第一个记录作为基准,设置两个参数i,j;
将一个难以直接解决的大问题,划分成一些规模 较小的子问题,分别求解各个子问题,再合并子问 题的解得到原问题的解。
如果子问题的规模仍然不够小,可继续分解下去。
2020/4/16
分治法
3/56
分治法的求解过程:分-治-合
(1)划分:把规模为n的原问题划分为k个规模较 小的子问题,并尽量使这k个子问题的规模大致相同。
(2)求解子问题:各子问题的解法与原问题的解 法通常是相同的,可以用递归的方法求解各个子问题。
(3)合并:把各个子问题的解合并起来,分治算 法的有效性很大程度上依赖于合并的实现。
2020/4/16
分治法
4/56
启发式规则:
1. 平衡子问题:最好使子问题的规模大 致相同。 2. 独立子问题:各子问题之间相互独立。
分治法是最著名的算法设计技术。
4.1 概 述 4.2 排序问题中的分治法 4.3 组合问题中的分治法 4.4 几何问题中的分治法
2020/4/16
分治法
1/56
4.1 概 述
4.1.1 分治法的设计思想 4.1.2 数字旋转方阵
2020/4/16
分治法
2/56
4.1.1 分治法的设计思想
66的旋转方阵
2020/4/16
分治法
8/56
4.2 排序问题中的分治法
4.2.1 归并排序 4.2.2 快速排序
2020/4/16
分治法
9
4.3.1 归并排序
二路归并排序的分治策略是: (1)划分:将待排序序列r1, r2, …, rn划分为两个 长度相等的子序列r1, …, rn/2和rn/2+1, …, rn; (2)求解子问题:分别对这两个子序列进行排 序,得到两个有序子序列; (3)合并:将这两个有序子序列合并成一个有 序序列。
2020/4/16
分治法
5/56
分治法的典型情况
原问题 的规模是n
子问题1 的规模是n/2
子问题1的解
子问题2 的规模是n/2
子问题2的解
原问题的解
2020/4/16
分治法
6/56
例:计算an,应用分治技术得到如下计算方法:
分析时 间性能
an
a
=
a
n
2
a n 2
34
如果 n = 1 如果 n > 1
r[i]=r1[i];
}
}
2020/4/16
分治法
12/56
二路归并排序的合并步的时间复杂性为O(n), 所以,二路归并排序算法存在如下递推式:
T (n)
=
1
2T
(n
2)
+n
n =1 n >1
可得二路归并排序的时间代价是O(nlog2n)。
二路归并排序在合并过程中需要与原始记录序列同 样数量的存储空间,因此其空间复杂性为O(n)。
算法4.3——归并排序
void MergeSort(int r[ ], int s, int t)
{ int m, r1[1000]; if (s= =t) return;
else { m=(s+t)/2; Mergesort(r, s, m); //归并排序前半个子序列 Mergesort(r, m+1, t); //归并排序后半个子序列 Merge(r, r1, s, m, t); //合并两个已排序的子序列 for (int i=s; i<=t; i++) //将有序序列传回数组r中
2020/4/16
分治法
10/56
r1 … … rn/2 rn/2+1 … … rn r‘1<… …<r’n/2 r’n/2+1<… …<r’n
划分 递归处理
r''1<……<r''n/2<r''n/2+1 <……<r ''n
合并解
举例:8 3 2 6 7 1 5 4
2020/4/16
分治法
11/56
r1[k++]=r[j++]; }
2020/4/16
分治法
14/56
4.3.2 快速排序
快速排序的分治策略是: (1)划分:选定一个记录作为轴值,以轴值为基准 将整个序列划分为两个子序列;
(2)求解子问题:分别对划分后的每一个子序列 递归处理; (3)合并:由于对子序列r1 … ri-1和ri+1 … rn的排序 是就地进行的,所以合并不需要执行任何操作。
2020/4/16
分治法
18
算法4.5——一次划分
int Partition(int r[ ], int first, int end)
(2)右侧扫描过程:
(3)左侧扫描过程:
(4)重复(2)(3)步,直到i与j指向同一位置,即基准记 录最终的位置。
2020/4/16
分治法
17
一次划分示例
38 27 55 50 13 49 65
i
jj
j
13 27 55 50 38 49 65
i
ii
j
13 27 38 50 55 49 65
ij j j
2020/4/16
分治法
13/56
算法4.4——合并有序子序列
void Merge(int r[ ], int r1[ ], int s, int m, int t) {
i=s; j=m+1; k=s; while (i<=m && j<=t) {
if (r[i]<=r[j]) r1[k++]=r[i++]; //取r[i]和r[j]中较小者放入r1[k] else r1[k++]=r[j++]; } if (i<=m) while (i<=m) //若第一个子序列没处理完,则进行收尾处理 r1[k++]=r[i++]; else while (j<=t) //若第二个子序列没处理完,则进行收尾处理
32
32
分解问题
31
31
31
31
求解每个子问题Байду номын сангаас
3
3
3
3
9
9
合并子问题的解
81
❖ 不是所有的分治法都比简单的蛮力法更有效。
2020/4/16
分治法
7/56
4.1.2 数字旋转方阵
问题:输出NN(1N10)数字旋转方阵。
1 20 19 18 17 16 2 21 32 31 30 15 3 22 33 36 29 14 4 23 34 35 28 13 5 24 25 26 27 12 6 7 8 9 10 11
2020/4/16
分治法
15/56
[ r1 … … ri-1 ] ri [ ri+1 … … rn ] 均≤ri 轴值 均≥ri 位于最终位置
❖归并排序按照记录在序列中的位置对序列进行划分, ❖快速排序按照记录的值对序列进行划分。
2020/4/16
分治法
16/56
以第一个记录作为轴值,对待排序序列进行划分的过程为: (1)初始化:取第一个记录作为基准,设置两个参数i,j;
将一个难以直接解决的大问题,划分成一些规模 较小的子问题,分别求解各个子问题,再合并子问 题的解得到原问题的解。
如果子问题的规模仍然不够小,可继续分解下去。
2020/4/16
分治法
3/56
分治法的求解过程:分-治-合
(1)划分:把规模为n的原问题划分为k个规模较 小的子问题,并尽量使这k个子问题的规模大致相同。
(2)求解子问题:各子问题的解法与原问题的解 法通常是相同的,可以用递归的方法求解各个子问题。
(3)合并:把各个子问题的解合并起来,分治算 法的有效性很大程度上依赖于合并的实现。
2020/4/16
分治法
4/56
启发式规则:
1. 平衡子问题:最好使子问题的规模大 致相同。 2. 独立子问题:各子问题之间相互独立。